首页 > 代码库 > 用HAWQ轻松取代传统数据仓库(十七) —— 最佳实践
用HAWQ轻松取代传统数据仓库(十七) —— 最佳实践
一、HAWQ参数配置最佳实践
(原文地址:http://hawq.incubator.apache.org/docs/userguide/2.1.0.0-incubating/bestpractices/config_hawq_bestpractices.html)在$GPHOME/etc/hawq-site.xml文件中维护HAWQ的配置参数。该文件存在于所有HAWQ实例上,并可以通过Ambari或使用HAWQ命令行接口进行修改。使用一致的策略(Ambari或命令行接口)维护hawq-site.xml文件的内容。
对于Ambari管理的集群,始终使用Ambari配置hawq-site.xml文件中的参数;任何从Ambari外对hawq-site.xml参数所做的配置改变,都将被通过Ambari重启或重新配置HAWQ所覆盖。
如果你使用命令行工具代替Ambari管理你的集群,使用一致的hawq-site.xml文件配置你的整个集群。
注意:不要通过postgresql.conf文件配置HAWQ参数。只使用hawq-site.xml配置你的HAWQ集群。hawq-site.xml中定义的任何参数将覆盖postgresql.conf里的参数。
二、HAWQ操作最佳实践
(原文地址:http://hawq.incubator.apache.org/docs/userguide/2.1.0.0-incubating/bestpractices/operating_hawq_bestpractices.html)本主题提供操作HAWQ的最佳实践,包括推荐的HAWQ的停止、启动和监控。
1. 使用命令行启动/停止HAWQ集群成员最佳实践
以下最佳实践是使用hawq start和hawq stop管理你的HAWQ集群时所推荐的。- 始终使用HAWQ管理命令启动和停止HAWQ,而不用等价的Postgres。
- 使用hawq start cluster或hawq restart cluster启动整个集群,而不要分别启动master和单个segments。
- 如果你决定使用hawq start standby|master|segment分别启动节点,总是在主master前先启动从master。否则,从有可能与主master不同步。
- 停止集群时,发出CHECKPOINT命令更新并将所有数据文件刷新到磁盘,并在停止集群前更新日志文件。倘若发生崩溃,检查点可以保证文件能够从检查点快照中还原。
- 通过在master主机上停止集群,停止整个HAWQ系统:
host: shell $ hawq stop cluster
- 要停止segment并杀掉任何正在执行的查询,同时不引起数据丢失或不一致等问题,在集群上使用fast或immediate模式:
$ hawq stop cluster -M fast $ hawq stop cluster -M immediate
- 使用hawq stop master仅停止master。如果你因为运行的事务而不能停止master时,尝试使用fast关闭。如果fast关闭不能工作,使用immediate关闭。使用immediate关闭要小心,因为它在系统重启时会导致运行崩溃恢复。
$ hawq stop master -M fast $ hawq stop master -M immediate
- 停止一个segment或所有segment时,你可以使用缺省的smart模式。在segment上使用fast或immediate模式是无效的,因为segment是无状态的。
$ hawq stop segment $ hawq stop allsegments
2. 集群扩展指南
本主题提供围绕HAWQ集群扩展的一些指南。给你的正在运行的HAWQ集群扩容时,牢记以下这些建议:
- 当你增加一个新节点时,在新节点上安装DataNode和一个物理segment。
- 新增节点后,你都应该重新平衡HDFS数据,以维护集群性能。
- 增加或移除节点还需要更新HDFS元数据的缓存。这个更新将在最后发生,但可能要花些时间。为了加快更新元数据缓存的速度,执行select gp_metadata_cache_clear();。
- 注意,对于哈希分布表,扩展集群不会立即提升性能,因为哈希分布表使用固定数量的虚拟段。为了使哈希分布表获得更好的性能,你必须在更新后的集群上使用ALTER TABLE或CREATE TABLE AS命令重新分布表。
- 如果你使用哈希表,集群扩展后,重新分布哈希表之前,考虑将default_hash_table_bucket_number服务器配置参数修改为一个更大的值。
3. HAWQ系统监控最佳实践
下面章节提供常见监控任务的建议。注意:如果你的集群从Ambari界面进行管理,使用Ambari执行建议的监控任务。
(1)数据库状态监控活动
活动 | 过程 | 改进措施 |
列出当前宕掉的segment。如果返回行,应该生成一个警告或警报。 推荐频率:每隔5到1-分钟运行一次 重要性:重要 | 在postgres数据库中运行下面的查询:
SELECT * FROM gp_segment_configuration WHERE status <> ‘u‘; | 如果查询返回行,执行下面这些步骤修改问题: 1. 核实宕掉segment的主机有响应。 2. 如果主机没问题,在pg_log文件中检查宕掉的segment,找到该segment宕掉的根本原因。 |
(2)硬件和操作系统监控
活动 | 过程 | 改进措施 |
维护需求或硬件系统故障的底层平台检查。 推荐频率:如果可能,实时,或者每15分钟 重要性:非常重要 | 构建用于硬件和操作系统错误的系统检查。 | 如果有必要,从HAWQ集群中移除机器,解决硬件和操作系统问题,问题解决后再加回集群中。 |
检查用于HAWQ数据存储和操作系统的磁盘空间使用量。 推荐频率:每5到30分钟 重要性:非常重要 | 建立磁盘空间检查。 . 设置阈值,当磁盘到达一个容量百分比时发出警告。推荐的阈值为总容量的75% . 不推荐在接近容量100%的系统上运行系统。 | 删除数据或文件释放系统空间。 |
检查丢包等网络问题。 推荐频率:每小时 重要性:重要 | 建立网络检查。 | 与网络或系统管理团队一起解决问题。 |
检查RAID错误或RAID性能下降。 推荐频率:每5分钟 重要性:非常重要 | 建立RAID检查。 | . 尽快替换失效磁盘。 . 尽快与系统管理团队一起解决其它RAID或控制器问题。 |
检查I/O带宽是否充足和I/O倾斜。 推荐频率:创建集群或怀疑有硬件问题时 | 运行HAWQ的hawq checkperf应用。 | 如果数据传输速率与下面的不相似,集群可能I/O带宽不足: . 每秒2GB磁盘读 . 每秒1GB磁盘读 . 每秒10Gb网络读写 如果传输率低于预期,与你的数据架构师协商期望的性能。 如果集群中的机器显示出不平衡的性能表现,与系统管理员团队一起修复有故障的机器。 |
(3)数据维护
活动 | 过程 | 改进措施 |
检查缺少统计信息的表。 | 检查每个数据库的hawq_stats_missing视图: SELECT * FROM hawq_toolkit.hawq_stats_missing; | 在缺少统计的表上运行ANALYZE。 |
(4)数据库维护
活动 | 过程 | 改进措施 |
标记HAWQ系统目录里(pg_catalog模式下的表)删除的行,以重用它们占用的空间。 推荐频率:每天 重要性:非常重要 | 清理每个系统目录: VACUUM <table>; | 定期清理系统目录,防止膨胀。 |
更新表统计。 推荐频率:装载数据后,执行查询前。 重要性:非常重要 | 分析用户表: ANALYZEDB -d <database> -a | 定期分析更新的表,使得优化器可以产生高效的查询执行计划。 |
备份数据库数据。 推荐频率:每天,或者按照你备份计划的要求 重要性:非常重要 | 参考Backing up and Restoring HAWQ Databases讨论的备份过程。 | 最佳实践有一个当前备份,用于数据库必须还原的情况。 |
推荐频率:每周或更短周期,如果数据库对象的创建与删除很频繁 重要性:非常重要 | 在每个数据库中运行REINDEX SYSTEM。 REINDEXDB -s | 优化器从系统表查询信息创建查询计划。如果系统表随时间不断膨胀,扫描系统表增加查询执行时间。 |
(5)补丁与升级
活动 | 过程 | 改进措施 |
确保任何修复的bug和改进应用到内核中。 推荐频率:至少每6个月 重要性:重要 | 按照供应商的指示更新Linux内核。 | 保持当前内核包含bug修复和安全修复,避免将来升级困难。 |
安装HAWQ次版本。 推荐频率:每季度 重要性:重要 | 总是升级到最新的系列。 | 保持你的HAWQ集群包含HAWQ软件当前的bug修复、性能提升和改进特性。 |
三、HAWQ安全最佳实践
(原文地址:http://hawq.incubator.apache.org/docs/userguide/2.1.0.0-incubating/bestpractices/secure_bestpractices.html)为了安全部署你的HAWQ,参考本主题所列的建议。
- 建立SSL,加密你的客户端服务器信道。参见Encrypting Client/Server Connections。
- 只在HAWQ master上配置pg_hba.conf,而不要在segment上配置它。注意:对于更安全的系统,考虑删除所有从你的master pg_hba.conf使用授信认证的连接。授信认证意味着角色不需要任何认证就被授予访问权限,因此绕过所有安全保护。如果你的系统具有身份识别服务,用身份认证替换授信认证条目。
四、资源管理最佳实践
(原文地址:http://hawq.incubator.apache.org/docs/userguide/2.1.0.0-incubating/bestpractices/managing_resources_bestpractices.html)本节描述HAWQ中的资源管理最佳实践。
1. 资源管理配置最佳实践
配置资源管理时,你可以应用某些最佳实践保证高效管理资源和最好的系统性能。下面是优化资源管理的高级最佳实践列表:
- 确保segment没有相同的IP地址。参见Segments Do Not Appear in gp_segment_configuration对此问题的说明。
- 所有segment配置相同的资源配额。参见Configuring Segment Resource Capacity。
- 为防止资源碎片,确保你部署的segment资源配额(独立模式)或者YARN节点的资源配额(YARN模式)是所有虚拟段资源限额的倍数。参见Configuring Segment Resource Capacity(HAWQ独立模式)和Setting HAWQ Segment Resource Capacity in YARN。
- 确保有足够的可用注册segment用于查询的资源请求。如果不可用或没有注册的segment数量高于设置的限制,那么查询的资源请求被拒绝。还要保证跨物理segment分配的虚拟段偏差不高于配置的限制。参见Rejection of Query Resource Requests。
- 在独立的大硬盘(2TB或以上)上建立多个master和segment临时目录,使写临时文件(例如,/disk1/tmp /disk2/tmp)的负载均衡。对于给定的查询,HAWQ将为每个虚拟段使用一个独立的临时目录(如果可用)存储溢出文件。多个HAWQ会话也是用独立的临时目录避免磁盘争用。如果你配置的临时目录太少,或者在同一磁盘上建立了多个临时目录,当多个虚拟段指向同一磁盘时,会增加磁盘竞争或者磁盘空间被占满的风险。
- 在YARN中配置最小资源等级,并调整空闲资源返还YARN的超时时间。参见Tune HAWQ Resource Negotiations with YARN。
- 保证yarn-site.xml中的yarn.scheduler.minimum-allocation-mb属性值能被1GB整除。例如1024、512。
2. 资源队列使用最佳实践
资源队列的设计和配置依赖于你部署的业务需要。本节描述不同业务场景中创建和修改资源队列的最佳实践。(1)为过载HDFS修改资源队列
高并发HAWQ查询可能造成HDFS过载,尤其是在查询分区表时。使用资源队列的ACTIVE_STATEMENTS属性限制并发语句数。例如,如果一个外部应用执行多于100的并发查询,那么在你的资源队列中限制活跃语句数量,将指示HAWQ资源管理器限制HAWQ里的实际并发语句数。你可能希望如下修改一个已有的资源队列:
ALTER RESOURCE QUEUE sampleque1 WITH (ACTIVE_STATEMENTS=20);在该场景下,当这个DDL应用到sampleque1队列,使用该队列的角色必须等到正在运行的语句不多于20个时再执行他们的查询。因此,队列里的80个查询将等待以后执行。限制活跃语句数量有助于控制和保护HDFS的资源使用。你甚至能够在资源队列忙碌时修改其并发数。例如,如果一个队列已经有40个并行的语句,此时你使用DDL语句指定ACTIVE_STATEMENTS=20,则该资源队列暂停为查询分配资源,直到多于20个语句已经返还它们的资源。
(2)隔离并保护生产环境工作负载
另一个最佳实践是使用资源队列隔离你的工作负载。工作负载隔离防止你的生产环境资源匮乏。为了建立这种隔离,通过为特定目的创建角色来划分工作负载。例如,你可以为线上生产验证环境创建一个角色,而为正常运行的生产过程建立另一个角色。
在这种场景中,让我们为正式线上工作负载赋予role1,线上软件验证服务role2。我们可以定义以下资源队列,它们有同一个为整个部门定义的父队列dept1que。
CREATE RESOURCE QUEUE dept1product WITH (PARENT=‘dept1que‘, MEMORY_LIMIT_CLUSTER=90%, CORE_LIMIT_CLUSTER=90%, RESOURCE_OVERCOMMIT_FACTOR=2); CREATE RESOURCE QUEUE dept1verification WITH (PARENT=‘dept1que‘, MEMORY_LIMIT_CLUSTER=10%, CORE_LIMIT_CLUSTER=10%, RESOURCE_OVERCOMMIT_FACTOR=10); ALTER ROLE role1 RESOURCE QUEUE dept1product; ALTER ROLE role2 RESOURCE QUEUE dept1verification;用这些资源队列定义,工作负载通过资源队列划分如下:
- 在role1和role2都有工作负载时,测试验证工作负载获得dept1que资源总配额10%,剩余90%的dept1que资源配额用于运行生产工作负载。
- 当role1有工作负载但role2空闲时,则100%的dept1que资源都用于生产工作负载。
- 当只有role2有工作负载时(例如,调度的测试窗口期间),则100%的dept1que资源也可以用于测试。
另外,你可以使用资源队列隔离不同部门或不同应用的工作负载。例如,我们能使用下面的DDL语句定义三个部门,管理员也可以随意重新分配各部门之间的资源分配。
ALTER RESOURCE QUEUE pg_default WITH (MEMORY_LIMIT_CLUSTER=10%, CORE_LIMIT_CLUSTER=10%); CREATE RESOURCE QUEUE dept1 WITH (PARENT=‘pg_root‘, MEMORY_LIMIT_CLUSTER=30%, CORE_LIMIT_CLUSTER=30%); CREATE RESOURCE QUEUE dept2 WITH (PARENT=‘pg_root‘, MEMORY_LIMIT_CLUSTER=30%, CORE_LIMIT_CLUSTER=30%); CREATE RESOURCE QUEUE dept3 WITH (PARENT=‘pg_root‘, MEMORY_LIMIT_CLUSTER=30%, CORE_LIMIT_CLUSTER=30%); CREATE RESOURCE QUEUE dept11 WITH (PARENT=‘dept1‘, MEMORY_LIMIT_CLUSTER=50%,CORE_LIMIT_CLUSTER=50%); CREATE RESOURCE QUEUE dept12 WITH (PARENT=‘dept1‘, MEMORY_LIMIT_CLUSTER=50%, CORE_LIMIT_CLUSTER=50%);
(3)用大内存查询Parquet表
你可以使用大内存的资源队列提升Parquet表的查询性能。此类查询需要给虚拟段大的内存限额。因此,如果一个角色主要使用大内存查询Parquet表,修改角色相关的资源队列增加它的虚拟段资源限额。例如:
ALTER RESOURCE queue1 WITH (VSEG_RESOURCE_QUOTA=‘mem:2gb‘);如果只是偶尔用大内存查询Parquet表,使用语句级指定代替修改资源队列。例如:
SET HAWQ_RM_STMT_NVSEG=10; SET HAWQ_RM_STMT_VSEG_MEMORY=‘2gb‘; query1; SET HAWQ_RM_STMT_NVSEG=0;
(4)限制特定查询的资源消耗
通常,HAWQ资源管理器试图给当前查询提供尽可能多的资源,以获得高性能查询。然而,与一个复杂大查询相关的资源队列可能使用很多虚拟段,造成其它资源队列和查询资源不足。这种情况下,你应该启用与大查询相关资源队列的nvseg限制。例如,你可以指定所有查询都不能使用多于200的虚拟段。为实现此限制,如下修改资源队列:
ALTER RESOURCE QUEUE queue1 WITH (NVSEG_UPPER_LIMIT=200);如果我们希望根据不同的集群大小动态设置此限制,我们也以使用下面的语句。
ALTER RESOURCE QUEUE queue1 WITH (NVSEG_UPPER_LIMIT_PERSEG=10);这样设置后,入股你有一个10节点的集群,实际限制是100。如果集群扩展到20个节点,限制自动增加到200。
(5)确保个别语句的资源分配
一般而言,给一条语句分配的最少虚拟段数量由资源队列的实际配额及其并行度设置所决定。例如,如果集群有10个节点,总的资源配额是640GB和160核,那么一个有20%配额的资源队列拥有128GB(640 * 0.2)和32核(160 * 0.2)。如果虚拟段限额设置为256MB,则此队列将分配512个虚拟段(128GB/256MB=512)。如果该队列的ACTIVE_STATEMENTS并行度设置为20,则为每个查询分配的最少虚拟段数量是25(trunc(512/20)=25)。但这个最少虚拟段数是一个软限制。如果查询语句只需要5个虚拟段,那么这个25的最少数量被忽略,因为没必要为这个语句分配25个虚拟段。
为了增加一个查询语句的虚拟段最少数量,有两个选项:
- 选项1:修改资源队列降低并行度。这是为实现目标推荐的方法。例如:
ALTER RESOURCE QUEUE queue1 WITH (ACTIVE_STATEMENTS=10); 如果原始的并行度为20,则最少虚拟段数量会翻倍。
- 选项2:修改资源队列的nvseg限制。例如:
ALTER RESOURCE QUEUE queue1 WITH (NVSEG_LOWER_LIMIT=50); 或者: ALTER RESOURCE QUEUE queue1 WITH (NVSEG_LOWER_LIMIT_PERSEG=5); 在一个10节点的集群中,第二条DDL实际的最少虚拟段数量是50(5 * 10 = 50)。
五、数据管理最佳实践
(原文地址:http://hawq.incubator.apache.org/docs/userguide/2.1.0.0-incubating/bestpractices/managing_data_bestpractices.html)本节描述在HAWQ中建立数据库、装载数据、数据分区以及数据恢复的最佳实践。
1. 数据装载最佳实践
由于NameNodes和DataNodes上能够为写入而同时打开文件的数量限制,向HDFS中装载数据是个挑战。为了获得数据装载时的最佳性能,遵守以下最佳实践:
- 一个NameNode典型的并发连接数不应超过50000,每个DataNode打开的文件数不应超过10000。如果超过这些限制,NameNode和DataNode可能过载并变慢。
- 如果表的分区很多,推荐的分区表数据装载方式是逐个分区装载数据。例如,你可以使用下面的查询只向一个分区装载数据:
INSERT INTO target_partitioned_table_part1 SELECT * FROM source_table WHERE filter filter只选择目标分区的数据。
- 为减轻NameNode的负载,你可以减少每个节点使用的虚拟段数量。这可以在语句级或资源队列级进行设置。更多信息参见Configuring the Maximum Number of Virtual Segments。
- 使用资源队列限制查询负载和读查询并行度。
2. 数据分区最佳实践
并不是所有表都适合分区。如果以下问题的所有或大部分答案是yes,分区表对于提高查询性能是可行的数据库设计。如果下面问题的回答大部分是no,分区表不是正确的解决方案。测试你的设计策略以保证预期的查询性能提升。- 表是否足够大?大的事实表是好的分区候选者。如果你的一个表中有数百万或数十亿的记录,你可以从逻辑地将数据分解成更小的块看到性能收益。对于只有几百行或更少记录的小表,维护分区的管理消耗会超过任何可见的性能好处。
- 性能是否表现欠佳?与任何性能调整建议一样,只有表上查询的响应时间超过可接受的时才应该分区。
- 你的查询谓词中有可识别的访问模式吗?检查你的查询负载中的WHERE子句,找到查找始终用于访问数据的表列。例如,如果你的大部分查询都通过日期查找数据,那么按月或周的日期分区设计可能是有益的。如果你要通过地区访问记录,考虑一个列表分区设计,以地区划分表。
- 是否需要维护一个数据仓库的历史数据窗口?分区设计考虑的另一个问题是组织的维护历史数据的业务需求。例如,你的数据仓库可能需要你保留过去12个月的数据。如果数据按月分区,你可以轻易从数据仓库中删除最老的月份分区,并将当前数据装载到最近的月份分区中。
- 根据分区定义条件,是否每个分区的数据量基本相同?选择尽可能平均划分数据的条件作分区。如果分区包含基本相同的记录数,ch查询性能的提升基于创建的分区数量。例如,将一个大表分成10个分区,当提供的分区设计支持查询条件时,查询将比非分区表快10倍。
除非查询优化器能够基于查询谓词消除分区,否则分区不能提升查询性能。扫描每个分区的查询比非分区表更慢,因此当只有很少的查询满足分区消除时,要避免进行分区。检查查询的解释计划确认分区被消除。更多分区消除信息参见Query Profiling。
多级分区要非常仔细,因为分区文件数量会快速增长。例如,如果一个表通过日期和城市分区,有1000和日期数据和1000个城市,则总的分区数是一百万。面向列的表每列存储在一个物理表中,因此如果该表有100列,系统需要管理一亿个表文件。
六、数据查询最佳实践
(原文地址:http://hawq.incubator.apache.org/docs/userguide/2.1.0.0-incubating/bestpractices/querying_data_bestpractices.html)为在HAWQ中查询数据时获得最好的性能,回顾本节描述的最佳实践。
1. 影响查询性能的因素
查询使用的虚拟段数量直接影响查询性能。以下因素可能影响查询的并行度:- 查询成本。小查询使用更少的虚拟段,大查询使用更多的虚拟段。定义资源队列使用的某些技术可以影响为查询分配的虚拟段数和一般资源。更多信息参见Best Practices for Using Resource Queues。
- 查询时可用的资源。如果查询队列中有更多的可用资源,这些资源将被使用。
- 哈希表桶数。如果查询只包含哈希分布表,查询并行度在以下情况下是固定的(等于哈希表的桶数):所有哈希表配置的桶数(bucketnum)相同;随机表大小不大于为哈希表分配的大小的1.5倍。否则,虚拟段数量依赖于查询成本:查询哈希分布表的行为与查询随机分布表类似。
- 查询类型。对引用用户定义函数或外部表的查询,其资源成本估算是困难的。这类查询的虚拟段数由hawq_rm_nvseg_perquery_limit和hawq_rm_nvseg_perquery_perseg_limit参数,以及外部表定义的ON子句和位置列表所控制。如果查询结果是哈希表(例如INSERT into hash_table),虚拟段数必须等于结果哈希表的桶数。如果查询以应用模式执行,例如COPY和ANALYZE操作,虚拟段数通过不同策略计算。
更多细节参见Query Performance。
2. 检查查询计划解决问题
如果查询性能差,查看它的执行计划问下列问题:- 计划中的操作是否使用了异常长的时间?找到最消耗查询处理时间的一个操作。例如,哈希表的扫描时间出乎意料的长,可能是由于数据本地化程度低;重新装载数据可能提高数据本地化并加速查询。或者调整enable_<operator>参数,查看是否能通过禁用查询的特殊查询计划操作,强制使用遗留优化器(planner)选择不同的计划。
- 查询优化器的估算是否与实际的相近?运行EXPLAIN ANALYZE,检查优化器估算的行数是否与查询实际返回的函数相似。如果相差很多,收集更多相关列的统计。
- 是否在计划的早期应用了过滤谓词?在计划早期应用最具选择性的过滤,使得计划树向上移动的行更少。如果查询计划错误地估计了查询谓词的选择性,收集更多相关表列的统计。你也可以尝试改变SQL语句中WHERE子句中列的顺序。
- 查询优化器是否选择了最好的连接顺序?当查询连接多个表时,确保优化器选择最具选择性的连接顺序。消除最大行数的连接应该在计划中更早处理,使得计划树向上移动的行更少。如果计划没有选择优化的连接顺序,设置join_collapse_limit=1并在你的查询语句中使用显式JOIN语法,强制遗留的优化器(planner)指定连接顺序。你也可以收集更多连接相关列的统计。
- 优化器是否选择性扫描分区表?如果你使用表分区,优化器是否只选择扫描满足查询谓词的子表?父表扫描应该返回0行,因为父表不包含任何数据。查询计划中显示选择性分区扫描的例子,参见Verifying Your Partition Strategy。
- 优化器是否选择了适当的哈希聚合与哈希连接?哈希操作通常比其它的连接或聚合类型快的多。行的比较和排序在内存中完成,而不是读写磁盘。为了让优化器适当地选择哈希操作,必须有足够的可用内存,存储估算的行数。为查询运行EXPLAIN ANALYZE,显示计划中的哪些操作溢出到磁盘,它们使用多少内存,为避免溢出到磁盘需要多少内存。例如:
Work_mem used: 23430K bytes avg, 23430K bytes max (seg0). Work_mem wanted: 33649K bytes avg, 33649K bytes max (seg0) to lessen workfile I/O affecting 2 workers.
用HAWQ轻松取代传统数据仓库(十七) —— 最佳实践