简介:作者:阿里云数据库OLAP产品部 - 子华
一 背景
AnalyticDB PostgreSQL版(简称ADB PG)是阿里云数据库团队基于PostgreSQL内核(简称PG)打造的一款云原生数据仓库产品。在数据实时交互式分析、HTAP、ETL、BI报表生成等业务场景,ADB PG都有着独特的技术优势,在金融、物流、泛互联网等行业都有广泛的应用,是传统数仓上云、去O去T、替换自建Greenplum的标杆云上数据仓库产品。
数据仓库产品是数据分析系统的重要组件之一,各类线上业务对数据仓库产品的稳定性、可用性具有很高的要求。缺乏有效的资源管理机制会导致数据库产品的稳定性下降,发生例如连接数打满OS限制、内存不足、进程卡死等问题,从而影响产品的可用性。
Resource Queue(资源队列)是ADB PG的一种资源管理方式,能够对数据库的CPU、内存等资源进行限制,对多租户资源限制、保障数据库稳定运行具有一定的作用。顾名思义,Resource Queue以队列形式对运行在数据库集群上的SQL进行资源管理。对于每个用户,他的所有连接只能归属于一个队列。而对于每个队列能够管理多个用户的连接。没有显示指定资源队列的用户,会归属于默认资源队列管理。通过限制每个队列的资源总量,我们可以达到限制某类业务或者某个用户使用的资源总量的目的。
我们以ADB PG某在线交易平台类客户A为例,介绍Resource Queue的使用。客户A基于ADB PG构建数据仓库,日常运行三类业务:以交易数据入库为代表的实时类业务;用于支撑决策分析的报表类业务;以及用于实时大屏展示的可视化类业务。我们根据三类业务的不同特点,按如下策略配置资源队列。
客户A的实时类业务的典型代表是,交易数据经Kafka->Flink->ADB PG链路实时写入ADB PG。这类业务的典型特点是,峰值并发比较大,单个SQL资源消耗小。在进行资源队列限制前,业务高峰期经常发生突然提高的并发查询打满数据库连接,造成高可用探活查询执行失败,引发实例不可用。对于这类业务我们将其关联到一个高CPU权重、大并发限制(安全阈值内)、单个SQL内存份额低的队列。既保证数据的快速入库,又防止流量洪峰造成系统不稳定。
客户A的另一类典型业务是报表类、ETL类业务,这类业务会在实时类业务的低峰期进行调度,生成报表以提供决策支持。这类业务涉及的数据量较大,消耗内存量和产生的临时文件量大。对于这类业务,我们将其关联到低CPU权重、低并发限制,但是内存份额高的队列,在满足业务需要的同时,控制内存使用上限;
除此之外,客户还基于ADB PG数据仓库支持数据的实时可视化展示,这类可视化方案往往具有非常稳定的并发,但是对查询的延时具有一定的要求。对于这类业务,我们将其资源队列设定为高CPU权重,低并发限制,以及宽泛的优化器查询计划消耗份额,最大程度为其生成良好的查询计划,以保证业务稳定。
接下来,本文会具体介绍Resource Queue的使用方式、状态监控,以及它的实现机制。
二 Resource Queue简介
Resource Queue支持通过SQL配置,支持进行四种类型的资源限制:并发限制、CPU限制、内存限制和查询计划限制。用户可以通过SQL在数据库内定义多个资源队列,并设置每个资源队列的资源限制。在一个数据库中,每个资源队列可以关联一个或多个数据库用户,而每个数据库用户只能归属于单个资源队列。
另外,并不是所有提交到资源队列的SQL都会受到队列限制的限制,数据库只会限制SELECT、SELECT INTO、CREATE TABLE AS SELECT、DECLARE CURSOR、INSERT、UPDATE 和DELETE这些类型SQL的资源利用。另外,在执行EXPLAIN ANALYZE命令期跑的SQL也会被资源队列排除。
资源队列支持的资源限制配置如下:
配置名 | 配置说明 |
MEMORY_LIMIT | 队列中所有查询所使用的内存总量。 |
ACTIVE_STATEMENTS | 队列中允许同时运行的查询数。超出该设置值的查询需要排队等待执行。 |
PRIORITY | 队列的CPU使用优先级,可以设置为以下级别:LOW、MEDIUM、HIGH 和MAX。默认值为MEDIUM,优先级越高的队列会被分配越高的CPU份额。 |
MAX_COST | 查询计划消耗限制。 |
`
CREATE RESOURCE QUEUE etl WITH (ACTIVE_STATEMENTS=3,
MEMORY_LIMIT='1GB', PRIORITY=LOW, MAX_COST=-1.0);
`
ACTIVE\_STATEMENTS:
队列中允许同时运行的查询数,即队列中允许并发查询的最大并发值。数据库允许超出ACTIVE\_STATEMENTS数目、但是少于数据库最大连接数MAX\_CONNECTIONS数目的链接连接到数据库,但是这部分SQL连接并不会立刻开始运行,而是排队等待。
MAX\_COST:
查询计划Cost限制。数据库优化器会为每个查询计算Cost,如果该Cost总量超过了资源队列所设定的的MAX\_COST的值,该查询就会被拒绝。ADB PG的默认配置为0,即不受限制。
Memory Limit:
ADB PG可以通过设置statement\_mem来决定每条SQL在每个Segment上使用的内存上限。Memory Limit既没有默认值,也可以不指定。在MEMORY\_LIMIT参数没有被配置时,一个资源队列中的一条SQL所允许的内存大小,由statement\_mem参数决定:
* 如果一个资源队列没有设置MEMORY\_LIMIT的话,每个资源所分配到的内存大小就是statement\_mem的服务器配置参数,一个资源队列的可用内存大小是根据statement\_mem和ACTIVE\_STATEMENTS的计算结果。
* 当资源队列有设置MEMORY\_LIMIT时,单个SQL所使用的内存量会由队列中的平均分配值(MEMORY\_LIMIT/ACTIVE\_STATEMENTS)和statement\_mem中的最大值决定,具体计算方式可以参考后面实现章节。
资源队列中可以并行执行的查询数会受到该队列的可用内存限制。举个例子:对于队列etl,设置STATEMENTS=3, MEMORY\_LIMIT=2.1G;那么在没有设置statement\_mem的情况下,每个查询默认使用内存700MB。
SQL1进入队列,使用内存700MB,此时队列剩余内存1.4G;
SQL2进入队列,设置statement\_mem为1.0GB,此时队列剩余内存为0.4GB;
此时,队列剩余内存无法满足SQL3的内存使用需求(默认700GB),那么虽然队列中并行查询数没有达到队列限制,SQL3依然无法执行,需要排队等待。
PRIORITY:
数据库运行的SQL会按照其所在资源队列的优先权设置来共享可用的CPU资源。当一个来自高优先权队列的语句进入到活动运行语句分组中时,它可以得到可用CPU中较高的份额,同时也会降低具有较低优先权设置队列中已经在运行的语句得到的份额。
查询的相对尺寸或复杂度不影响CPU的分配。如果一个简单的低代价的查询与一个大型的复杂查询同时运行,并且它们的优先权设置相同,它们将被分配同等份额的可用CPU资源。当一个新的查询变成活动时,CPU份额将会被重新计算,但是优先权相等的查询仍将得到等量的CPU。
例如,管理员创建三个资源队列:streaming、etl、prod,并相应地配置为以下优先权:
* streaming — 低优先权
* etl— 高优先权
* prod — 最大优先权
当数据库中只有etl队列中有查询1和2同时运行时,它们有相等份额的CPU,因为它们的优先权设置相等:
`
CREATE RESOURCE QUEUE etl WITH (ACTIVE_STATEMENTS=3);
`
这意味着对于所有被分配到etl资源队列的角色,在任意给定时刻只能有三个活动查询被运行在这个系统上。如果这个队列已经有三个查询在运行并且一个角色在该队列中提交第四个查询,则第四个查询只有等到一个槽被释放出来后才能运行。
###
### 创建带有内存限制的队列
带有MEMORY\_LIMIT设置的资源队列控制所有通过该队列提交的查询的总内存。在与ACTIVE\_STATEMENTS联合使用时,每个查询被分配的默认内存量为:MEMORY\_LIMIT /ACTIVE\_STATEMENTS。
例如,要创建一个活动查询限制为10且总内存限制为2000MB的资源队列(每个查询将在执行时被分配200MB的Segment主机内存):
`
CREATE RESOURCE QUEUE etl WITH (ACTIVE_STATEMENTS=10,
MEMORY_LIMIT='2000MB');
`
另外gp\_vmem\_protect\_limit参数会限制一个Segment上分配的内存总大小。该参数的优先级更高,如果这个参数超标,查询可能会被取消。
###
### 设置优先级
为了控制一个资源队列对可用CPU资源的消耗,用户可以指派一个合适的优先级。
`
ALTER RESOURCE QUEUE etl WITH (PRIORITY=LOW);
ALTER RESOURCE QUEUE etl WITH (PRIORITY=MAX);
`
## 3.2 指派角色(用户)到资源队列
一旦创建了一个资源队列,用户必须把角色(用户)指派到它们合适的资源队列。如果没有显式地把角色指派给资源队列,它们将进入默认资源队列pg\_default。
使用ALTER ROLE或者CREATE ROLE命令来指派角色到资源队列。例如:
`
ALTER ROLE name RESOURCE QUEUE queue_name;
CREATE ROLE name WITH LOGIN RESOURCE QUEUE queue_name;
`
### 从资源队列移除角色
所有用户都必须被指派到资源队列。如果没有被显式指派到一个特定队列,用户将会进入到默认的资源队列pg\_default。如果用户想要从一个资源队列移除一个角色并且把它们放在默认队列中,可以将该角色的队列指派改成none。例如:
`
ALTER ROLE role_name RESOURCE QUEUE none;
`
## 3.3 修改资源队列
在资源队列被创建后,用户可以使用ALTER RESOURCE QUEUE命令更改队列限制,或使用DROP RESOURCE QUEUE命令移除一个资源队列。
### 修改资源队列配置
ALTER RESOURCE QUEUE命令更改资源队列的限制。要更改一个资源队列的限制,可以为该队列指定想要的新值。例如:
`
ALTER RESOURCE QUEUE etl WITH (ACTIVE_STATEMENTS=5);
ALTER RESOURCE QUEUE etl WITH (PRIORITY=MAX);
`
### 删除资源队列
DROP RESOURCE QUEUE命令可以删除资源队列。要删除一个资源队列,该队列不能有指派给它的角色,也不能有任何语句在其中等待。
`
DROP RESOURCE QUEUE etl;
`
# 四 Resource Queue状态监控
##
## 4.1 查看队列中的语句和资源队列状态
gp\_toolkit.gp\_resqueue\_status视图允许用户查看一个负载管理资源队列的状态和活动。对于一个特定资源队列,它展示有多少查询在等待运行以及系统中当前有多少查询是活动的。要查看系统中创建的资源队列、它们的限制属性和当前状态:
`
SELECT * FROM gp_toolkit.gp_resqueue_status;
`
`
SELECT * FROM pg_stat_resqueues;
`
## 4.3 查看指派到资源队列的角色
要查看指派给资源队列的角色,执行下列在pg\_roles和gp\_toolkit.gp\_resqueue\_status系统目录表上的查询:
`
SELECT rolname, rsqname FROM pg_roles, gp_toolkit.gp_resqueue_status
WHERE pg_roles.rolresqueue=gp_toolkit.gp_resqueue_status.queueid;
`
## 4.4 查看资源队列的等待查询
用户可以看到所有资源队列的所有当前活跃的以及在等待的查询:
`
SELECT * FROM gp_toolkit.gp_locks_on_resqueue WHERE
lorwaiting='true';
`
如果这个查询不返回结果,那就意味着当前没有语句在资源队列中等待。
## 4.5 查看活动语句的优先权
查看当前正在被执行的语句并且提供优先权、会话ID和其他信息:
`
SELECT * FROM gp_toolkit.gp_resq_priority_statement;
`
## 4.6 重置活动语句的优先权
用户可以使用函数gp\_adjust\_priority(session\_id,statement\_count,priority)调整当前正在被执行的语句的优先权。使用这个函数,用户可以提升或者降低任意查询的优先权。例如:
`
SELECT gp_adjust_priority(12, 10000, 'LOW');
`
在这个函数的参数中,session\_id代表会话id, statement\_count代表要调整的SQL在session中的序号,priority是待调整的优先级。可以通过gp\_resq\_priority\_statement视图查询现有语句的上述信息。
`
select * from gp_toolkit.gp_resq_priority_statement;
`
# 五 Resource Queue实现
ADB PG数据库是MPP架构,整体分为一个或多个Master,以及多个segment,数据在多个segment之间可以随机、哈希、复制分布。在ADB PG中,Resource Queue的资源限制级别是语句级别,即在整条SQL执行的任何时刻,不管是否处于事务中,均会受到资源队列的限制。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。