最佳实践概要
本章包含Greenplum数据库的最佳实践概要。
数据模型
Greenplum数据库是一种shared nothing的分析型MPP数据库。这种模型与高度规范化的/事务型 的SMP数据库有显著区别。正因为如此,推荐以下几项最佳实践。
- Greenplum数据库使用非规范化的模式设计会工作得最好,非规范化的模式适合于MPP分析型处理,例如 带有大型事实表和较小维度表的星形模式或者雪花模式。
- 表之间用于连接(join)的列采用相同的数据类型。
详见模式设计。
堆存储 vs. 追加优化存储
- 经常进行反复的批量或单一UPDATE,DELETE和INSERT 操作的表或分区使用堆存储。
- 经常进行并发UPDATE,DELETE和INSERT的表或分区 使用堆存储。
- 对于在初始装载后很少更新并且只会在大型批处理操作中进行后续插入的表和分区,使用追加优化存储。
- 绝不在追加优化表上执行单个INSERT,UPDATE或 DELETE操作。
- 绝不在追加优化表上执行并发的批量UPDATE或DELETE操作。可以执行并发的 批量INSERT操作。
详见堆存储还是追加优化存储。
行存 vs. 列存
- 如果负载中有要求更新并且频繁执行插入的迭代事务,则对这种负载使用行存。
- 在对宽表选择时使用行存。
- 为一般目的或混合负载使用行存。
- 选择面很窄(很少的列)和在少量列上计算数据聚集时使用列存。
- 如果表中有单个列定期被更新而不修改行中的其他列,则对这种表使用列存。
详见行存还是列存。
压缩
- 在大型追加优化和分区表上使用压缩以改进系统范围的I/O。
- 在数据最终的存储位置表设置列压缩。
- 平衡压缩解压缩时间和CPU执行周期,选择性能最高的压缩级别。
详见压缩。
数据分布
- 为所有的表显式定义一个列分布或者随机分布。不要使用默认值。
- 使用能将数据在所有segment上均匀分布的单个列作为分布键。
- 不要采用查询的WHERE条件中使用的列作为分布键。
- 不要采用日期或时间戳作为分布键。
- 不要将同一列同时用于数据分布和分区。
- 在经常做连接(join)操作的大表上采用相同的分布键,这样可以通过本地连接(join)来显著提高性能。
- 在初始装载数据以及增量装载数据之后验证数据没有明显倾斜。
详见分布。
资源队列内存管理
- 设置vm.overcommit_memory为2。
- 不要配置OS使用大页。
- 使用gp_vmem_protect_limit设置实例可以为每个Segment数据库中执行的所有工作分配的最大内存。
可以通过以下计算方法来设置gp_vmem_protect_limit:
gp_vmem – Greenplum数据库可用总内存
gp_vmem = ((SWAP + RAM) – (7.5GB + 0.05 * RAM)) / 1.7
其中SWAP是该主机的交换空间,单位GB,RAM是该主机的内存,单位GB
- max_acting_primary_segments – 当发生主机或主segment故障导致镜像segment切换时, 单台主机上可以运行的主segment上限。
gp_vmem_protect_limit
gp_vmem_protect_limit = gp_vmem / acting_primary_segments
转换成MB来设置配置参数的值。
在有大量工作文件被生成的场景下用下面的公式计算将工作文件考虑在内的gp_vmem因子:
gp_vmem = ((SWAP + RAM) – (7.5GB + 0.05 * RAM - (300KB *
total_#_workfiles))) / 1.7
绝不将gp_vmem_protect_limit设置得过高或者比系统上的物理RAM大。
使用计算出的gp_vmem值来计算操作系统参数vm.overcommit_ratio 的设置:
vm.overcommit_ratio = (RAM - 0.026 * gp_vmem) / RAM
使用statement_mem来分配每个segment数据库中用于一个查询的内存。
- 使用资源队列设置活动查询的数目(ACTIVE_STATEMENTS)以及队列中查询所能利用的内存量 (MEMORY_LIMIT)。
- 把所有的用户都与一个资源队列关联。不要使用默认的队列。
- 设置PRIORITY以匹配用于负载以及实际情况的队列的实际需要,避免使用MAX权限。
- 确保资源队列的内存分配不会超过gp_vmem_protect_limit的设置。
- 动态更新资源队列设置以匹配日常操作流。
分区
- 只对大型表分区。不要分区小表。
- 只有能基于查询条件实现分区消除(分区裁剪)时才使用分区。
- 选择范围分区而舍弃列表分区。
- 基于查询谓词对表分区。
- 不要在同一列上对表进行分布和分区。
- 不要使用默认分区。
- 不要使用多级分区,创建较少的分区让每个分区中有更多数据。
- 通过检查查询的EXPLAIN计划验证查询有选择地扫描分区表(分区被裁剪)。
- 不要用列存储创建太多分区,因为每个Segment上的物理文件总数:physical files = segments x columns x partitions
见分区.
索引
- 通常在Greenplum数据库中无需使用索引。
- 对高基数的表在列式表的单列上创建索引用于钻透目的要求查询具有较高的选择度。
- 不要索引被频繁更新的列。
- 总是在装载数据到表之前删除索引。在装载后,重新为该表创建索引。
- 创建具有选择性的B-树索引。
- 不要在被更新的列上创建位图索引。
- 不要为唯一列、基数非常高或者非常低的数据使用位图索引。位图索引在列值唯一性位于100-100,000之间时性能最好。
- 不要为事务性负载使用位图索引。
- 通常不要索引分区表。如果需要索引,索引列必须与分区列不同。
见索引.
资源队列
- 使用资源队列来管理集群上的负载。
- 将所有的角色都与一个用户定义的资源队列关联。
- 使用ACTIVE_STATEMENTS参数限制特定队列的成员能并发运行的活动查询数量。
- 使用MEMORY_LIMIT参数控制通过队列运行的查询所能利用的总内存量。
- 动态修改资源队列以匹配负载以及现状。
见配置资源队列.
监控和维护
- 实现Greenplum数据库管理员指南中的”推荐的监控和维护任务”。
- 安装时运行gpcheckperf并且在之后定期运行该工具,保存其输出用来比较系统性能随时间的变化。
- 使用手头的所有工具来理解系统在不同负载下的表现。
- 检查任何异常事件以判断成因。
- 通过定期运行执行计划监控查询活动以确保查询被以最优的方式运行。
- 检查执行计划以判断索引是否被使用以及分区消除是否按照预期发生。
- 了解系统日志文件的位置和内容并且定期监控它们,而不是只在问题出现时才去检查日志。
见系统监控和维护, Query Profiling and 监控Greenplum数据库日志文件.
ANALYZE
- 如果分析操作势在必行,那么请做出决定。如果p_autostats_mode设置为 on_no_stats(默认)并且表没有被分区,分析操作并不是必须的。
- 处理大量的表时,优先使用analyzedb工具而不是ANALYZE命令, 因为analyzedb工具不会分析整个数据库。analyzedb工具可以增量 并发地更新统计数据。针对堆表,统计数据会一直被更新。相较而言ANALYZE则不像 analyzedb一样去更新表的元数据(用来记录表统计信息是否是最新的)。
- 不要在整个数据库上运行ANALYZE。需要时,有选择地在表级别上运行ANALYZE。
- 在显著改变底层数据的INSERT、UPDATE以及DELETE 操作之后总是运行ANALYZE。
- 在CREATE INDEX操作之后总是运行ANALYZE。
- 如果在非常大的表上运行ANALYZE需要太长时间,可以只在用于连接条件、 WHERE子句、SORT子句、GROUP BY 子句或者HAVING子句的列上运行ANALYZE。
- 当处理大批量表时,使用analyzedb工具而不是使用ANALYZE 命令
Vacuum
- 在大量UPDATE和DELETE操作后运行 VACUUM。
- 不要运行VACUUM FULL。而是运行一个CREATE TABLE…AS 操作,然后重命名并且删掉原始表。
- 频繁地在系统目录上运行VACUUM以避免目录膨胀以及在目录上运行 VACUUM FULL的需要。
- 绝不要杀掉系统目录表上的VACUUM操作。
见管理数据库膨胀.
装载
- 随着segment数目增加最大化并行度。
- 在尽可能多的ETL节点上均匀散布数据。
- 把非常大型的数据文件分割成相等的部分,并且把数据散布在尽可能多的文件系统上。
- 每个文件系统运行两个gpfdist实例。
- 在尽可能多的接口上运行gpfdist。
- 使用gp_external_max_segs以控制每个gpfdist 服务的segment数量。
- 总是保持gp_external_max_segs和gpfdist 进程的数量为偶因子。
- 在装载到现有表之前总是删除索引并且在装载之后重建索引。
- 总是在对表装载之后运行VACUUM。
见装载数据.
安全性
- 保护gpadmin用户ID并且只允许对它进行必需的系统管理员访问。
- 在执行特定的系统维护任务(例如升级或者扩容)时,管理员只应作为gpadmin 登入到Greenplum。
- 限制具有SUPERUSER角色属性的用户。成为超级用户的角色能绕过Greenplum 数据库中的所有访问特权检查以及资源队列。只有系统管理员应该被给予超级用户的权力。请见 Greenplum数据库管理员指南中的“修改角色属性”。
- 数据库用户绝不应该以gpadmin登录,且ETL或者生产负载也绝不应该以 gpadmin运行。
- 为每个登入的用户、应用和服务分派一个不同的角色。
- 对于应用或者Web服务,考虑为每个应用或服务创建一个不同的角色。
- 使用组管理访问特权。
- 保护root口令。
- 为操作系统口令强制一种强口令策略。
- 确保重要的操作系统文件受到保护。
见安全性.
加密
- 加密和解密数据需要性能作为代价,只加密需要加密的数据。
- 在生产系统中实现任何加密方案之前,先执行性能测试。
- 生产Greenplum数据库系统中的服务器证书应该由一个数字证书认证机构(CA)签发,这样客户端可以 认证该服务器。如果客户端都是机构中的本地客户端,CA可以是本地的。
- 只要客户端到Greenplum数据库的连接会通过不安全的链接,就应该对其使用SSL加密。
- 对称加密方案(加密和解密使用同样的密钥)具有比非对称方案更好的性能,因此在密钥能被安全共享时应当使用 对称加密方案。
- 使用crytographic函数来加密磁盘上的数据。数据在数据库进程中被加密和解密,因此有必要用SSL保护客户端 连接以避免传输未加密数据。
- 在ETL数据被装载到数据库中或者从数据库中卸载时,使用gpfdists而不是gpfdist。
高可用性
Note: 以下指导规则在真实硬件部署环境中总结而出,但是并不能直接移植到公有云架构下,该架构下本身 已经存在一些高可用手段。
- 使用带有8至24个磁盘的硬件RAID存储方案。
- 使用RAID 1、5或6,这样磁盘阵列能容忍一个失效的磁盘。
- 在磁盘阵列中配置一个热后备以允许在检测到磁盘失效时自动开始重建。
- 通过镜像RAID卷防止重建时整个磁盘阵列失效和退化。
- 定期监控磁盘使用并且在需要时增加额外的空间。
- 监控segment倾斜以确保数据被平均地分布并且在所有segment上存储被平均地消耗。
- 设置一个后备master以便在主master故障后接管。
- 规划当故障发生时,如何把客户端切换到新的master实例,例如,通过更新DNS中的master地址。
- 设置监控机制以便在主Master失效时在系统监控应用中或者通过email发出通知。
- 为所有的segment设置镜像。
- 将主segment和它们的镜像放置在不同的主机上以预防主机故障。
- 迅速地使用gprecoverseg工具恢复故障的segment,以便恢复冗余并且让系统回到最佳平衡。
- 考虑双集群配置以提供额外层次上的冗余以及额外的查询处理吞吐。
- 除非数据库可以很容易地从源端恢复,否则定期备份Greenplum数据库。
- 如果堆表相对较小并且两次备份之间只有很少的追加优化或列存分区被修改,使用增量备份
- 如果备份被保存到NFS挂载点,使用例如Dell EMC Isilon之类的横向扩展NFS方案以避免IO瓶颈。
- 考虑使用Greenplum集成将备份流式传送给Dell EMC Data Domain或者 Veritas NetBackup企业级备份平台。
见高可用性.
Parent topic: Greenplum数据库最佳实践