作者:闻乃松
- MinMax
每个Iceberg文件的头部元数据信息中记录了当前文件每个列的最大最小值,比如下图中的parquet文件数据记录包含两列:year和uid,file1.parquet中列year的最大和最小值分别是2019和2018,列uid的最大和最小值分别是23000和12000。
当我们进行查询
select * from event where year=2019 and uid=20000
因为这些元数据信息在数据写入文件时最终收集,因此在查询时候,很容易利用这些统计信息过滤掉不符合条件的数据文件。比如示例中,根据year=2020和uid=20000查询到符合条件的数据文件为file1.parquet,另外两个数据文件直接过滤掉了,减少了不必须的文件读取。
为了获取更好的过滤效果,MinMax通常进行全局排序,但是适合排序字段较少的情况,比如1个字段,当排序字段多于1个,依据索引的最左匹配规则,只有查询字段覆盖所有所有索引字段才能获得最好的查询效果,否则过滤效果将大打折扣,为此需要更合适的索引,比如Z-Order。
- Z-Order
因为MinMax索引包括多个字段时,不能保证数据的聚集性,而利用Z-Order索引能够获得比MinMax平均更好的数据聚集性。Z-Order原理是把天然没有有序性的多维数据以某种方式映射成一维数据进行比较。映射后的一维数据,能够保证各个原始维度按照同种程度去保证其聚集性。如下图所示:
对X,Y这两个维度进行比特位的交叉组值,形成了Interleave Index进而得出一个新的值,这个值被称作Z-Value。从图中,可以看到针对X,Y这两个字段的数据,生成的z-value会呈现出一个Z形嵌套。按照这样的一个结构,在按照Z-Value排序时,能够同时保证X,Y两个字段的聚集性。
实现Z-Order 的一个前提是需要保证数据以保序的方式映射成一个正整型,但参与排序的字段类型很多,如String、Long、DateTime、Double等,如何将这些不同类型的值映射为正整型就是个问题。实践中,虽然可以将String类型取固定的前几位字符转为二进制来进行映射,但也带来了信息损失。另外,即使是正整型数据,由于其数据分布不同,可能导致映射的结果不符合Z-Order曲线的嵌套分布。比如,X的取值是0,1&