Greenplum Database (V6.2.1) - 9

 

  Index      Manuals     Greenplum Database (V6.2.1)

 

Search            copyright infringement  

 

   

 

   

 

Content      ..     7      8      9     

 

 

 

 

Greenplum Database (V6.2.1) - 9

 

 

Greenplum Database 管理员指南 V6.2.1
从执行计划可以看到Orca优化器根据失真的统计信息生成了错误的执行计划
在扫描完数据之后就使用a字段进行数据重分布这注定会发生计算倾斜。执行计划
选择了GroupAggregate算子而不是HashAggregate算子来完成Group By
的计算这个问题不是本节的重点结尾处会再来优化这个问题下面先看看这个缺省
的执行计划的实际执行情况
EXPLAIN ANALYZE的输出可以看出表扫描之后重分布算子就花费了22秒的时间。
接下来对执行计划进行适当的干预避免出现计算倾斜设置如下的GUC参数
SET optimizer_force_multistage_agg TO ON;
此时执行计划变为
图形化的执行计划为
版权所有Esena(陈淼 ) 编写陈淼 - 400 -
Greenplum Database 管理员指南 V6.2.1
从执行计划可以看出扫描完数据之后先进行了本地AGG操作这样就避免的计
算倾斜。实际执行情况
整个SQL的耗时52秒下降到了7秒。
最后GroupAggregate的问题进行一下优化
设置如下的GUC参数
SET optimizer_force_multistage_agg TO ON;
SET optimizer_enable_groupagg TO OFF;
再看一下执行计划
图形化的执行计划为
实际执行情况
版权所有Esena(陈淼 ) 编写陈淼 - 401 -
Greenplum Database 管理员指南 V6.2.1
整个SQL的耗时下降到了0.9这是因为在大多数情况下GroupAgg的性能
远不如HashAgg的性能根本原因是Sort的计算复杂度是O(NlnN)Hash的计算
复杂度为O(N))
编者无法进行大篇幅的举例说明毕竟真实生产情况下计算倾斜的情况比这个例
子要复杂的多不过编者希望这个例子能成为一个学习和解决计算倾斜的入门示例。
在官方文档中还介绍了如何如何通过gpssh工具来查看每个Primary的溢出文
件情况以此来分析发生倾斜时哪些Primary因为内存资源的不足而导致大量的产
生溢出文件到磁盘上实际上编者认为直接通过gp_toolkit的几个workfile
视图就可以很好的发现溢出文件的问题gp_workfile_entries
gp_workfile_usage_per_querygp_workfile_usage_per_segment
分区
合理的分区将有助于减少相关查询需要扫描的数据量也将有助于对数据进行周
期性管理。每个叶子分区都是一个独立的数据表在每个Instance数据都存储
在独立的数据文件中。分区与分布是完全不相关的两个概念分布是数据在多个
Instance之间分散分区在每个Instance看来数据被拆分存储在多个独立的数
据库表中。如果对于分库分表能够理解的话分布类似于分库分区类似于分表。
不过如果没有任何的分区裁剪而是做全表查询分区表的性能会低于同样
数据的非分区表因为需要打开更多的文件以及对扫描的结果进行合并。这就如同列
存表与行存表如果要查询所有的字段列存表的性能会低于同样数据的行存表因为
需要打开更多的文件甚至还需要把不同字段的数据重新组织为ROW
下面是分区的最佳实践
只对特别大的表进行分区--这是所有条件中必须满足的条件不满足该条件的任
何表都不应该进行分区。永远不要对小表进行分区哪怕它的表结构和应用场景
非常的具有周期性和规律性。
版权所有Esena(陈淼 ) 编写陈淼 - 402 -
Greenplum Database 管理员指南 V6.2.1
选择分区字段时要确保该字段可以用于查询条件从而可以进行分区消除以降
低查询扫描的数据量。
只有等值表达式和比较大小的表达式可以用于分区裁剪比如这些操作符=
<<=>>=<>。当然对于ORCA来说还可能会有动态分区裁剪(Partition
selector算子)
分区选择只适用STABLEIMMUTABLE类型的函数VOLATILE类型的函数不
适用这是因为STABLEIMMUTABLE类型的函数是事务稳定的VOLATILE类型
的函数对于任意一次的执行都具有不确定性可以参考"GP中使用函数"章节
获得更多关于函数易变性的解释。
例如下面这种条件
date > CURRENT_DATE
这个条件可以使用分区裁剪因为在整个事务期间CURRENT_DATE的结果是不
变的所以优化器可以提前将其替换为一个常量。但是如果是下面这种条件
date > TIMEOFDAY
这个条件将无法使用分区裁剪因为对于每条记录来说TIMEOFDAY的输出都
在变化。如果能使用STABLEIMMUTABLE类型的函数作为分区字段的过滤条件
应该避免使用VOLATILE类型的函数作为分区字段的过滤条件需要特别注意
的是创建函数时缺省的易变性属性是VOLATILE类型。
如果可以选择范围(range)分区最好不要选择列表(list)分区。列表分区
个分区对应的都是孤立的值对于只有有限个DISTINT数量的字段进行分区
往往没有必要因为不一定会带来显著的性能提升。
要选择常常会用于条件过滤的字段作为分布键字段。
不要用分布键作为分区字段。一般来说这两个概念不应该有交集分布键一般
是某个业务表的主键具有很高的唯一性比如手机号身份证号码客户号等
而分区字段一般应该是具有可比较大小和范围的字段比如时间日期等。
不要使用缺省分区。PostgreSQL优化器一定会扫描缺省分区而且有缺省分区
的情况下添加分区必须通过split缺省分区来完成。ORCA在进行分区裁剪时
会跳过对缺省分区的扫描。
杜绝使用多级分区多级分区很容易使得表的数量失控从而导致文件数过度膨胀。
不要过度的曲解分区的功能分区不是万能膏药。
版权所有Esena(陈淼 ) 编写陈淼 - 403 -
Greenplum Database 管理员指南 V6.2.1
虽然GP支持多级子分区但是编者衷心奉劝功能是功能最佳实践是最佳实
如果有可能应该杜绝使用一级以上的分区编者在初始化GP集群时会缺
省将GUC参数gp_max_partition_level设置为1不允许创建多级分区表。多
级分区很容易导致很多叶子分区实际上存储的数据量很小甚至是空表未必带来
性能的提升反而会为分区维护带来异常的复杂度最终可能会把业务的性能搞
的更差使得情况变得更糟糕。
需要合理控制分区粒度不要过度零碎的进行分区。每个叶子分区在每个
Primary上的数据量应该控制在100MB以上或者记录数在100万条以上。比如集
群有100Primary那么可以使用一个通用的简化标准每个叶子分区的数据量
1亿条以上。同时单表在单个Primary上的记录数低于500万条时建议不
做分区比如集群有100Primary单表记录数在5亿以下时可以不分区。
应该检查执行计划是否有分区裁剪以确定分区是否对查询有帮助。
当需要对列存表进行分区时每个分区的记录数应该更大因为列存表是按照每个
字段作为一个单独的数据文件来存储的。整个分区表的数据文件数量为
文件数量 = Primary数量 × 分区数量 × 字段数量
比如100Primary的集群一张表有100个分区100个字段那么数据文
件的数量就会达到100万个如果再有多并发INSERT导致AO表文件分裂最坏的
情况下文件数将达到1.28亿个每个Primary上的文件数最坏的情况下
以达到128万个这些数字都是极其糟糕的。
在对列存表进行分区时应该控制每个叶子分区在每个Primary的记录数在
1000万以上。
注意编者认为合理的分区对于大表的查询性能提升和数据周期管理都有很大帮助
所以应该合理的使用分区表但是绝对不要过度分区也不要完全不用分区。
分区和列存的文件数
GP数据库在软件层面并未对文件数有任何限制所以总的文件数量需要控
制在什么范围主要取决于主机的配置和文件系统的性能。但是根据编者的实施经验
来看如果能将一个Instance的文件数控制在20万以下将是非常良好的状态相反
如果文件数达到100将会有很多问题随之而来比如IO性能下降
gprecoverseg -F的操作耗时过长(与同样容量但文件数较少的情况相比)
对于一个Instance来说一个分区表的文件数会受到分区数量的很大影响
其是列存分区表。比如一张分区表有400个子分区如果使用列存每个字段都需要
版权所有Esena(陈淼 ) 编写陈淼 - 404 -
Greenplum Database 管理员指南 V6.2.1
存储到一个单独的文件如果有100个字段那么这样一张分区表将产生4万个文
这对于一个Instance来说一个表就产生了4万个数据文件影响极大如果出
现了并发INSERT导致文件分裂的情况一个文件最多还会分裂成为128个文件也就
是说这样一张有100个字段的400个子分区的表在最严重的情况下最多可能会产
128万个数据文件。
要控制单个Instance的数据文件的数量从表设计的角度来说合理控制分区表
和列存的使用极其重要另外就是定期对系统的数据表文件数进行监控另外
VACUUMVACUUM FULL无法降低因为并发INSERT导致的文件数膨胀问题只有
REORGANIZE可以解决该问题。
索引
通常来说GP数据库不需要依赖索引来进行分析型场景的性能优化因为分析型
场景一般都是对大量数据进行分析可能是表中的全部数据或者很大比例的数据
这种情况下索引的存在并不会为数据过滤带来性能提升甚至说如果一定要用索
引来进行数据扫描反而可能会带来严重的性能问题。
由于GP已经是MPP架构在扫描一张数据表时所有Primary会并行扫描数据文
性能已经非常高如果全表扫描的性能可以满足业务要求那么尽量不要创建索
索引的维护也需要很高的代价包括磁盘空间IO性能资源和CPU的计算资源。
对于高选择性的查询可以在相关的字段上创建索引以提升查询的性能。如果这
种查询很少发生则创建索引的代价会远远超过带来的收益所以应该只为高选择性
且会多次使用的查询场景考虑使用索引来提升查询的性能。
应该通过检查执行计划和进行实际的业务测试来确认索引的效果如果发现索引的
存在并没有带来性能的提升那么应该删除该索引。
避免为高频更新的字段创建索引。索引字段的更新一定会导致索引的更新从而导
致索引的膨胀严重的甚至导致索引失效。
对于表达式索引要确保该索引的表达式能够在查询中经常被使用到应该通过
检查执行计划和进行实际的业务测试来确定表达式索引的确会带来性能的提升否则
不应该保留这样的索引。
对于条件索引如果在一个大表上经常会使用某方面特定范围的条件来过滤很少
的数据可以考虑建立一个条件索引这样将只会在满足条件范围的数据上创建索引。
避免索引的重叠因为在同一个字段上创建多个索引一定会使得索引维护的代
价更高却未必会带来性能的提升尤其是不同的索引开始的字段相同的情况是完
版权所有Esena(陈淼 ) 编写陈淼 - 405 -
Greenplum Database 管理员指南 V6.2.1
全多余的。
在返回少量结果的场景下索引同样可以改善压缩 AO 表上查询的性能当情况合
适时优化器会把索引作为获取数据的选择而不是一味的全表扫描。对于压缩数据来说
索引访问数据时只解压需要的记录而不是全表解压(最小单元的压缩块是要解压的)
应该为高选择性字段创建 B-tree 索引而不是 Bitmap 索引
对于加载数据量较大的场景应该考虑删除索引后再加载数据在完成数据加载后
重建索引。这个比较难找到一个确切的界限当需要加载的数据量不是很大也不是很
小时重建索引未必会比直接带索引加载更快。
对于经常需要被更新的字段不应该使用 Bitmap 索引。编者认为实际上 Bitmap
索引 GP 数据库中几乎没有存在的价值。
对于分区表尽量不使用索引如果必须使用索引一定要与分区字段不同。
总之不要过度的曲解索引的功能索引不是万能膏药在该用的时候用不该用
的时候不要用无效索引是对整个集群的各种资源的极大浪费。
更多关于使用索引的说明可以参见"GP中使用索引"章节。
资源组管理内存等资源
资源组是一种新的资源管理方式相比于资源队列可以精确的管理内存、CPU
和并发事务数量所以未来应该逐渐转向使用资源组来取代资源队列GP数据
库集群进行资源管理。
GP 数据库的内存配置
理论上来说内存是越多越好但实际情况是不可能总是增加内存所以有必
要对内存的使用进行必要的管理以尽可能的避免出现内存不足的情况。
使用资源组来管理GP数据库资源时以下是操作系统和GP数据库内存设置非常
重要的因素
vm.overcommit_memory
版权所有Esena(陈淼 ) 编写陈淼 - 406 -
Greenplum Database 管理员指南 V6.2.1
这是非常重要的Linux Kernel参数/etc/sysctl.conf配置文件中设置
该参数的值决定了操作系统如何对内存进行分配和管理。GP数据库要求
vm.overcommit_memory必须设置为2。对于overcommit的三种选择012
对应了不同的行为0允许适度的超限申请内存1允许无节制的超限申请内
2禁止超限申请内存。为什么GP要求配置为2因为对于01两种情况
都有可能会触发oom-killer一旦触发该行为将无法确保数据库主服务进程一
定不会被选中成为被kill的进程那将是十分危险的。
vm.overcommit_ratio
这是Linux Kernel参数/etc/sysctl.conf配置文件中设置决定了操作
系统可用内存的计算结果编者建议vm.overcommit_ratio的值设置为95。不
应该通过该参数来实际控制GP数据库的内存使用量而是应该通过GP数据库自身
GUC参数gp_resource_group_memory_limit的值来决定数据库的资源组
可用内存总量vm.overcommit_ratio的值设置为95只是为了使得操作系
统的可用内存的计算结果足够大但不是真的按照这个结果来计算GPGUC参数
gp_resource_group_memory_limit的值建议根据实际情况调整GUC参数
gp_resource_group_memory_limit的值。
gp_resource_group_memory_limit
资源组可用的内存占操作系统可用内存的百分比缺省为0.7(70%)。这里有个
问题在开启资源组的情况下内存限制不再受gp_vmem_protect_limit的控
而是受gp_resource_group_memory_limit的控制也就是说使用资源
队列时gp_vmem_protect_limit控制着单个Instance的总内存使用量使
用资源组时gp_resource_group_memory_limit控制着单个Instance的总
内存使用量。注意尤其在开启资源组时SWAP的配置显得尤为重要必须配置
为和物理内存固定的比值。
hugepage
要禁用hugepage特性。主机的内存分配的控制应该由GP数据库来统一管理。
gp_workfile_limit_files_per_query
可以通过控制GUC参数gp_workfile_limit_files_per_query的值来控制
一个查询在一个Primary上的溢出文件的个数如果设置为0就意味着对溢出文
件的数量不做任何的限制不过限制溢出文件的数量可以防止劣质的查询对系
统造成破坏性影响。编者建议不要修改这个参数或者如果要改就改小一些
以阻止更多的劣质查询对系统的影响。
gp_workfile_compression
版权所有Esena(陈淼 ) 编写陈淼 - 407 -
Greenplum Database 管理员指南 V6.2.1
GUC参数gp_workfile_compression用于控制溢出文件是否进行压缩存储
6之前的版本类似的参数为gp_workfile_compress_algorithm一般配置
zlib6版本中gp_workfile_compression是一个布尔型的参数一般
建议配置为on。缺省情况下溢出文件是不压缩的编者建议压缩。
memory_spill_ratio
开启资源组的情况下(通过 gpconfig 配置 gp_resource_manager group
来开启)如果 GUC 参数(或者资源组的属性)memory_spill_ratio 的值不为 0
的情况下语句的内存分配由资源组根据内存配额最大活动事务数和
memory_spill_ratio 参数的值来决定详情可以参见"算子内存配额"章节。
statement_mem
在开启资源组并且 memory_spill_ratio 为非零时语句的内存分配根据内
存配额最大活动事务数和 memory_spill_ratio 参数的值来决定。否则
statement_mem 决定计算方法参见"算子内存配额"章节。也就是说如果没
有开启资源组 statement_mem 决定如果开启了资源组
memory_spill_ratio 0仍由 statement_mem 决定。
编者不喜欢通过 memory_spill_ratio 的方式来控制内存如果所有的事务的
内存分配都通过这种方式来控制那么相当于总的内存量已经按照事先划分的资源组
和并发事务数量进行了定量分割但是实际的使用中是做不到所有时间都有这么多
的事务在运行而当某个任务需要更多的内存却无法获取到会造成内存资源的极大
浪费。编者还是更倾向于通过 statement_mem 来控制内存的分配允许有交叉重叠
允许总量超过内存总数但不是真的超过而是动态总的使用量保持小于内存总量
是一种相对安全的控制而不是绝对安全的控制。
在使用资源组时关于内存的考虑
资源组的可用内存会受到一些参数和设置的限制物理内存的尺寸SWAP的尺
vm.overcommit_ratiogp_resource_group_memory_limit的设置。要
确保GP数据库能够充分利用每个主机的内存资源可能需要调整这些参数
1. 操作系统的SWAP尺寸。
2. Linux Kernel参数vm.overcommit_ratio
3. 资源组GUC参数gp_resource_group_memory_limit
在使用资源组时资源组的可用内存总量不再受gp_vmem_protect_limit的控
版权所有Esena(陈淼 ) 编写陈淼 - 408 -
Greenplum Database 管理员指南 V6.2.1
而是与主机的物理内存总量和这3个参数有直接关系但是编者认为需要确保
资源组的可用内存总量不要超过物理内存总量。对于一个Primary来说所有资源
组可用内存的总量为
int(
(RAM × (vm.overcommit_ratio ÷ 100) + SWAP)
× gp_resource_group_memory_limit
÷ num_of_active_primary
)
配置资源组
GP数据库的资源组为资源管理和工作负载管理提供了更精确的控制。在配置
资源组时需要考虑以下一些原则
具有SUPERUSER权限的角色缺省会在admin_group资源组下运行。这是需要特
别注意的问题因为admin_group资源组的缺省最大活跃事务数量是10很多时
这个值可能无法满足所以应该合理的安排SUPERUSER的使用或者增加
admin_group资源组的最大活跃事务数量。
为每个非SUPSERUSER角色分配一个合适的资源组否则该角色将在
default_group资源组下运行。应该为不同类型的角色分配合适的资源组这样
便于对资源进行更精确的管理和控制。
通过资源组的CONCURRENCY属性来控制一个资源组上所有角色的最大活跃事务
数量。
GP数据库将未配额给资源组的内存(100减去所有资源组的MEMORY_LIMIT属性
)留作全局可共享内存。这部分内存对于所有的事务来说是先到先得。
可以根据资源组的负载情况动态的调整资源组的属性以及时的适应工作负载的
变化。对资源组的属性的修改是及时生效的数据库会动态的进行资源评估。
可以使用gp_toolkit模式中关于资源组的视图来监控资源组的使用情况。详情可
以参考"监控资源组状态"章节。
还可以通过GPCC的图形界面来实现资源组的创建和管理配置以及动态修改运行
中的事务的所属资源组。
版权所有Esena(陈淼 ) 编写陈淼 - 409 -
Greenplum Database 管理员指南 V6.2.1
低内存消耗型的查询
官方文档上说对于低内存消耗型的查询来说设置如下的参数可以提升查询的性
编者觉得有待验证至少编者认为这种操作可能没有特别显著的性能提升。
=# SET memory_spill_ratio=0;
=# SET statement_mem='10MB';
通过设置memory_spill_ratio0(实际上缺省值也是0资源组的该属性缺省
值也是0)来关闭资源组的内存管理模式内存分配以statement_mem参数的设置为
准。不过虽然说对于低内存消耗的查询来说设置较低的内存有可能提升性能
者理解应该也只是针对交易型的场景然而编者通过测试没有发现这个现象。
命令工具与 admin_group CONCURRENCY 属性
GP数据库为SUPERUSER配置的缺省资源组是admin_groupadmin_group缺省
CONCURRENCY属性是10也就是说缺省情况下在启用资源组时SUPERUSER
执行事务的最大并发是10超过10个并发事务也需要排队注意在启用资源组的
情况下SUPERUSER没有特殊待遇和普通角色一样都要受到资源组的资源限制。
有些数据库命令可能会运行较多的并发数比如gpbackup命令的--jobs比如
analyzedb命令的-p参数。所以对于这些情况可能需要临时增加admin_group
资源组的内存和CONCURRENCY的属性值或者根据日常执行这些命令的情况适当的
永久增加admin_group资源组的内存和CONCURRENCY的属性值编者建议应该适
当的永久增加admin_group资源组的CONCURRENCY属性值。
资源队列管理内存等资源
资源队列是GP数据库一直在使用的资源管理方式虽然有很多不足但已经伴随
GP这个产品很多年在并发控制和内存管理方面还是有着很重要的作用。资源组是
一种全新的资源管理方式在内存控制CPU压制和并发事务控制方面都有了很大的
增强所以未来应该逐渐转向使用资源组来取代资源队列。
版权所有Esena(陈淼 ) 编写陈淼 - 410 -
Greenplum Database 管理员指南 V6.2.1
GP数据库中内存管理对性能的影响很大缺省的内存设置已经可以满足大
多数的场景所以在搞清楚内存管理机制之前最好不要修改缺省的内存管理设置。
也就是说缺省使用资源队列来管理内存如果资源队列可以满足要求或者还没有理
解资源组的内存管理机制不应该马上修改为资源组的方式。
解决内存不足的报错
内存不足的报错是有分类的比如下面这两种属于gp_vmem_protect_limit
耗尽的报错
ERROR: Out of memory
(seg0 slice3 192.168.137.66:40000 pid=17836)
DETAIL: VM Protect failed to allocate 33554488 bytes, 31 MB available
这种属于 gp_vmem_protect_limit 剩余可用内存已经无法满足内存分配的需求。
ERROR: Canceling query because of high VMEM usage. Used: 78MB, available
8MB, red zone: 90MB
这种属于所需内存达到了gp_vmem_protect_limit的红线(90%)语句被终止。
注意上述两种情况都是属于gp_vmem_protect_limit参数设置的限制用超了
如果gp_vmem_protect_limit参数是按照物理内存的0.9倍为基准来配置的那么
就不要在gp_vmem_protect_limit参数上动脑筋了这个参数不能设置过大设置
过大就会遭遇接下来要说的系统OOM报错了剩下能做的事情就是试试如何降低内
存的使用需求或者增加物理内存也不要试图用SWAP来冒充物理内存因为性能差
了几个数量级。
下面这种属于操作系统报出的OOM错误
ERROR: Out of memory
(seg0 slice3 192.168.137.66:40000 pid=23729)
VM protect failed to allocate 33554488 bytes from system, VM Protect 1269
MB available
这种情况一般是gp_vmem_protect_limit的设置超出了操作系统的可用内存
上限。也就是说gp_vmem_protect_limit的限制还没有到却已经无法从操作系
统获取内存说明gp_vmem_protect_limit参数的设置太大了。
GP数据库出现内存不足的一些常见原因有
可用的系统内存不足。就是内存配置的太低了现在主流的生产机器的配置单机
一般物理内存至少达到256GB。内存低还想多并发执行大数据量的复杂任务
版权所有Esena(陈淼 ) 编写陈淼 - 411 -
Greenplum Database 管理员指南 V6.2.1
那是不可能的违背自然规律了。
内存相关的参数配置不正确。gp_vmem_protect_limit参数的配置要符合系统
的内存资源现状既不能太小也不能太大太小内存资源利用不足太大
易出现操作系统报OOM错误。编者建议按照物理内存的0.9倍为基准来配置
gp_vmem_protect_limit参数的值。
数据倾斜。
计算倾斜。
解决内存不足报错的一些方法
SQL调优以减少内存的使用量。虽然很多时候会被技术人员抗拒但是在其他
优化调整已经没招的情况下如果必须在SQL优化和增加硬件之间选择没有一个
决策者会优先选择增加硬件因为硬件没有终点SQL调优往往可能会节省一
大笔的硬件投资SQL写的烂还硬要把锅甩给硬件和数据库自己是不是有点尴
尬。任何数据库都需要SQL调优只有不懂数据库的技术人员才会持有不同意见
SQL设计的初衷是给专业计算机技术人员使用的。
确认gp_vmem_protect_limit参数的配置是否合理。编者建议按照物理内存的
0.9倍为基准来配置gp_vmem_protect_limit参数的值。
对资源队列设置内存使用量的限制从而限制资源队列中的查询语句使用的内存
量。过低的内存分配会影响任务的处理性能应该在并发数控制方面多考虑。
降低业务的并发数。系统最终追求的目标是单位时间内完成的任务数量过高的
并发只会导致资源的严重争抢从而导致单位时间内完成了更少的任务数量。
在会话级别降低statement_mem参数以减少内存的使用量。编者认为这一
点比较难做到尤其是大规模的复杂系统出现内存不足之后再考虑从会话级别
降低statement_mem参数的值比较困难。
在数据库级别降低statement_mem参数的值。这个很容易实现直接通过ALTER
DATABASE命令即可修改数据库级别的参数值。
降低GP集群中每个计算主机上Primary的数量。这个也是难以操作因为需要重
建集群几乎不可能做得到。
增加物理内存。这个虽然不然容易但是如果物理内存的确太少而其他方法又
难以完全实现最终目标还是应该考虑增加物理内存物理内存太低的话很难有
什么办法既不降低计算性能又不降低并发处理能力还能避免内存不足的报错
这违背自然规律了。
版权所有Esena(陈淼 ) 编写陈淼 - 412 -
Greenplum Database 管理员指南 V6.2.1
集群扩容增加计算主机的数量不会从本质上缓解内存不足的问题因为每个查询
消耗的内存量受到statement_mem参数的控制不过如果增加了计算主机的数量
可以降低每个计算主机的数据量的话可以降低statement_mem参数的值这样可以
缓解内存不足问题或者在增加计算主机数量的时候减少每个计算主机的Primary
的个数从而可以增加gp_vmem_protect_limit的值也可以缓解内存不足的问题。
低内存消耗型的查询
官方文档上说对于低内存消耗型的查询来说设置如下的参数可以提升查询的性
编者觉得有待验证至少编者认为这种操作可能没有特别显著的性能提升。
=# SET statement_mem='2MB';
虽然说对于低内存消耗的查询来说设置较低的内存有可能提升性能编者理解
应该也只是针对交易型的场景然而编者通过测试没有发现这个现象。
GP 数据库进行内存配置
如果能够深入理解GP的内存管理方法绝大部分的内存不足的报错是可以避免
的。在增加物理内存比较困难的时候通过正确的进行内存相关的参数配置结合资源
队列的控制可以有效缓解和防止出现内存不足的报错。
还需要注意一点当发生故障切换时Mirror会切换为Primary并承担处理任
同样需要消耗内存所以在进行内存规划时也需要考虑到这个因素。但是
者认为绝大部分时间Mirror在处于Mirror状态时是不需要消耗内存的所以
不应该将物理内存为可能发生切换的Mirror做预留而是要依赖SWAP来做保障这也
是编者一直强调SWAP的尺寸要与Mirror策略保持一致的原因一般的通用方案是
SWAP的尺寸与RAM相等。因此在配置内存参数时vm.overcommit_ratio设置
95确保系统可用内存的总量接近理论最大值而在配置
gp_vmem_protect_limit只考虑物理内存和Primary的关系剩余的可用内存
其实都是SWAP提供的Mirror切换为Primary有足够的保障同时并不是
任何时候内存的使用量都是很高的SWAP只是一种保障。
下面是操作系统和GP数据库的内存配置方面的建议
要禁用hugepage特性。主机的内存分配的控制应该由GP数据库来统一管理。
版权所有Esena(陈淼 ) 编写陈淼 - 413 -
Greenplum Database 管理员指南 V6.2.1
vm.overcommit_memory
这是非常重要的Linux Kernel参数/etc/sysctl.conf配置文件中设置
该设置决定了操作系统如何对待进行内存分配的管理。GP数据库要求
vm.overcommit_memory必须设置为2。对于overcommit的三种选择012
对应了不同的行为0允许适度的超限申请内存1允许无节制的超限申请内
2禁止超限申请内存。为什么GP要求配置为2因为对于01两种情况
都有可能会触发oom-killer一旦触发该行为将无法确保数据库主服务进程一
定不会被选中成为被kill的进程那将是十分危险的。
vm.overcommit_ratio
这是Linux Kernel参数/etc/sysctl.conf配置文件中设置决定了操作
系统可用内存的计算结果编者建议vm.overcommit_ratio的值设置为95。不
应该通过该参数来实际控制GP数据库的内存使用量在开启资源队列的情况下
应该通过GP数据库自身的GUC参数gp_vmem_protect_limit的值来决定数据
库的内存使用量vm.overcommit_ratio的值设置为95只是为了使得操作
系统的可用内存的计算结果足够大但不是真的按照这个结果来计算GPGUC参数
gp_vmem_protect_limit的值。
gp_vmem_protect_limit
gp_vmem_protect_limit参数用于限制在开启资源队列的情况下一个
Instance的最大使用内存的总量如果设置过大将会导致出现操作系统内存不
足的报错设置过小又会导致内存利用不足。编者建议按照物理内存的0.9倍为
基准来配置gp_vmem_protect_limit参数的值。
runaway_detector_activation_percent
4.3.4版本开始引入的新GUC参数用于控制查询以防止出现内存不足的情况。
runaway_detector_activation_percent参数控制的是
gp_vmem_protect_limit使用到多少百分比时触发查询终止。缺省值为90
90%gp_vmem_protect_limit使用量达到90%数据库将开始终止查
从内存消耗量最大的查询开始终止一直到gp_vmem_protect_limit的使
用量低于指定的百分比为止。
一般来说不需要修改此参数如果出现了内存不足的报错应该寻求提升内存配
或者降低内存使用量。
statement_mem
编者认为statement_memgp_vmem_protect_limit参数和最大并发查询
的数量这两个参数之间并没有严格的等式关系并不是说statement_mem的值
一定不能超过[(gp_vmem_protect_limit × 0.9) ÷ 最大并发查询的数量]
版权所有Esena(陈淼 ) 编写陈淼 - 414 -
Greenplum Database 管理员指南 V6.2.1
计算的结果因为很多时候内存的真实使用量并不大。根据编者的经验可以
通过持续多日的对系统资源进行统计确定系统的最高活跃内存百分比比如
statement_mem使用的是缺省的125MB的情况下统计发现系统的最高活跃内
存百分比为30%那么statement_mem设置为125MB3倍是安全的用真
实的数据来推导出一个合理的值总是比通过公式计算出的结果更实用。
gp_workfile_limit_files_per_query
可以通过控制GUC参数gp_workfile_limit_files_per_query的值来控制
一个查询在一个Primary上的溢出文件的个数如果设置为0就意味着对溢出文
件的数量不做任何的限制不过限制溢出文件的数量可以防止劣质的查询对系
统造成破坏性影响。编者建议不要修改这个参数或者如果要改就改小一些
以阻止更多的劣质查询对系统的影响。
gp_workfile_compression
GUC参数gp_workfile_compression用于控制溢出文件是否进行压缩存储
6之前的版本类似的参数为gp_workfile_compress_algorithm一般配置
zlib6版本中gp_workfile_compression是一个布尔型的参数一般
建议配置为on。缺省情况下溢出文件是不压缩的。
配置资源队列
资源队列GP数据库的资源管理和控制提供了保障资源队列最常用的功能是
控制活跃查询的数量还可以用于控制查询语句的内存使用量。在开启资源队列的情况
当一个查询被提交到数据库其资源会受到所在资源队列的限制数据库将根据资
源队列的资源情况来决定是否执行SQL马上执行还是排队等等。
所有的角色都应该设置合理的资源队列。
每个角色都与一个资源队列相关连在开启资源队列的情况下任何查询都需要经
过资源队列才能得到执行(SUPERUSER不受资源队列的限制)如果没有为角色指
定资源队列缺省将分配到pg_default资源队列。
不用使用gpadmin用户或者具有SUPERUSER权限的角色执行业务查询。
SUPERUSER是完全不受资源队列限制的所以SUPERUSER执行的业务查询
是直接被执行这将不利于资源的管理和控制。
使用ACTIVE_STATEMENTS属性来控制资源队列中所有角色同时执行查询语句
的数量。
版权所有Esena(陈淼 ) 编写陈淼 - 415 -
Greenplum Database 管理员指南 V6.2.1
使用MEMORY_LIMIT属性来控制资源队列中所有查询的总的内存使用量。一般结
ACTIVE_STATEMENTS属性来使用建议不要结合MAX_COST来使用。当与
ACTIVE_STATEMENTS结合使用时缺省每个语句获得的内存为MEMORY_LIMIT
/ ACTIVE_STATEMENTS。当与MAX_COST结合使用时缺省的内存分配为
MEMORY_LIMIT * (query_cost / MAX_COST)。推荐与ACTIVE_STATEMENTS
结合使用而不是与MAX_COST结合使用因为cost的评估很多时候会严重失准
这样将会严重影响内存分配的合理性。
关于资源队列的优先级设置几乎没有实际意义。使用资源队列主要还是用于控制
并发查询的数量。
使用gp_toolkit模式中资源队列相关的视图来查看资源队列的状态。详情请参
"检查资源队列状态"章节。
编者认为资源队列最重要的作用是控制并发查询的数量当然有时候
MIN_COST 属性也非常好用可以将一些小查询直接放行提升资源控制的灵活性。
版权所有Esena(陈淼 ) 编写陈淼 - 416 -

 

 

 

 

 

 

 

Content      ..     7      8      9