1.数据库性能
1.1.系统性能
管理系统性能包括度量性能、确定性能问题的原因以及应用可用的工具和技术来解决问题。
Greenplum基于数据库管理系统(DBMS)提供给请求者信息的速率来衡量数据库性能。
有多个关键性能因素会影响数据库性能。理解这些因素有助于确定提高性能的办法以及避免性能问题:
- 系统资源
- 负载
- 吞吐量
- 竞争
- 优化
- 系统资源 数据库性能严重依赖于磁盘I/O和内存使用。为了准确地设置性能预期,需要知道DBMS所部署的硬件的基线性能。CPU、硬盘、磁盘控制器、RAM以及网络接口等硬件组件的性能将会显著地影响数据库的执行速度。
- 负载 负载等于来自于DBMS的请求总量,它会随着时间变化。总负载是任意给定时刻通过DBMS的用户查询、应用、批处理任务、事务和系统命令的组合。例如,总负载会在运行期末报表时增加或者在大部分用户离开办公室时减小。负载会强力地影响数据库性能。了解负载以及峰值请求时刻有助于规划最有效地利用系统资源以及允许处理最大可能的负载。
- 吞吐量 一个系统的吞吐量定义了它处理数据的总体能力。DBMS的吞吐量以每秒的查询数、每秒的事务数或者平均响应时间来衡量。DBMS的吞吐量与底层系统(磁盘I/O、CPU速度、内存带宽等等)的处理能力紧密相关,因此在设置DBMS吞吐量目标时了解硬件的吞吐量能力很重要。
- 竞争 竞争就是负载中的两个或者更多组成部分尝试以一种冲突方式使用系统的情况 — 例如,多个查询尝试同时更新同一片数据或者多个大型负载竞争系统资源。竞争加剧则吞吐量下降。
- 优化 DBMS优化可以影响总体的系统性能。SQL形式化、数据库配置参数、表设计、数据分布等等都让数据库查询优化器能创建更有效的访问计划。
1.2.查询性能
GP支持动态分区消除和查询内存优化; GP在查询优化时为不同的操作动态的消除不相关分区和分配内存;
- 动态分区消去 在GP中,运行的值只能用于在内部动态的减少分区;需要设置Server参数 gp_dynamic_partition_pruning 缺省设置为on
- 内存优化 GP为一个查询中不同的操作以最优的方式分配内存;在单个查询的不同阶段快速地释放和重分配内存。
查询分析
GP为每一个查询设计出一个查询计划,确保查询和数据结构选择了正确的查询计划;
通过检查查询计划,帮助确定调优方案;
优化器根据统计信息来选择尽可能成本低的查询计划
成本是对I/O和CPU消耗的衡量(获取磁盘页的数量)
使用EXPLAIN来获取评估的查询计划,例如:
代码语言:javascript复制EXPLAIN SELECT * FROM tb_cp_02 WHERE date=‘2013-01-01’;
EXPLAIN ANALYZE会真正的执行语句,获取实际的查询执行情况。例如:
代码语言:javascript复制EXPLAIN ANALYZE SELECT * FROM tb_cp_02 WHERE date=‘2013-01-01’;
查看EXPLAIN输出
- EXPLAIN输出一个计划为节点组成的树
- 每个节点表示一个独立的操作
- 计划应该从下向上读,每个节点得到的记录向上传递
成本评估项:
- cost - 获取的磁盘页数,1.0等于一个连续的磁盘页读取 第一个评估是开始成本,第二个评估是总成本
- rows - 输出的记录数,通常小于真实处理的数量。 顶层节点评估的数量最接近真实值
- width - 输出的总字节数
示例
代码语言:javascript复制testdw=# explain select * from tb_cp_02 where date='2013-01-01';
QUERY PLAN
-------------------------------------------------------------------------------------------------------
Gather Motion 2:1 (slice1; segments: 2) (cost=0.00..2.02 rows=1 width=17)
-> Append (cost=0.00..2.02 rows=1 width=17)
-> Append-only Scan on tb_cp_02_1_prt_jan131to15 tb_cp_02 (cost=0.00..2.02 rows=1 width=17)
Filter: date = '2013-01-01'::date
(4 rows)
查看EXPLAIN ANALYZE输出
EXPLAIN输出真实运行的评估结果;EXPLAIN ANALYZE 输出的额外信息:
- 执行查询花费的总时间
- 参与每个节点计划的节点数,只有返回记录的segment实例被统计
- 操作中的segment实例返回的最大结果数量及其ID
- 返回最大结果数量的segment实例产生记录的开始时间和结束时间
- Slice数量及其内存消耗
1.3.如何看查询计划
若一个查询性能很差,查看查询计划有可能帮助我们找到问题,关注的几个方面:
- 计划中是否有一个操作花费时间过长?
- 优化器的评估是否接近实际情况?
- 选择性强的条件是否较早出现?
- 优化器是否选择了最佳的关联顺序?
- 优化器是否选择性的扫描分区表?
- 优化器是否合适的选择了HASH聚合与HASH关联操作? HASH 操作通常比其他类型的操作要快; 记录在内存中的比较排序比磁盘块 Work_mem wanted: 33649K bytes avg, 33649K bytes max (seg0) to lessen
2.判断可接受的性能
当有了性能调整的决定时,首先应该了解用户的系统的预期性能水平并且定义可衡量的性能需求,这样才能准确地评估系统的性能。在设置性能目标时考虑以下两点:
- 基线硬件性能
- 性能基准
- 基线硬件性能 大部分的数据库性能问题并非由数据库而是数据库所运行的底层系统导致。I/O瓶颈、内存问题以及网络问题都能显著地降低数据库性能。在开始摸索数据库或者查询级别调整前,了解硬件和操作系统(OS)基线能力将帮助用户发现并且解决硬件相关的问题。 有关运行gpcheckperf工具验证硬件和网络性能的信息请见Greenplum数据库参考指南。
- 性能基准 要维护好的性能或者修复性能问题,应该了解DBMS在一个定义好的负载上的能力如何。基准是一个预定义的能产生已知结果集的负载。周期性地运行相同的基准测试可以帮助发现系统性能随时间衰退的情况。使用基准可以比较负载并且发现需要优化的查询或者应用。 很多第三方组织(例如事务处理性能委员会,TPC)都为数据库产业提供了基准工具。TPC提供了TPC-H,它是一个决策支持系统,它检查大量数据、执行高度复杂的查询并且对核心业务问题给出答案。
3.识别硬件和Segment失效
Greenplum数据库的性能取决于它所运行的硬件和IT基础设施。 Greenplum数据库由多台服务器(主机)构成,它们作为一个紧密的系统(阵列)一起工作。 作为诊断性能的第一步,应确保所有的Greenplum数据库的Segment都在线。Greenplum数据库的性能将和阵列中最慢的那一台主机相同。CPU利用、内存管理、I/O处理或者网络负载方面的问题都会影响性能。常见的与硬件相关的问题有:
- 磁盘失效 – 尽管在使用RAID时单一磁盘失效不会剧烈的影响数据库性能,但磁盘重新同步确实会在有失效磁盘的主机上消耗资源。gpcheckperf工具可以帮助发现有磁盘I/O问题的Segment主机。
- 主机失效 – 当一台主机离线时,该主机上的Segment就不可操作。这意味着阵列中的其他主机必须执行两倍于它们通常的负载,因为它们运行着主要Segment和多个镜像。如果没有启用镜像,服务就会中断。为恢复失效的Segment也需要临时中断服务。gpstate工具可以帮助发现失效的Segment。
- 网络失效 – 一块网卡、一台交换机或者DNS服务器的失效都可能让Segment宕掉。如果在Greenplum阵列中无法解析主机名或者IP地址,这就表明它们是Greenplum数据库中的Interconnect错误。gpcheckperf可以帮助发现出现网络问题的Segment主机。
- 磁盘容量 – Segment主机上的磁盘容量应该永远不超过70%充满。Greenplum数据库需要一些空闲空间来做运行时处理。要回收已删除行占用的磁盘空间,可以在装载或者更新后运行VACUUM。gp_toolkit管理方案中有很多视图可用来检查分布式数据库对象的尺寸。有关检查数据库对象尺寸和磁盘空间的信息请见Greenplum数据库参考指南。
4.管理负载
一个数据库系统的CPU容量、内存和磁盘I/O资源是有限的。当多个负载竞争访问这些资源时,数据库性能就会受到影响。负载管理能在符合多变的业务需求的同时最大化系统吞吐。通过基于角色的资源队列,Greenplum数据库负载管理会限制活动查询并且保护系统资源。
一个资源队列限制用户或角色能在特定队列中执行的查询尺寸和查询总数。通过将数据库角色分配到适当的资源队列,管理员能够控制并发用户查询并且防止系统过载。
Greenplum数据库管理员应该在业务时段之后运行维护负载,例如数据装载和VACUUM ANALYZE操作。不要与数据库用户竞争系统资源,在低使用率时段执行管理任务。
4.1.避免竞争
当多个用户或者负载尝试以冲突的方式使用系统时,竞争就会发生。例如,当两个事务尝试同时更新一个表时会发生竞争。一个寻求表级或行级锁的事务将无限等待冲突的锁被释放。应用不应该保持事务打开很长时间,例如,在等待用户输入时。
4.2.维护数据库统计信息
Greenplum数据库使用一种依赖于数据库统计信息的基于代价的查询优化器。准确的统计信息让查询优化器更好地估计一个查询检索的行数,以便选择最有效的查询计划。如果没有数据库统计信息,查询优化器就不能估计将返回多少记录。优化器并不假设它有足够多的内存来执行特定的操作,例如聚集,因此它会采取最保守的行动并且通过读写磁盘来做这些操作。这比在内存中做要慢很多。ANALYZE会收集查询优化器需要的数据库相关的统计信息。注意:在使用GPORCA执行SQL命令时,如果通过在该命令引用的一列或者多列上收集统计信息可以改进命令的性能,Greenplum数据库会发出一个警告。该警告在命令行上发出并且信息会被加入到Greenplum数据库的日志文件中。有关在表列上收集统计信息的内容请见Greenplum数据库参考指南中的ANALYZE命令。 识别查询计划中的统计信息问题
在使用EXPLAIN或者EXPLAIN ANALYZE解释一个查询的计划之前,先熟悉一下有助于帮助发现统计信息问题的数据。在计划中检查下列不准确统计信息的指示器:
- 优化器的估计接近于现实吗?运行EXPLAIN ANALYZE并且看看优化器估计的行数是否和查询操作返回的行数接近。
- 计划中是否比较早地应用了选择性谓词?最具选择性的过滤条件应该在计划中早早地被应用,这样会有较少的行在计划树中向上移动。
- 优化器是否选择了最好的连接顺序?在一个查询连接多个表时,确保优化器选择最具选择性的连接顺序。消除行数最多的连接应该在计划中被最早执行,这样会有较少的行在计划树中向上移动。
4.3.调整统计收集
下列配置参数控制统计信息收集采样的数据量:
- default_statistics_target
- gp_analyze_relative_error
这些参数控制系统层面的统计信息采样。最好只对查询谓词中最频繁使用的列采样增加的统计信息。用户可以对一个特定的列采用下面的命令调整统计信息:
代码语言:javascript复制ALTER TABLE sales ALTER COLUMN region SET STATISTICS 50;
这等效于为特定列增加default_statistics_target。后续的ANALYZE操作接着将为该列收集更多统计数据并且结果就是会产生更好的查询计划。
4.4.优化数据分布
当用户在Greenplum数据库中创建一个表时,用户必须声明一个分布键,它允许在系统中所有的Segment上均匀地分布数据。因为Segment会以并行的方式工作在查询上,Greenplum数据库将总是和最慢的Segment速度相同。如果数据不平衡,拥有更多数据的Segment将更慢地返回它们的结果,因此会拖慢整个系统。 优化数据库设计
很多性能问题可以通过数据库设计改进。检查用户的数据库设计并且考虑以下几点:
- 模式是否反映了数据被访问的方式?
- 较大的表是否能被分解成分区?
- 是否在使用尽可能小的数据类型来存储列值?
- 用于连接表的列是否为相同的数据类型:?
- 索引有没有被使用?
4.5.Greenplum数据库最大量限制
为了帮助优化数据库设计,回顾一下Greenplum数据库支持的最大量限制:
维度 | 限制 |
---|---|
数据库尺寸 | 无限 |
表尺寸 | 无限,每个Segment的每个分区是128TB |
行尺寸 | 1.6 TB (1600 列 * 1 GB) |
域尺寸 | 1 GB |
每个表的行 | 281474976710656 (2^48) |
每个表/视图的列 | 1600 |
每个表的索引 | 无限 |
每个索引的列 | 32 |
每个表的表级约束 | 无限 |
表名长度 | 63 字节 (受name数据类型限制) |
这里列出的“无限”维度本质上不受Greenplum数据库的限制。不过,它们实际受限于可用的磁盘空间和内存/交换空间。当这些值异乎寻常地大时,性能可能会受到损害。注意:
可以同时存在的对象(表、索引以及视图,但不包括行)数有一个最大限制。该限制为4294967296 (2^32)。
5.工作负载管理
使用Greenplum数据库的工作负载管理根据业务需求对查询按照优先级分配资源,并且在资源不可用时阻止查询开始。
使用资源队列,可用的内存和CPU资源可以被分配给执行在Greenplum数据库系统上的不同类别的查询。用户可以限制并发查询的数量、执行一个查询所用到的内存量以及处理一个查询耗费的CPU相对量。
资源管理主要关注的是能并发执行的查询数量以及分配给每个查询的内存量。如果不限制并发度和内存使用,就不可能保证可接受的性能。内存是最有可能限制系统处理能力的资源。因此,我们从Greenplum数据库的内存使用概述开始。
5.1.Greenplum 数据库的内存
内存是一个Greenplum数据库系统的关键资源,如果被有效使用,就能确保高性能和高吞吐。
一台Greenplum数据库的Segment主机运行多个PostgreSQL实例,它们都共享该主机的内存。这些Segment拥有相同的配置,并且在并行处理查询时它们同时消耗相似的内存量、CPU和磁盘I/O。
为了最好的查询吞吐,内存配置应该被仔细地管理。在Greenplum数据库的每个层次都有内存配置选项,从操作系统参数到用资源队列管理负载,再到设置分配给个别查询的内存量。
Segment主机内存
在一台Greenplum数据库的Segment主机上,可用的主机内存被执行在该计算机上的所有进程共享,包括操作系统、Greenplum数据库的Segment实例以及其他应用进程。管理员必须决定Greenplum数据库进程和非Greenplum数据库进程怎样共享主机的内存,并且配置系统有效地使用内存。定期监控内存使用同样重要,这样可以检测Greenplum数据库或其他进程消耗主机内存的方式变化。下面的图展示了在一台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来配置操作系统如何处理大型内存分配请求。
为操作系统和其他进程保留的内存量是与负载相关的。操作系统内存的最小推荐是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):
代码语言:javascript复制gp_vmem = ((SWAP RAM) – (7.5GB 0.05 * RAM)) / 1.7
其中SWAP是主机上的交换空间(以GB为单位),而RAM是安装在主机上的RAM的GB数。用这个公式计算vm.overcommit_ratio:
代码语言:javascript复制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数据库进程可用的内存):
代码语言:javascript复制gp_vmem = ((SWAP RAM) – (7.5GB 0.05 * RAM)) / 1.7
其中 其中SWAP是主机上的交换空间(以GB为单位),而RAM是安装在主机上的RAM的GB数。使用这个公式计算gp_vmem_protect_limit:
代码语言:javascript复制gp_vmem_protect_limit = gp_vmem / max_acting_primary_segments
其中max_acting_primary_segments是镜像Segment由于主机或Segment失效而被激活时可能运行在一台主机上的主Segment的最大数量。
statement_mem 是一项重要的Greenplum数据库服务器配置参数。这个参数设置分配来执行查询的最大内存量。要为这个参数确定值,用每个Segment的内存量(gp_vmem_protect_limit)减去一个10%的安全量,然后除以期望并发执行的最大查询数量。默认的Greenplum书库资源队列允许最多20个并发查询。这里有一个公式计算statement_mem:
代码语言:javascript复制(gp_vmem_protect_limit * .9 ) / max_expected_concurrent_queries
资源队列允许对分配给查询的内存量进行更多控制。
5.2.用资源队列管理负载
资源队列是Greenplum数据库系统中管理并发程度的主要工具。资源队列是使用SQL语句CREATE RESOURCE QUEUE创建的数据库对象。用户可以使用它们来管理可以并发执行的活动查询的数量、每种查询分配的内存量和查询的相对优先级。资源队列也防止查询消耗过多资源并且降低总体系统性能。
每个数据库都关联着一个单一资源队列,多个角色可以共享同一个资源队列。使用CREATE ROLE or ALTER ROLE语句的RESOURCE QUEUE短语可将角色分派到资源队列。如果没有指定资源队列,角色将与默认资源队列pg_default关联。
当用户提交一个查询执行时,会根据资源队列的限制评估查询。如果该查询不会导致队列超过它的资源限制,那么该查询将被立即运行。如果该查询导致队列超过其限制(例如,如果当前正在使用的活动语句槽已达最大数量),那么查询必须等待直到队列资源被释放出来才能运行。采用先进先出的方式评估查询。如果启用了查询优先,系统上的活动负载会被定期访问并且处理资源会被根据查询优先度重新分配。带有SUPERUSER属性的角色会被免除资源队列限制。超级用户查询总是被立即运行,而不管它们所属资源队列上的限制。
资源队列定义了具有类似资源需求的查询的分类。管理员应该为其组织中各种类型的查询创建资源队列。例如,用户可能会为下列分类的查询创建资源队列,它们对应于不同的服务水平协议:
- ETL查询
- 报表查询
- 行政查询
资源队列有下列特性:
- 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语句被排除在资源队列之外。
资源队列实例
默认的资源队列pg_default允许最多20个活动查询并且为它们分配等量的内存。这通常不能胜任生产系统的资源控制。为了确保系统符合性能预期,用户可以定义查询的分类并且把它们分派到最适合(并行度、内存、CPU资源)该类查询的资源队列。下面的图展示了一个Greenplum数据库系统的资源队列配置的例子,其中gp_vmem_protect_limit被设置为8GB:
这个例子有三类具有不同特点和服务水平协议(SLA)的查询。为它们配置了三个资源队列。Segment内存的一部分被保留作为安全裕度。
资源队列名称 | 活动语句 | 内存限制 | 每个查询的内存 |
---|---|---|---|
ETL | 3 | 2GB | 667MB |
报表 | 7 | 3GB | 429MB |
行政 | 1 | 1.4GB | 1.4GB |
分配给队列的总内存是6.4GB或者gp_vmem_protect_limit服务器配置参数所定义的Segment总内存的80%。允许20%的安全裕度可以容纳某些操作符和查询,它们已知会使用比资源队列分配给它们的更多的内存。
内存限制如何工作
一个资源队列上的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。报表查询所使用的准确份额会被调整,但仍然保持相等,因为它们的优先权设置相等:
这些图中显示的百分数都是近似值。高、低和中优先权队列的CPU使用并不总是准确地用这些比例计算出来。
当一个行政查询进入到运行语句组中时,CPU使用会被调整以说明其最大优先权设置。它可能是一个堪比分析师和报表查询的简单查询,但直到它完成前,它都将要求最大份额的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和资源队列内存限制所控制。
- 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数据库安装指南。
- 下列参数与查询优先有关。注意下列参数都是本地参数,意味着它们必须在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核数中。
- 如果用户希望查看或者更改任何负载管理参数值,可以使用gpconfig工具。
- 例如,要查看一个特定参数的设置:$ gpconfig –show gp_vmem_protect_limit
- 例如,要在所有的Segment实例上设置一个值并且在Master上设置一个不同的值:$ gpconfig -c gp_resqueue_priority_cpucores_per_segment -v 2 -m 8
- 重启Greenplum数据库让配置更改生效:$ gpstop -r
创建资源队列
创建一个资源队列涉及到给它一个名称、设置一个活动查询限制并且可选地在该资源队列上设置一个查询优先权。使用CREATE RESOURCE QUEUE命令来创建新的资源队列。
创建带有活动查询限制的队列 Resource queues with an 带有ACTIVE_STATEMENTS设置的资源队列会限制指派给该队列的角色所执行的查询数量。例如,要创建一个名为adhoc且活动查询限制为3的资源队列:
代码语言:javascript复制=# 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_LIMIT与ACTIVE_STATEMENTS而不是与MAX_COST一起使用。 例如,要创建一个活动查询限制为10且总内存限制为2000MB的资源队列(每个查询将在执行时被分配200MB的Segment主机内存):
代码语言:javascript复制=# CREATE RESOURCE QUEUE myqueue WITH (ACTIVE_STATEMENTS=20,
MEMORY_LIMIT='2000MB');
可以使用statement_mem服务器配置参数针对每个查询覆盖默认的内存分配,前提是没有超过MEMORY_LIMIT或者max_statement_mem。例如,要对一个特定查询分配更多内存:
代码语言:javascript复制=> 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 QUEUE和ALTER RESOURCE QUEUE的WITH参数创建或修改。例如,要为adhoc and reporting队列指定优先权设置,管理员会使用下列命令:
代码语言:javascript复制=# ALTER RESOURCE QUEUE adhoc WITH (PRIORITY=LOW);
=# ALTER RESOURCE QUEUE reporting WITH (PRIORITY=HIGH);
要以最大优先权创建executive队列,管理员可以使用下列命令:
代码语言:javascript复制=# CREATE RESOURCE QUEUE executive WITH (ACTIVE_STATEMENTS=3, PRIORITY=MAX);
当查询优先特性被启用时,如果没有显式地指派,默认会为资源队列给出一个MEDIUM优先权。
为了在活动查询负载上实施资源队列优先级,用户必须通过设置相关服务器配置参数来启用查询优先特性。
指派角色(用户)到资源队列
一旦创建了一个资源队列,用户必须把角色(用户)指派到它们合适的资源队列。如果没有显式地把角色指派给资源队列,它们将进入默认资源队列pg_default。默认资源队列的活动语句限制是20,没有代价限制,优先权设置是中等。
使用ALTER ROLE或者CREATE ROLE命令来指派角色到资源队列。例如:
代码语言:javascript复制=# ALTER ROLE name RESOURCE QUEUE queue_name;
=# CREATE ROLE name WITH LOGIN RESOURCE QUEUE queue_name;
任一给定时间,一个角色只能被指派给一个资源队列,因此用户可以使用ALTER ROLE命令来初始指派角色的资源队列或者更改角色的资源队列。
资源队列必须按逐用户的方式指派。如果有一个角色层次(例如,组级别角色),那么把资源队列指派给组将不会传播到组中的用户。
超级用户总是被免除资源队列限制。超级用户查询将总是被运行,而不管它们被指派的队列上的限制。
从资源队列移除角色
所有用户都必须被指派到资源队列。如果没有被显式指派到一个特定队列,用户将会进入到默认的资源队列pg_default。如果用户想要从一个资源队列移除一个角色并且把它们放在默认队列中,可以将该角色的队列指派改成none。例如:
代码语言:javascript复制=# ALTER ROLE role_name RESOURCE QUEUE none;
修改资源队列
在资源队列被创建后,用户可以使用ALTER RESOURCE QUEUE命令更改或者重置队列限制。用户可以使用DROP RESOURCE QUEUE命令移除一个资源队列。
ALTER RESOURCE QUEUE命令更改资源队列的限制。要更改一个资源队列的限制,可以为该队列指定想要的新值。例如:
代码语言:javascript复制=# ALTER RESOURCE QUEUE adhoc WITH (ACTIVE_STATEMENTS=5);
=# ALTER RESOURCE QUEUE exec WITH (PRIORITY=MAX);
要重置活动语句或者内存限制为没有限制,输入值-1。要重置最大查询代价为无限制,输入值-1.0。例如:
代码语言:javascript复制=# ALTER RESOURCE QUEUE adhoc WITH (MAX_COST=-1.0, MEMORY_LIMIT='2GB');
用户可以使用ALTER RESOURCE QUEUE命令更改一个资源队列相关查询的优先权。例如,要把一个队列设置为中等优先级:
代码语言:javascript复制ALTER RESOURCE QUEUE webuser WITH (PRIORITY=MIN);
删除资源队列
DROP RESOURCE QUEUE命令可以删除资源队列。要删除一个资源队列,该队列不能有指派给它的角色,也不能有任何语句在其中等待。
代码语言:javascript复制=# DROP RESOURCE QUEUE name;
检查资源队列状态
检查资源队列状态涉及下列任务:
- 查看队列中的语句和资源队列状态
- 查看资源队列统计信息
- 查看指派到资源队列的角色
- 查看资源队列的等待查询
- 从资源队列清除等待语句
- 查看活动语句的优先权
- 查看活动语句的优先权
step 1.查看队列中的语句和资源队列状态 gp_toolkit.gp_resqueue_status视图允许管理员查看一个负载管理资源队列的状态和活动。对于一个特定资源队列,它展示有多少查询在等待运行以及系统中当前有多少查询是活动的。要查看系统中创建的资源队列、它们的限制属性和当前状态:
代码语言:javascript复制=# SELECT * FROM gp_toolkit.gp_resqueue_status;
step 2.查看资源队列统计信息 如果想要持续跟踪资源队列的统计信息和性能,可以为资源队列启用统计收集。这可以通过在Master的postgresql.conf文件中设置下列服务器配置参数实现:
代码语言:javascript复制stats_queue_level = on
一旦统计收集被启用,用户可以使用pg_stat_resqueues系统视图来查看在资源队列使用上收集的统计信息。注意启用这一特性确实会引发一点点性能开销,因为每个通过资源队列提交的查询都必须被跟踪。可以先在资源队列上启用统计收集用于初始的诊断和管理规划,然后再连续使用中禁用该特性。
step 3.查看指派到资源队列的角色 要查看指派给资源队列的角色,执行下列在pg_roles和gp_toolkit.gp_resqueue_status系统目录表上的查询:
代码语言:javascript复制=# SELECT rolname, rsqname FROM pg_roles,
gp_toolkit.gp_resqueue_status
WHERE pg_roles.rolresqueue=gp_toolkit.gp_resqueue_status.queueid;
用户可能想用这个查询创建一个视图来简化未来的查询。例如:
代码语言:javascript复制=# CREATE VIEW role2queue AS
SELECT rolname, rsqname FROM pg_roles, pg_resqueue
WHERE pg_roles.rolresqueue=gp_toolkit.gp_resqueue_status.queueid;
然后就可以只查询该视图:
代码语言:javascript复制=# SELECT * FROM role2queue;
step 4.查看资源队列的等待查询 当资源队列的一个槽被使用时,它被记录在pg_locks系统目录表中。在其中用户可以看到所有资源队列的所有当前活跃的以及在等待的查询。要检查被放入队列中的语句(甚至不在等待的语句),用户还可以使用gp_toolkit.gp_locks_on_resqueue视图。例如:
代码语言:javascript复制=# SELECT * FROM gp_toolkit.gp_locks_on_resqueue WHERE lorwaiting='true';
如果这个查询不返回结果,那就意味着当前没有语句在资源队列中等待。
step 5.从资源队列清除等待语句 在某些情况下,用户可能想要从资源队列中清除等待的语句。例如,用户可能想移除在队列中等待但还未被执行的语句。用户可能还想停止已经被启动但是执行时间太久的查询,或者是在事务中闲置并且占据其他用户所需的资源队列槽的查询。要做到这一点,用户必须标识出想要清除的语句,确定它的进程ID(pid),然后使用pg_cancel_backend和进程ID来结束该进程(如下所示)。可以选择对被结束的进程发送一个消息来告诉用户原因,该消息作为第二个参数传入。
例如,要查看在所有资源队列中当前活动的或者在等待的语句,运行下列查询:
代码语言:javascript复制=# 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;
如果这个查询不返回结果,那就意味着当前没有语句在资源队列中等待。例如,下面的资源队列在结果中有两个语句:
代码语言:javascript复制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)并且取消对应的进程。例如:
代码语言:javascript复制=# pg_cancel_backend(31905)
不要使用任何的操作系统KILL命令。
step 6.查看活动语句的优先权 gp_toolkit管理方案有一个名为gp_resq_priority_statement的视图,它列出了当前正在被执行的语句并且提供优先权、会话ID和其他信息。
这个视图只有通过gp_toolkit管理方案才可用。更多信息请见Greenplum数据库参考指南。 重置活动语句的优先权
超级用户可以使用内建函数gp_adjust_priority(session_id, statement_count, priority)调整当前正在被执行的语句的优先权。使用这个函数,超级用户可以提升或者降低任意查询的优先权。例如:
代码语言:javascript复制=# SELECT gp_adjust_priority(752, 24905, 'HIGH')
为了获得这个函数所需的会话ID和语句计数参数,超级用户可以使用gp_toolkit管理方案的视图gp_resq_priority_statement。从该视图用户可以把这些值用作该函数的参数。
- rqpsession列的值用作session_id参数
- rqpcommand列的值用作statement_count参数
- rqppriority列的值是当前优先权。可以指定字符串值MAX、HIGH、MEDIUM或者LOW作为priority。
gp_adjust_priority()函数只影响指定的语句。同一资源队列中后续的语句还是使用该队列正常指派的优先权执行。
6.检修性能问题
这一主题列出了可以帮助用户确定性能问题原因的步骤。如果问题影响了一种特定的负载或查询,用户可以聚焦于调节该特定负载。如果性能问题是系统范围的,那么硬件问题、系统失效或者资源竞争可能是原因。
检查系统状态
使用gpstate工具来确定失效的Segment。当Segment实例宕机时,Greenplum数据库系统将会引发性能退化,因为其他主机必须负担起宕掉的Segment的责任。
失效的Segment可能表明有硬件失效,例如一个失效的磁盘驱动器或者网卡。Greenplum数据库提供了硬件验证工具gpcheckperf来确定有硬件问题的Segment主机。
检查数据库活动
- 检查活动会话(负载)
- 检查锁(竞争)
- 检查查询状态和系统利用
检查活动会话(负载) pg_stat_activity系统目录视图为每个服务器进程展示了一行,它显示数据库OID、数据库名、进程ID、用户OID、用户名、当前查询、当前查询开始执行的时间、进程开始时间、客户端地址和端口号。要获得大部分有关当前系统负载的信息,可以作为数据库超级用户查询这个视图。例如:
代码语言:javascript复制SELECT * FROM pg_stat_activity;
注意信息不会立刻更新。
检查锁(竞争) pg_locks系统目录视图允许用户查看有关未解除的锁的信息。如果一个事务在一个对象上持有一个锁,任何其他查询在能够继续之前都必须等待该锁被释放。这对于用户来说可能就好像一个查询悬而不决。 在pg_locks中检查未授予的锁,以便帮助确定数据库客户端会话之间的竞争。pg_locks提供了数据库系统中所有锁的一个全局视图,而不只是那些与当前数据库相关的锁。用户可以把它的relation列与pg_class.oid连接在一起以确定被锁住的关系(例如表),但这只对当前数据库中的关系能正确地工作。用户可以把pid列连接到pg_stat_activity.procpid以查看更多会话持有或者等待持有锁的信息。例如:
代码语言:javascript复制SELECT locktype, database, c.relname, l.relation,
l.transactionid, l.transaction, l.pid, l.mode, l.granted,
a.current_query
FROM pg_locks l, pg_class c, pg_stat_activity a
WHERE l.relation=c.oid AND l.pid=a.procpid
ORDER BY c.relname;
如果用户把资源队列用于负载管理,在一个队列中等候的查询也会显示在pg_locks中。要查看一个资源队列中有多少查询正在等待运行,可使用 gp_resqueue_status 系统目录视图。例如:
代码语言:javascript复制SELECT * FROM gp_toolkit.gp_resqueue_status;
检查查询状态和系统利用 用户可以使用ps、top、iostat、vmstat、netstat之类的系统监控工具监控Greenplum数据库阵列中主机上的数据库活动。这些工具能够帮助确定当前运行在系统上的Greenplum数据库进程(postgres进程)以及资源占用最多(CPU、内存、磁盘I/O或者网络活动)的任务。查看这些统计信息以确定降低数据库性能的查询,它们会让系统超载并且消耗极多的资源。Greenplum数据库的管理工具gpssh允许用户在多个主机上同时运行这些系统监控命令。 用户可以创建并使用Greenplum数据库的session_level_memory_consumption视图,它为在Greenplum数据库上运行查询的会话提供有关当前内存利用和闲置时间的信息。 用户可以启用一个专用数据库gpperfmon,运行在每个Segment主机上的数据收集代理把查询和系统的使用指标保存在其中。创建gpperfmon数据库以及管理代理的帮助请参考Greenplum数据库管理工具参考指南中的gperfmon_install管理工具参考。
检修问题查询
如果一个查询执行得很糟糕,查看它的查询计划以帮助确定问题。EXPLAIN命令展示一个给定查询的查询计划。
当查询执行期间发生内存不足事件时,Greenplum数据库内存核算框架会报告事件发生时运行的每一个查询的详细内存消耗。这些信息被写入到Greenplum数据库的Segment日志中。
研究错误消息
Greenplum数据库的日志消息被写入到Master或Segment的数据目录中pg_log子目录下的文件中。由于Master的日志文件包含了大部分的信息,用户应该总是先检查它。日志文件会每日滚动并且使用下面的命名习惯:gpdb-YYYY–MM–DD_hhmmss.csv. 要在Master主机上定位日志文件:
代码语言:javascript复制$ cd $MASTER_DATA_DIRECTORY/pg_log
日志行的格式:
代码语言:javascript复制timestamp | user | database | statement_id | con#cmd#
|:-LOG_LEVEL: log_message
用户可能想把搜索聚焦在WARNING、ERROR、FATAL或者PANIC日志级别的消息上。用户可以使用Greenplum的工具gplogfilter在Greenplum数据库的日志文件中搜索。例如,在Master主机上运行下列命令时,它会在标准日志位置检查有问题的日志消息:
代码语言:javascript复制$ gplogfilter -t
要在Segment日志文件中搜索相关的日志项,用户可以使用gpssh在Segment主机上运行gplogfilter。可以根据statement_id或者con#(会话标识符)确定对应的日志项。例如,要在Segment日志文件中搜索含有字符串con6的日志消息并且把输出保存到一个文件:
代码语言:javascript复制gpssh -f seg_hosts_file -e 'source
/usr/local/greenplum-db/greenplum_path.sh ; gplogfilter -f
con6 /gpdata/*/pg_log/gpdb*.csv' > seglog.out