分区
好的分区策略可以让查询只扫描需要访问的分区,以降低扫描的数据量。
在每个段数据库上的每个分区都是一个物理文件。读取分区表的所有分区比读取相同数据量的非分区表需要更多时间。
以下是分区最佳实践:
- 只为大表设置分区,不要为小表设置分区。
- 仅在根据查询条件可以实现分区裁剪时对大表使用分区。
- 建议优先使用范围 (Range) 分区,否则使用列表 (List) 分区。
- 仅当 SQL 查询包含使用不变操作符(例如 =,<, <=, >=, <>)的简单直接的约束时,查询优化器才会执行分区裁剪。
选择性扫描可以识别查询中的 STABLE 和 IMMUTABLE 函数,但是不能识别 VOLATILE 函数。例如查询优化器对下面的 WHERE 子句
date > CURRENT_DATE
可以启用分区裁剪,但是如果 WHERE 子句如下则不会启用分区裁剪。
time > TIMEOFDAY
通过检查查询的 EXPLAIN 计划验证是否执行分区裁剪非常重要。
不要使用默认分区。默认分区总是会被扫描,更重要的是很多情况下会导致溢出而造成性能不佳。
- 切勿使用相同的字段既做分区键又做分布键。
- 避免使用多级分区。虽然支持子分区但不推荐,因为通常子分区包含数据不多甚至没有。随着分区或者子分区增多性能可能会提高,然而维护这些分区和子分区的代价将超过性能的提升。基于性能、扩展性和可管理性,在扫描性能和分区总数间取得平衡。
- 对于列存储的表,慎用过多的分区。
- 考虑好并发量和所有并发查询打开和扫描的分区均值。
分区数目和列存储文件
HashData 数据仓库对于文件数目的唯一硬性限制是操作系统的打开文件限制。然而也需要考虑到集群的文件总数、每个段数据库(Segment)上的文件数和每个主机上的文件总数。在 MPP 无共享环境中,节点独立运行。每个节点受其磁盘、CPU 和内存的约束。HashData 数据仓库中 CPU 和 I/O 较少成为瓶颈,而内存却比较常见,因为查询执行器需要使用内存优化查询的性能。
Segment 的最佳文件数与每个主机节点上 Segment 个数、集群大小、SQL 访问模式、并发度、负载和倾斜等都有关系。通常一个主机上配置六到八个 Segments,对于大集群建议为每个主机配置更少的 Segment。使用分区和列存储时平衡集群中的文件总数很重要,但是更重要的是考虑好每个 Segment 的文件数和每个主机上的文件数。
例如数据仓库集群中每个节点 64GB 内存:
- 节点数:16
- 每个节点 Segment 数:8
- 每个 Segment 的文件均数:10000
一个节点的文件总数是:810000 = 80000,集群的文件总数是:8 16 * 10000 = 1280000. 随着分区增加和列字段的增加,文件数目增长很快。
作为一个最佳实践,单个节点的文件总数上限为 100000。如前面例子所示,Segment 的最佳文件数和节点的文件总数和节点的硬件配置(主要是内存)、集群大小、SQL 访问、并发度、负载和数据倾斜等相关。