GBase 8a数据库索引机制详解-列存引擎的原生加速机制 本文继续说明为什么列存不依赖传统 B-Tree 索引南大通用GBase 8a数据库gbase database) 实际使用了哪些替代机制以及怎样在列存环境下做到真正有效的查询加速。既然传统索引在列存里失效GBase 8a数据库用什么机制来加速过滤查询答案是列存引擎特有的三层过滤机制分区裁剪、列块元数据过滤Min-Max 剪枝和字典过滤。这三层机制组合起来能在不使用 B-Tree 索引的情况下大幅减少实际需要读取的数据量。1、分区裁剪Partition Pruning这是 GBase 8a 最重要的查询加速手段在前面的文章中已多次提到。当查询带有针对分区键的范围过滤条件时优化器直接跳过不在范围内的分区把扫描数据量从全表缩减到若干个分区。分区裁剪发生在查询规划阶段不需要任何索引结构是纯粹基于元数据的静态剪枝。分区裁剪的效果取决于分区键与查询 WHERE 条件的匹配程度。最理想的情况是 WHERE 条件精确地覆盖了分区键且不对分区键列使用函数此时优化器能准确地确定需要扫描哪些分区剪枝效果最佳。2、 列块 Min-Max 过滤Zone Map列存引擎在存储数据时把每一列的数据切分成若干个固定大小的列块Column Block每个列块通常包含几万到几十万行的数据。GBase 8a 的 Express 引擎为每个列块维护一份元数据记录该列块中值的最小值和最大值这种机制称为 Zone Map 或 Min-Max 索引。当查询带有等值或范围过滤条件时引擎在扫描每个列块之前先检查 WHERE 条件是否与该列块的 Min-Max 范围有交集如果查询是WHERE amount 50000而某个列块的最大值max_amount 10000则该列块中不可能有满足条件的行直接跳过不需要解压和扫描该列块的实际数据。Zone Map 的过滤效果与数据的物理排序有关。如果amount列的数据按升序物理排列则低值区间的列块能被早早剪掉过滤效果极好如果数据完全随机分布每个列块的 Min 到 Max 范围都很宽Zone Map 几乎无法剪掉任何列块过滤效果很差。这也是为什么数据按查询过滤列有序写入能提升查询性能——有序写入会让同一过滤范围的数据集中在少数几个列块里Zone Map 能裁掉大量列块。实际上Zone Map 是列存引擎的内置 Min-Max 索引不需要用户显式创建是列存存储格式本身的一部分。只要合理安排数据的写入顺序Zone Map 的过滤效果相当于在行存数据库上建了一个覆盖索引。3、字典过滤Dictionary Filter对于使用了字典编码的低基数列如status、dept_id、provinceGBase 8a 在扫描实际数据之前可以先在字典层面过滤把 WHERE 条件的目标值如status 2映射到字典中的 ID如字典 ID 2然后在列块的字典映射层面直接判断不需要解压原始值就能确定某行是否满足条件。字典过滤的开销极低因为操作的是压缩后的字典 ID通常是 1~2 字节的整数而不是解压后的原始字符串。对于高频出现的低基数过滤条件如状态筛选、部门筛选字典过滤能在接近零额外开销的情况下完成过滤是列存引擎天然具备的优化。