用资源队列进行工作负载管理

用资源队列进行工作负载管理

使用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_memoryvm.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):
gp_vmem = ((SWAP + RAM) – (7.5GB + 0.05 * RAM)) / 1.7

其中SWAP是主机上的交换空间(以GB为单位),而RAM是安装在主机上的RAM的GB数。

用这个公式计算vm.overcommit_ratio
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数据库进程可用的内存):
gp_vmem = ((SWAP + RAM) – (7.5GB + 0.05 * RAM)) / 1.7
其中 其中SWAP是主机上的交换空间(以GB为单位),而RAM是安装在主机上的RAM的GB数。
使用这个公式计算gp_vmem_protect_limit
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
(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查询
  • 报表查询
  • 行政查询
资源队列有下列特性:
MEMORY_LIMIT
该队列(每个Segment)中所有查询使用的内存量。例如,在ETL队列上把MEMORY_LIMIT设置为2GB允许ETL查询在每个Segment上使用最多2GB内存。
ACTIVE_STATEMENTS
一个队列的数量,队列的最大并发度水平。当所有的槽都被使用时,新查询必须等待。默认每个查询都使用等量的内存。
例如,pg_default资源队列有 ACTIVE_STATEMENTS = 20。
PRIORITY
查询的相对CPU使用。这可能是下列水平之一: LOWMEDIUMHIGHMAX。默认水平是MEDIUM。查询优先机制监控系统中运行的所有查询的CPU使用,并且为每个查询调整CPU使用来符合其优先级。例如,用户可以为行政资源队列设置MAX优先权,并为其他队列设置MEDIUM以确保行政查询会拿到更大份的CPU时间。
MAX_COST
查询计划代价限制.
Greenplum数据库优化器为每个查询分配一个数字代价。如果该代价超过为该资源队列设置的MAX_COST值,该查询会因为太昂贵而被拒绝。
注意: 使用MEMORY_LIMITACTIVE_STATEMENTS来为资源队列设置限制,而不是使用MAX_COST

Greenplum数据库系统的默认配置是有一个单一的默认资源队列,名为pg_defaultpg_default资源队列的ACTIVE_STATEMENTS设置为20,没有MEMORY_LIMIT、中等PRIORITY并且没有设置MAX_COST。这意味着所有查询都会被接受并且立即以相同的优先级执行,没有内存限制,不过只能有20个查询并发执行。

一个资源队列允许的并发查询数量取决于是否设置MEMORY_LIMIT参数:

  • 如果没有为资源队列设置MEMORY_LIMIT,每个查询分配的内存量是statement_mem服务器配置参数的值。该资源队列能使用的最大内存是statement_memACTIVE_STATEMENTS的积。
  • 当在资源队列上设置了一个MEMORY_LIMIT时,该队列能并发执行的查询数受限于该队列的可用内存。

一个被准许进入系统的查询会被分配一定量的内存并且会为它生成一个查询计划树。该树的每个节点是一个操作符,例如排序或者哈希连接。每个操作符是一个单独的执行线程并且被分配语句总体内存的一部分,最少100KB。如果计划有大量的操作符,操作符所要求的最小内存也可能超过可用内存并且查询将会被一个内存不足错误拒绝。操作符会判断它们是否能在分配的内存中完成其任务,或者它们是否必须把数据溢出到磁盘中的工作文件。分配和控制每个操作符所使用的内存量的机制被称为内存限额

并非所有通过资源队列提交的SQL语句都会被按照队列限制进行评估。默认只有SELECTSELECT INTOCREATE TABLE AS SELECTDECLARE CURSOR语句会被评估。如果服务器配置参数resource_select_only被设置为off,那么INSERTUPDATEDELETE语句也将被评估。

还有,在EXPLAIN ANALYZE命令执行期间被运行的SQL语句被排除在资源队列之外。

资源队列实例

默认的资源队列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 QUEUECREATE/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内存。现在考虑下列一系列事件:
  1. 用户ADHOC_1提交查询Q1,并且把STATEMENT_MEM覆盖为800MB。Q1语句被准许进入系统。
  2. 用户ADHOC_2提交查询Q2,使用默认的500MB。
  3. Q1Q2仍在运行时,用户ADHOC3提交查询Q3,使用默认的500MB。

查询Q1Q2已经用掉了队列的1500MB中的1300MB。因此,Q3在能运行前必须等待Q1或者Q2完成。

如果在一个队列上没有设置MEMORY_LIMIT,查询都被准许进入,直到所有的ACTIVE_STATEMENTS槽被用尽,并且每个查询可以设置一个任意高的statement_mem。这可能导致资源队列使用无限量的内存。

更多有关在资源队列上配置内存限制以及其他内存利用控制的信息,请见创建带内存限制的队列

优先权如何起作用

资源队列的PRIORITY设置与MEMORY_LIMITACTIVE_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数据库中启用并且使用负载管理涉及下列高层任务:

  1. 配置负载管理,见配置负载管理
  2. 创建资源队列并且在其上设置限制。见创建资源队列修改资源队列
  3. 把队列分派给一个或者更多用户角色。见将角色(用户)指派给资源队列
  4. 使用负载管理系统视图来监控并且管理资源队列。见检查资源队列状态.

配置负载管理

在安装Greenplum数据库时默认会启用资源调度,资源调度对所有角色都是必需的。默认的资源队列pg_default的活动语句限制是20、没有内存限制和中等的优先权设置。为各种类型的负载创建资源队列。

配置负载管理

  1. 下列参数用于资源队列的一般配置:
    • max_resource_queues - 设置资源队列的最大数量。
    • max_resource_portals_per_transaction - 设置每个事务允许同时打开的游标的最大数量。注意一个打开的游标将在资源队列中占有一个活动查询槽。
    • resource_select_only - 如果被设置为on,那么SELECTSELECT INTOCREATE TABLE ASSELECTDECLARE CURSOR命令会被评估。如果被设置为offINSERTUPDATE以及DELETE也将被评估。
    • resource_cleanup_gangs_on_wait - 在资源队列中取得一个槽之前清除空转的Segment工作者进程。
    • stats_queue_level - 在资源队列使用上启用统计信息收集,然后可以通过查询pg_stat_resqueues系统视图来查看收集到的信息。
  2. 下列参数与内存利用有关:
    • gp_resqueue_memory_policy - 启用Greenplum数据库的内存管理特性。

      在Greenplum数据库4.2和其后的版本中,分布算法eager_free会利用并非所有操作符都会同时执行这一事实。查询计划被划分成阶段并且Greenplum数据库会饥渴地在上一阶段执行结束时释放分配给上一阶段的内存,然后将释放出来的内存饥渴地分配给新的阶段。

      当被设置为none时,内存管理与4.1之前Greenplum数据库发行版相同。当被设置为auto时,查询内存使用由statement_mem和资源队列内存限制所控制。

    • statement_memmax_statement_mem - 被用来在运行时给一个特定查询分配内存(覆盖资源队列指派的默认分配)。max_statement_mem被数据库超级用户设置以防止常规数据库用户过度分配。
    • gp_vmem_protect_limit - 设置所有查询处理能消耗的上界并且不应超过Segment主机的物理内存量。当一台Segment主机在查询执行时达到这一限制,导致超过限制的查询将被取消。
    • gp_vmem_idle_resource_timeoutgp_vmem_protect_segworker_cache_limit - 被用来释放Segment主机上由闲置数据库进程持有的内存。管理员可能想要在有大量并发的系统上调整这些设置。
    • shared_buffers - 设置Greenplum服务器实例用作共享内存缓冲区的内存量。这个设置必须至少为128千字节并且至少为16千字节乘以max_connections。该值不能超过操作系统共享内存最大分配请求尺寸,该尺寸由Linux上的shmmax控制。推荐的OS内存设置请见Greenplum数据库安装指南
  3. 下列参数与查询优先有关。注意下列参数都是本地参数,意味着它们必须在Master和所有Segment的postgresql.conf文件中设置:
    • gp_resqueue_priority - 查询优先特性默认被启用。
    • gp_resqueue_priority_sweeper_interval - 设置所有活动语句重新计算CPU使用的时间间隔。这个参数的默认值应该足够用于通常的数据库操作。
    • gp_resqueue_priority_cpucores_per_segment - 指定每个Segment实例分配的CPU核数。Master和Segment的默认值是4。对于Greenplum Data Computing Appliance Version 2,Segment的默认值是4而Master默认值是25。

      每台主机会在其自己的postgresql.conf文件中检查这个参数的值。这个参数也影响Master节点,在Master节点上它应该被设置为一个反映CPU核数更高比率的值。例如,在每台主机有10个CPU核以及4个Segment的集群上,用户可以为gp_resqueue_priority_cpucores_per_segment指定这些值:

      为Master和后备Master指定10。通常,在Master主机上只有Master实例。

      为Segment主机上的每个Segment实例指定2.5。

      如果参数值未被设置正确,要么是CPU可能不会被完全利用,要么是查询优先可能无法按照预期工作。例如,如果Greenplum数据库集群在Segment主机上每个CPU核低于一个Segment实例,确保要相应地调整这个值。

      实际的CPU核利用取决于Greenplum数据库并行化查询的能力以及执行查询要求的资源。

      注意:操作系统任何可用的CPU核都会被包括在CPU核数中。例如,虚拟CPU核会被包括在CPU核数中。

  4. 如果用户希望查看或者更改任何负载管理参数值,可以使用gpconfig工具。
  5. 例如,要查看一个特定参数的设置:
    $ gpconfig --show gp_vmem_protect_limit
    
  6. 例如,要在所有的Segment实例上设置一个值并且在Master上设置一个不同的值:
    $ gpconfig -c gp_resqueue_priority_cpucores_per_segment -v 2 -m 8
    
  7. 重启Greenplum数据库让配置更改生效:
    $ gpstop -r
    

创建资源队列

创建一个资源队列涉及到给它一个名称、设置一个活动查询限制并且可选地在该资源队列上设置一个查询优先权。使用CREATE RESOURCE QUEUE命令来创建新的资源队列。

创建带有活动查询限制的队列

Resource queues with an 带有ACTIVE_STATEMENTS设置的资源队列会限制指派给该队列的角色所执行的查询数量。例如,要创建一个名为adhoc且活动查询限制为3的资源队列:

=# CREATE RESOURCE QUEUE adhoc WITH (ACTIVE_STATEMENTS=3);

这意味着对于所有被分配到adhoc资源队列的角色,在任意给定时刻只能有三个活动查询被运行在这个系统上。如果这个队列已经有三个查询在运行并且一个角色在该队列中提交第四个查询,则第四个查询只有等到一个槽被释放出来后才能运行。

创建带有内存限制的队列

Resource queues with a 带有MEMORY_LIMIT设置的资源队列控制所有通过该队列提交的查询的总内存。总内存不应超过每个Segment可用的物理内存。以每个Segment为基础,设置MEMORY_LIMIT为90%的可用内存。例如,如果一台主机有48GB物理内存和6个Segment实例,那么每个Segment实例可用的内存是8GB。可以为单个队列按照0.90*8=7.2 GB来计算推荐的MEMORY_LIMIT。如果在系统上创建有多个队列,它们的总内存限制加起来也必须为7.2 GB。

在与ACTIVE_STATEMENTS联合使用时,每个查询被分配的默认内存量为:MEMORY_LIMIT / ACTIVE_STATEMENTS。在与MAX_COST联合使用时,每个查询被分配的默认内存量为:MEMORY_LIMIT * (query_cost / MAX_COST)。将MEMORY_LIMITACTIVE_STATEMENTS而不是与MAX_COST一起使用。

例如,要创建一个活动查询限制为10且总内存限制为2000MB的资源队列(每个查询将在执行时被分配200MB的Segment主机内存):

=# CREATE RESOURCE QUEUE myqueue WITH (ACTIVE_STATEMENTS=20, 
MEMORY_LIMIT='2000MB');

可以使用statement_mem服务器配置参数针对每个查询覆盖默认的内存分配,前提是没有超过MEMORY_LIMIT或者max_statement_mem。例如,要对一个特定查询分配更多内存:

=> SET statement_mem='2GB';
=> SELECT * FROM my_big_table WHERE column='value' ORDER BY id;
=> RESET statement_mem;

作为一种一般性的指导方针,对于所有资源队列的MEMORY_LIMIT不应超过一台Segment主机的物理内存量。如果负载在多个队列之间交错安排,超额分配一些内存可能是OK的,但要记住,如果执行期间Segment主机的内存限制(gp_vmem_protect_limit)被超过,查询可能会被取消。

设置优先级

为了控制一个资源队列对可用CPU资源的消耗,管理员可以指派一个合适的优先级。当高并发导致对CPU资源的竞争时,与较高优先权资源队列相关的查询和语句将会比较低优先权的查询和语句得到更大份额的可用CPU。

优先权设置使用命令CREATE RESOURCE QUEUEALTER RESOURCE QUEUEWITH参数创建或修改。例如,要为adhoc and reporting队列指定优先权设置,管理员会使用下列命令:

=# ALTER RESOURCE QUEUE adhoc WITH (PRIORITY=LOW);
=# ALTER RESOURCE QUEUE reporting WITH (PRIORITY=HIGH);

要以最大优先权创建executive队列,管理员可以使用下列命令:

=# CREATE RESOURCE QUEUE executive WITH (ACTIVE_STATEMENTS=3, PRIORITY=MAX);

当查询优先特性被启用时,如果没有显式地指派,默认会为资源队列给出一个MEDIUM优先权。更多有关运行时如何评估优先权设置的信息,请见优先权如何起作用

重要: 为了在活动查询负载上实施资源队列优先级,用户必须通过设置相关服务器配置参数来启用查询优先特性。请见配置负载管理

指派角色(用户)到资源队列

一旦创建了一个资源队列,用户必须把角色(用户)指派到它们合适的资源队列。如果没有显式地把角色指派给资源队列,它们将进入默认资源队列pg_default。默认资源队列的活动语句限制是20,没有代价限制,优先权设置是中等。

使用ALTER ROLE或者CREATE ROLE命令来指派角色到资源队列。例如:

=# ALTER ROLE name RESOURCE QUEUE queue_name;
=# CREATE ROLE name WITH LOGIN RESOURCE QUEUE queue_name;

任一给定时间,一个角色只能被指派给一个资源队列,因此用户可以使用ALTER ROLE命令来初始指派角色的资源队列或者更改角色的资源队列。

资源队列必须按逐用户的方式指派。如果有一个角色层次(例如,组级别角色),那么把资源队列指派给组将不会传播到组中的用户。

超级用户总是被免除资源队列限制。超级用户查询将总是被运行,而不管它们被指派的队列上的限制。

从资源队列移除角色

所有用户都必须被指派到资源队列。如果没有被显式指派到一个特定队列,用户将会进入到默认的资源队列pg_default。如果用户想要从一个资源队列移除一个角色并且把它们放在默认队列中,可以将该角色的队列指派改成none。例如:

=# ALTER ROLE role_name RESOURCE QUEUE none;

修改资源队列

在资源队列被创建后,用户可以使用ALTER RESOURCE QUEUE命令更改或者重置队列限制。用户可以使用DROP RESOURCE QUEUE命令移除一个资源队列。要更改指派到资源队列的用户,请见指派角色(用户)到资源队列

修改资源队列

ALTER RESOURCE QUEUE命令更改资源队列的限制。要更改一个资源队列的限制,可以为该队列指定想要的新值。例如:

=# ALTER RESOURCE QUEUE adhoc WITH (ACTIVE_STATEMENTS=5);
=# ALTER RESOURCE QUEUE exec WITH (PRIORITY=MAX);

要重置活动语句或者内存限制为没有限制,输入值-1。要重置最大查询代价为无限制,输入值-1.0。例如:

=# ALTER RESOURCE QUEUE adhoc WITH (MAX_COST=-1.0, MEMORY_LIMIT='2GB');

用户可以使用ALTER RESOURCE QUEUE命令更改一个资源队列相关查询的优先权。例如,要把一个队列设置为中等优先级:

ALTER RESOURCE QUEUE webuser WITH (PRIORITY=MIN);

删除资源队列

DROP RESOURCE QUEUE命令可以删除资源队列。要删除一个资源队列,该队列不能有指派给它的角色,也不能有任何语句在其中等待。关于清空一个资源队列的指导请见从资源队列移除角色以及从资源队列清除等待语句。要删除一个资源队列:

=# DROP RESOURCE QUEUE name;

检查资源队列状态

查看队列中的语句和资源队列状态

gp_toolkit.gp_resqueue_status视图允许管理员查看一个负载管理资源队列的状态和活动。对于一个特定资源队列,它展示有多少查询在等待运行以及系统中当前有多少查询是活动的。要查看系统中创建的资源队列、它们的限制属性和当前状态:

=# SELECT * FROM gp_toolkit.gp_resqueue_status;

查看资源队列统计信息

如果想要持续跟踪资源队列的统计信息和性能,可以为资源队列启用统计收集。这可以通过在Master的postgresql.conf文件中设置下列服务器配置参数实现:

stats_queue_level = on

一旦统计收集被启用,用户可以使用pg_stat_resqueues系统视图来查看在资源队列使用上收集的统计信息。注意启用这一特性确实会引发一点点性能开销,因为每个通过资源队列提交的查询都必须被跟踪。可以先在资源队列上启用统计收集用于初始的诊断和管理规划,然后再连续使用中禁用该特性。

更多有关Greenplum数据库中收集统计信息的内容,可参考PostgreSQL文档中的统计收集器部分。

查看指派到资源队列的角色

要查看指派给资源队列的角色,执行下列在pg_rolesgp_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;

用户可能想用这个查询创建一个视图来简化未来的查询。例如:

=# CREATE VIEW role2queue AS
   SELECT rolname, rsqname FROM pg_roles, pg_resqueue 
   WHERE pg_roles.rolresqueue=gp_toolkit.gp_resqueue_status.queueid;

然后就可以只查询该视图:

=# SELECT * FROM role2queue;

查看资源队列的等待查询

当资源队列的一个槽被使用时,它被记录在pg_locks系统目录表中。在其中用户可以看到所有资源队列的所有当前活跃的以及在等待的查询。要检查被放入队列中的语句(甚至不在等待的语句),用户还可以使用gp_toolkit.gp_locks_on_resqueue视图。例如:

=# SELECT * FROM gp_toolkit.gp_locks_on_resqueue WHERE lorwaiting='true';

如果这个查询不返回结果,那就意味着当前没有语句在资源队列中等待。

从资源队列清除等待语句

在某些情况下,用户可能想要从资源队列中清除等待的语句。例如,用户可能想移除在队列中等待但还未被执行的语句。用户可能还想停止已经被启动但是执行时间太久的查询,或者是在事务中闲置并且占据其他用户所需的资源队列槽的查询。要做到这一点,用户必须标识出想要清除的语句,确定它的进程ID(pid),然后使用pg_cancel_backend和进程ID来结束该进程(如下所示)。可以选择对被结束的进程发送一个消息来告诉用户原因,该消息作为第二个参数传入。

例如,要查看在所有资源队列中当前活动的或者在等待的语句,运行下列查询:

=# SELECT rolname, rsqname, pid, granted,
          current_query, datname 
   FROM pg_roles, gp_toolkit.gp_resqueue_status, pg_locks,
        pg_stat_activity 
   WHERE pg_roles.rolresqueue=pg_locks.objid 
   AND pg_locks.objid=gp_toolkit.gp_resqueue_status.queueid
   AND pg_stat_activity.procpid=pg_locks.pid;
   AND pg_stat_activity.usename=pg_roles.rolname;

如果这个查询不返回结果,那就意味着当前没有语句在资源队列中等待。例如,下面的资源队列在结果中有两个语句:

rolname | rsqname |  pid  | granted |     current_query      | datname 
----------------------------------------------------------------------- 
  sammy | webuser | 31861 | t       | <IDLE> in transaction  | namesdb
  daria | webuser | 31905 | f       | SELECT * FROM topten;  | namesdb

使用这一输出来标识出想要从资源队列中清除的语句的进程ID(pid)。要清除语句,用户可以在Master主机上打开一个终端窗口(作为gpadmin数据库超级用户或者root)并且取消对应的进程。例如:

=# pg_cancel_backend(31905)
注意:

不要使用任何的操作系统KILL命令。

查看活动语句的优先权

gp_toolkit管理方案有一个名为gp_resq_priority_statement的视图,它列出了当前正在被执行的语句并且提供优先权、会话ID和其他信息。

这个视图只有通过gp_toolkit管理方案才可用。更多信息请见Greenplum数据库参考指南

重置活动语句的优先权

超级用户可以使用内建函数gp_adjust_priority(session_id, statement_count, priority)调整当前正在被执行的语句的优先权。使用这个函数,超级用户可以提升或者降低任意查询的优先权。例如:

=# SELECT gp_adjust_priority(752, 24905, 'HIGH')

为了获得这个函数所需的会话ID和语句计数参数,超级用户可以使用gp_toolkit管理方案的视图gp_resq_priority_statement。从该视图用户可以把这些值用作该函数的参数。

  • rqpsession列的值用作session_id参数
  • rqpcommand列的值用作statement_count参数
  • rqppriority列的值是当前优先权。可以指定字符串值MAXHIGHMEDIUM或者LOW作为priority
注意: gp_adjust_priority()函数只影响指定的语句。同一资源队列中后续的语句还是使用该队列正常指派的优先权执行。