合 Greenplum中的资源队列
- 用资源队列进行工作负载管理
- Greenplum数据库的内存使用概述
- Segment主机内存
- 配置Segment主机内存的选项
- 配置Greenplum数据库内存
- 用资源队列管理负载概述
- 资源队列实例
- 内存限制如何工作
- 优先权如何起作用
- 启用负载管理的步骤
- 配置负载管理
- 配置负载管理
- 创建资源队列
- 创建带有活动查询限制的队列
- 创建带有内存限制的队列
- 设置优先级
- 指派角色(用户)到资源队列
- 从资源队列移除角色
- 修改资源队列
- 修改资源队列
- 删除资源队列
- 检查资源队列状态
- 查看队列中的语句和资源队列状态
- 查看资源队列统计信息
- 查看指派到资源队列的角色
- 查看资源队列的等待查询
- 从资源队列清除等待语句
- 查看活动语句的优先权
- 重置活动语句的优先权
- 视图gp_resqueue_status
- SQL总结
- 总结
- 参考
用资源队列进行工作负载管理
使用Greenplum数据库的工作负载管理根据业务需求对查询按照优先级分配资源,并且在资源不可用时阻止查询开始。
这一节描述Greenplum数据库的负载管理,并且解释如何使用资源队列来管理资源。使用资源队列,可用的内存和CPU资源可以被分配给执行在Greenplum数据库系统上的不同类别的查询。用户可以限制并发查询的数量、执行一个查询所用到的内存量以及处理一个查询耗费的CPU相对量。
资源管理主要关注的是能并发执行的查询数量以及分配给每个查询的内存量。如果不限制并发度和内存使用,就不可能保证可接受的性能。内存是最有可能限制系统处理能力的资源。因此,我们从Greenplum数据库的内存使用概述开始。
Greenplum数据库的内存使用概述
内存是一个Greenplum数据库系统的关键资源,如果被有效使用,就能确保高性能和高吞吐。这一主题描述Segment主机的内存如何在Segment之间分配以及管理员可以用来配置内存的选项。
一台Greenplum数据库的Segment主机运行多个PostgreSQL实例,它们都共享该主机的内存。这些Segment拥有相同的配置,并且在并行处理查询时它们同时消耗相似的内存量、CPU和磁盘I/O。
为了最好的查询吞吐,内存配置应该被仔细地管理。在Greenplum数据库的每个层次都有内存配置选项,从操作系统参数到用资源队列管理负载,再到设置分配给个别查询的内存量。
Segment主机内存
在一台Greenplum数据库的Segment主机上,可用的主机内存被执行在该计算机上的所有进程共享,包括操作系统、Greenplum数据库的Segment实例以及其他应用进程。管理员必须决定Greenplum数据库进程和非Greenplum数据库进程怎样共享主机的内存,并且配置系统有效地使用内存。定期监控内存使用同样重要,这样可以检测Greenplum数据库或其他进程消耗主机内存的方式变化。下面的图展示了在一台Greenplum数据库的Segment主机上内存如何被消耗。图 1. Greenplum数据库的Segment主机内存
从该图示的底部开始,标有A的线表示总的主机内存。在上方紧挨着线A的线显示总的主机内存由物理RAM和交换空间构成。
标有B的线显示可用的总内存必须被Greenplum数据库和主机上的所有其他进程共享。非Greenplum数据库进程包括操作系统和任意其他应用,例如系统监控代理。一些应用可能会使用相当大一部分内存,结果用户可能不得不调整每台Greenplum数据库主机上的Segment数量或者每个Segment的内存量。
Segment(C)每个都会得到等份的Greenplum数据库内存(B)。
在一个Segment中,资源队列管理着如何分配内存以执行一个SQL语句。资源队列要求用户把业务需求翻译成Greenplum数据库系统的执行策略,并且警惕可能降低性能的查询。
有非管理用户提交给Greenplum数据库系统的每一个语句都与一个资源队列相关联。该队列决定该语句是否将被允许执行,并且在资源可用时允许它执行。该语句可能被拒绝、立即执行或者被放入队列在资源可用时执行。
用户可以为不同类型的查询创建资源队列,并且为每个队列保留固定大小的Segment内存。另外一种选择是,用户可以设置一个服务器配置参数来指定为每个内存分配多少内存并且在资源队列上不加最大内存限制。
查询优化器产生一个查询执行计划,它由一系列被称为操作符(图中标为D)的任务构成。操作符执行诸如表扫描或连接之类的任务,并且一般会通过处理一个或者多个输入行集合产生中间查询结果。操作符接收一份资源队列分配给查询的内存。如果一个操作符无法在分配给它的内存中执行它所有的工作,它会把数据缓冲在磁盘上的溢出文件中。
配置Segment主机内存的选项
主机内存是该Segment主机上所有应用共享的总内存。主机内存量可以用下列任一方法配置:
- 对节点增加更多RAM来增加物理内存。
- 分配交换空间来增加虚拟内存的尺寸。
- 设置内核参数vm.overcommit_memory和vm.overcommit_ratio来配置操作系统如何处理大型内存分配请求。
物理RAM和OS配置通常由平台团队和系统管理员管理。推荐的内核设置请见Greenplum数据库安装指南。
为操作系统和其他进程保留的内存量是与负载相关的。操作系统内存的最小推荐是32GB,但如果Greenplum数据库中很多并发,将保留内存增加到64GB可能是必须的。操作系统内存的最大用户是SLAB,它会随着Greenplum数据库并发和使用的端口数增加而增加。
vm.overcommit_memory内核参数应该总是被设置为2,这是对Greenplum数据库唯一的安全值。
vm.overcommit_ratio内核参数设置为应用进程使用的RAM百分数,剩下的保留给操作系统。Red Hat的默认值是50(50%)。将这个参数设置得过高可能会导致为操作系统保留的内存不足,这会导致Segment主机失效或者数据库失效。将这个设置保持在50的默认值通常是安全的,但有些保守。将这个值设置的太低会降低Greenplum数据库可用的内存量,进而降低并发量同时可以运行的查询的复杂度。在增加vm.overcommit_ratio时,重要的是记住总是为操作系统活动保留一些内存。要为vm.overcommit_ratio计算一个安全的值,首先用下面的公式确定Greenplum数据库进程可用的总内存(称为gp_vmem):
1 | gp_vmem = ((SWAP + RAM) – (7.5GB + 0.05 * RAM)) / 1.7 |
其中SWAP是主机上的交换空间(以GB为单位),而RAM是安装在主机上的RAM的GB数。用这个公式计算vm.overcommit_ratio:
1 | vm.overcommit_ratio = (RAM - 0.026 * gp_vmem) / RAM |
配置Greenplum数据库内存
Greenplum数据库内存是可用于所有Greenplum数据库的Segment实例的内存量。
在设置Greenplum数据库集群时,用户决定每台主机运行的主Segment数量以及为每个Segment分配的内存量。根据CPU核数、物理RAM的量以及负载特点,Segment的数量通常是介于4和8之间的值。如果启用了Segment镜像,为失效时执行在一台主机上的最大数量的主Segment分配内存很重要。例如,如果用户使用默认的组镜像配置,一个Segment主机失效会让拥有失效主机镜像的主机上的活动主Segment数量翻倍。将每台主机的镜像散布在多台其他主机上的镜像配置可以降低这个最大值,允许为每个Segment分配更多内存。例如,如果用户使用一种块镜像配置,其中每块有4台主机且每台主机上有8个主Segment,单个主机失效将会导致块中其他主机有11个活动主Segment这一最大值,这比默认的组镜像配置的16个要少。
gp_vmem_protect_limit值是为每个Segment分配的内存量。它通过计算所有Greenplum数据库进程可用的内存并且除以失效时主Segment的最大数量得到。如果gp_vmem_protect_limit被设置得过高,查询可能会失败。使用下面的公式为gp_vmem_protect_limit计算一个安全值。使用这个公式计算gp_vmem(所有Greenplum数据库进程可用的内存):
1 | gp_vmem = ((SWAP + RAM) – (7.5GB + 0.05 * RAM)) / 1.7 |
其中 其中SWAP是主机上的交换空间(以GB为单位),而RAM是安装在主机上的RAM的GB数。使用这个公式计算gp_vmem_protect_limit:
1 | gp_vmem_protect_limit = gp_vmem / max_acting_primary_segments |
其中max_acting_primary_segments是镜像Segment由于主机或Segment失效而被激活时可能运行在一台主机上的主Segment的最大数量。另一项重要的Greenplum数据库服务器配置参数是statement_mem。这个参数设置分配来执行查询的最大内存量。要为这个参数确定值,用每个Segment的内存量(gp_vmem_protect_limit)减去一个10%的安全量,然后除以期望并发执行的最大查询数量。默认的Greenplum书库资源队列允许最多20个并发查询。这里有一个公式计算statement_mem:
1 | (gp_vmem_protect_limit * .9 ) / max_expected_concurrent_queries |
资源队列允许对分配给查询的内存量进行更多控制。
用资源队列管理负载概述
资源队列是Greenplum数据库系统中管理并发程度的主要工具。资源队列是使用SQL语句CREATE RESOURCE QUEUE创建的数据库对象。用户可以使用它们来管理可以并发执行的活动查询的数量、每种查询分配的内存量和查询的相对优先级。资源队列也防止查询消耗过多资源并且降低总体系统性能。
每个数据库都关联着一个单一资源队列,多个角色可以共享同一个资源队列。使用CREATE ROLE or ALTER ROLE语句的RESOURCE QUEUE短语可将角色分派到资源队列。如果没有指定资源队列,角色将与默认资源队列pg_default关联。
当用户提交一个查询执行时,会根据资源队列的限制评估查询。如果该查询不会导致队列超过它的资源限制,那么该查询将被立即运行。如果该查询导致队列超过其限制(例如,如果当前正在使用的活动语句槽已达最大数量),那么查询必须等待直到队列资源被释放出来才能运行。采用先进先出的方式评估查询。如果启用了查询优先,系统上的活动负载会被定期访问并且处理资源会被根据查询优先度重新分配。带有SUPERUSER属性的角色会被免除资源队列限制。超级用户查询总是被立即运行,而不管它们所属资源队列上的限制。图 2. 资源队列处理
资源队列定义了具有类似资源需求的查询的分类。管理员应该为其组织中各种类型的查询创建资源队列。例如,用户可能会为下列分类的查询创建资源队列,它们对应于不同的服务水平协议:
- ETL查询
- 报表查询
- 行政查询
资源队列的设置有4个维度:
1 ACTIVE_STATEMENTS
2 PRIORITY
3 Memory_limit
4 min_cost、max_cost
资源队列有下列特性:MEMORY_LIMIT该队列(每个Segment)中所有查询使用的内存量。例如,在ETL队列上把MEMORY_LIMIT设置为2GB允许ETL查询在每个Segment上使用最多2GB内存。ACTIVE_STATEMENTS一个队列的槽数量,队列的最大并发度水平。当所有的槽都被使用时,新查询必须等待。默认每个查询都使用等量的内存。例如,pg_default资源队列有 ACTIVE_STATEMENTS = 20。PRIORITY查询的相对CPU使用。这可能是下列水平之一: LOW、MEDIUM、HIGH、 MAX。默认水平是MEDIUM。查询优先机制监控系统中运行的所有查询的CPU使用,并且为每个查询调整CPU使用来符合其优先级。例如,用户可以为行政资源队列设置MAX优先权,并为其他队列设置MEDIUM以确保行政查询会拿到更大份的CPU时间。MAX_COST查询计划代价限制.Greenplum数据库优化器为每个查询分配一个数字代价。如果该代价超过为该资源队列设置的MAX_COST值,该查询会因为太昂贵而被拒绝。注意: 使用MEMORY_LIMIT和ACTIVE_STATEMENTS来为资源队列设置限制,而不是使用MAX_COST。
Greenplum数据库系统的默认配置是有一个单一的默认资源队列,名为pg_default。pg_default资源队列的ACTIVE_STATEMENTS设置为20,没有MEMORY_LIMIT、中等PRIORITY并且没有设置MAX_COST。这意味着所有查询都会被接受并且立即以相同的优先级执行,没有内存限制,不过只能有20个查询并发执行。
一个资源队列允许的并发查询数量取决于是否设置MEMORY_LIMIT参数:
- 如果没有为资源队列设置MEMORY_LIMIT,每个查询分配的内存量是statement_mem服务器配置参数的值。该资源队列能使用的最大内存是statement_mem和ACTIVE_STATEMENTS的积。
- 当在资源队列上设置了一个MEMORY_LIMIT时,该队列能并发执行的查询数受限于该队列的可用内存。
一个被准许进入系统的查询会被分配一定量的内存并且会为它生成一个查询计划树。该树的每个节点是一个操作符,例如排序或者哈希连接。每个操作符是一个单独的执行线程并且被分配语句总体内存的一部分,最少100KB。如果计划有大量的操作符,操作符所要求的最小内存也可能超过可用内存并且查询将会被一个内存不足错误拒绝。操作符会判断它们是否能在分配的内存中完成其任务,或者它们是否必须把数据溢出到磁盘中的工作文件。分配和控制每个操作符所使用的内存量的机制被称为内存限额。
并非所有通过资源队列提交的SQL语句都会被按照队列限制进行评估。默认只有SELECT、SELECT INTO、CREATE TABLE AS SELECT和DECLARE CURSOR语句会被评估。如果服务器配置参数resource_select_only被设置为off,那么INSERT、UPDATE和DELETE语句也将被评估。
还有,在EXPLAIN ANALYZE命令执行期间被运行的SQL语句被排除在资源队列之外。
PRIORITY={MINLOW|MEDIUM|HIGH|MAX},指当前资源队列的优先级,当资源紧张时,优先将CPU资源分配给高优先级的资源队列。(处于高优先级的资源队列中的SQL,可以获得更高优先级的CPU资源)。建议将实时性要求高的查询对应的用户分配到高优先级的资源队列中。
gp_resqueue_priority ,是否使用资源队列的优先级。默认为ON,ON使用,OFF不使用。不使用资源队列优先级时,所有队列公平对待。
资源队列实例
默认的资源队列pg_default允许最多20个活动查询并且为它们分配等量的内存。这通常不能胜任生产系统的资源控制。为了确保系统符合性能预期,用户可以定义查询的分类并且把它们分派到最适合(并行度、内存、CPU资源)该类查询的资源队列。下面的图展示了一个Greenplum数据库系统的资源队列配置的例子,其中gp_vmem_protect_limit被设置为8GB:图 3. 资源队列配置实例
这个例子有三类具有不同特点和服务水平协议(SLA)的查询。为它们配置了三个资源队列。Segment内存的一部分被保留作为安全裕度。
资源队列名称 | 活动语句 | 内存限制 | 每个查询的内存 |
---|---|---|---|
ETL | 3 | 2GB | 667MB |
报表 | 7 | 3GB | 429MB |
行政 | 1 | 1.4GB | 1.4GB |
分配给队列的总内存是6.4GB或者gp_vmem_protect_limit服务器配置参数所定义的Segment总内存的80%。允许20%的安全裕度可以容纳某些操作符和查询,它们已知会使用比资源队列分配给它们的更多的内存。
关于命令语法帮助和详细参考信息请见Greenplum数据库参考指南中的CREATE RESOURCE QUEUE和CREATE/ALTER ROLE语句。
内存限制如何工作
一个资源队列上的MEMORY_LIMIT为一个Segment实例设置通过该队列提交的所有活动查询可以消耗的最大内存量。拨给一个查询的内存量是队列内存限制除以活动语句限制(将内存限制与基于语句的队列而不是基于代价的队列)。例如,如果一个队列的内存限制是2000MB而活动语句限制是10,每个通过该队列提交的查询会默认拿到200MB内存。可以以每个查询为基础使用statement_mem服务器配置参数覆盖默认的内存分配(最高到队列内存限制)。一旦一个查询开始执行,它会在队列中保持分拨给它的内存直至完成,即便在执行中它实际消耗的内存比分配到的内存少也是如此。
用户可以使用statement_mem服务器配置参数来覆盖当前资源队列设置的内存限制。在会话级别,用户可以增加statement_mem,最高到资源队列的MEMORY_LIMIT。这将允许个别查询使用分配给整个队列的所有内存而不影响其他资源队列。
statement_mem的值会被max_statement_mem配置参数(是一个超级用户参数)覆盖。对于一个设置有MEMORY_LIMIT的资源队列中的查询,statement_mem的最大值是min(MEMORY_LIMIT, max_statement_mem)。当一个查询被允许进入时,分配给它的内存会被从MEMORY_LIMIT中减去。如果MEMORY_LIMIT被耗尽,同一个资源队列中的新查询必须等待。即使ACTIVE_STATEMENTS还没有达到时也会发生这种事情。注意只有当statement_mem被用来覆盖资源队列分配的内存时才会发生这种情况。例如,考虑一个名为adhoc的队列,它有下列设置:
- MEMORY_LIMIT为1.5GB
- ACTIVE_STATEMENTS为3
默认每个被提交到队列的语句会被分配500MB内存。现在考虑下列一系列事件:
- 用户ADHOC_1提交查询Q1,并且把STATEMENT_MEM覆盖为800MB。Q1语句被准许进入系统。
- 用户ADHOC_2提交查询Q2,使用默认的500MB。
- 在Q1和Q2仍在运行时,用户ADHOC3提交查询Q3,使用默认的500MB。
查询Q1和Q2已经用掉了队列的1500MB中的1300MB。因此,Q3在能运行前必须等待Q1或者Q2完成。
如果在一个队列上没有设置MEMORY_LIMIT,查询都被准许进入,直到所有的ACTIVE_STATEMENTS槽被用尽,并且每个查询可以设置一个任意高的statement_mem。这可能导致资源队列使用无限量的内存。
优先权如何起作用
资源队列的PRIORITY设置与MEMORY_LIMIT和ACTIVE_STATEMENTS设置不同,后两者决定一个查询是否将被准许进入该队列并且最终被执行。PRIORITY设置对于活动查询适用。活动查询会按照其所在资源队列的优先权设置来共享可用的CPU资源。当一个来自高优先权队列的语句进入到活动运行语句分组中时,它可以得到可用CPU中较高的份额,同时也降低了具有较低优先权设置队列中已经在运行的语句得到的份额。
查询的相对尺寸或复杂度不影响CPU的分配。如果一个简单的低代价的查询与一个大型的复杂查询同时运行,并且它们的优先权设置相同,它们将被分配同等份额的可用CPU资源。当一个新的查询变成活动时,CPU份额将会被重新计算,但是优先权相等的查询仍将得到等量的CPU。例如,管理员创建三个资源队列:adhoc用于业务分析师提交的正在进行的查询,reporting用于计划的报表任务,而executive用于行政用户角色递交的查询。由于分析师可能临时提交查询,而这些查询的资源需求是不可预测的,管理员想要确保计划的报表任务不会受到这类查询的严重影响。还有,管理员想要确保行政角色递交的查询会被分配相当份额的CPU。相应地,资源队列的优先权被设置如下:
- adhoc — 低优先权
- reporting — 高优先权
- executive — 最大优先权
在运行时,活动语句的CPU份额由这些这些优先权设置决定。如果来自报表队列的查询1和2同时运行,它们有相等份额的CPU。当一个临时查询变成活动时,它会索取一个较小份额的CPU。报表查询所使用的准确份额会被调整,但仍然保持相等,因为它们的优先权设置相等:图 4. 根据优先权重新调整CPU份额
注意:
这些图中显示的百分数都是近似值。高、低和中优先权队列的CPU使用并不总是准确地用这些比例计算出来。
当一个行政查询进入到运行语句组中时,CPU使用会被调整以说明其最大优先权设置。它可能是一个堪比分析师和报表查询的简单查询,但直到它完成前,它都将要求最大份额的CPU。图 5. 为最大优先权查询重新调整CPU份额
启用负载管理的步骤
在Greenplum数据库中启用并且使用负载管理涉及下列高层任务:
配置负载管理
在安装Greenplum数据库时默认会启用资源调度,资源调度对所有角色都是必需的。默认的资源队列pg_default的活动语句限制是20、没有内存限制和中等的优先权设置。为各种类型的负载创建资源队列。
配置负载管理
下列参数用于资源队列的一般配置:
- max_resource_queues – 设置资源队列的最大数量。
- max_resource_portals_per_transaction – 设置每个事务允许同时打开的游标的最大数量。注意一个打开的游标将在资源队列中占有一个活动查询槽。
- resource_select_only – 如果被设置为on,那么SELECT、SELECT INTO、CREATE TABLE ASSELECT和DECLARE CURSOR命令会被评估。如果被设置为off,INSERT、UPDATE以及DELETE也将被评估。
- resource_cleanup_gangs_on_wait – 在资源队列中取得一个槽之前清除空转的Segment工作者进程。
- stats_queue_level – 在资源队列使用上启用统计信息收集,然后可以通过查询pg_stat_resqueues系统视图来查看收集到的信息。
下列参数与内存利用有关:
gp_resqueue_memory_policy – 启用Greenplum数据库的内存管理特性。在Greenplum数据库4.2和其后的版本中,分布算法eager_free会利用并非所有操作符都会同时执行这一事实。查询计划被划分成阶段并且Greenplum数据库会饥渴地在上一阶段执行结束时释放分配给上一阶段的内存,然后将释放出来的内存饥渴地分配给新的阶段。当被设置为none时,内存管理与4.1之前Greenplum数据库发行版相同。当被设置为auto时,查询内存使用由statement_mem和资源队列内存限制所控制。
内存使用配置方式:资源队列配置参考
GP的内存配置有两种方式,由参数gp_resqueue_memory_policy的两个选项(eager_free、auto)决定。
1 eager_free
此时内存的消耗由 max_statement_mem 和 资源队列的memory_limit两个参数决定。
如果当前用户不是普通用户或没有设置资源队列的memory_limit,那么内存的消耗只受max_statement_mem这个数值限定,该数值默认为2000mb。
2 auto
此时内存的消耗由 statement_mem 和 资源队列的memory_limit两个参数决定。
同样资源队列的memory_limit只对普通用户有效,而statement_mem默认值为125mb。
statement_mem和max_statement_mem – 被用来在运行时给一个特定查询分配内存(覆盖资源队列指派的默认分配)。max_statement_mem被数据库超级用户设置以防止常规数据库用户过度分配。
gp_vmem_protect_limit – 设置所有查询处理能消耗的上界并且不应超过Segment主机的物理内存量。当一台Segment主机在查询执行时达到这一限制,导致超过限制的查询将被取消。
gp_vmem_idle_resource_timeout和gp_vmem_protect_segworker_cache_limit – 被用来释放Segment主机上由闲置数据库进程持有的内存。管理员可能想要在有大量并发的系统上调整这些设置。
shared_buffers – 设置Greenplum服务器实例用作共享内存缓冲区的内存量。这个设置必须至少为128千字节并且至少为16千字节乘以max_connections。该值不能超过操作系统共享内存最大分配请求尺寸,该尺寸由Linux上的shmmax控制。推荐的OS内存设置请见Greenplum数据库安装指南。
本人提供Oracle(OCP、OCM)、MySQL(OCP)、PostgreSQL(PGCA、PGCE、PGCM)等数据库的培训和考证业务,私聊QQ646634621或微信dbaup66,谢谢!