由于Kudu是一个典型的列存系统,所以存在一个优化机制叫做延迟物化。在查询时会优先 过滤出谓词中涉及到的列,将符合条件的行筛选出来以后,再决定是否去读取其他列。
举个例子。用户的sql是这样的:
Select * from tb where sex=’男’ and age>20;
表上的数据如下:
kudu中的实际查询过程是:
1.扫描sex列,过滤出行1,3
2.扫描age列,过滤出行3,4
3.过滤条件相交,得到3
4.真正读取id=3行对应的所有列信息,并组装数据
这样的查询过程就减少了IO数量,提高了性能。但是我感觉这个过程还可以再优化一下。假设表上数据量比较多,有一百万行。表上有十列,C1列是主键。C9列是特殊的列,选择性非常好,有一百万个不同的值。那么单独只用这一个谓词条件去查询,就可以只得到一行结果。实际测试下,这行sql耗时105毫秒。
如果给出更多的谓词,返回结果仍然是只有一行。但是根据前面延迟物化的步骤,从C9过滤完结果后,又继续去读其他列进行过滤,导致性能反而下降。如下图所示,谓词数量增加后,反而耗时185毫秒,性能明显下降。
所以我觉得这个延迟物化的功能应该这样设计:
首先把所有谓词按照选择性从高到低排列,优先处理高选择性谓词。当过滤出的行低于某个临界值,例如总行数的1%后,可以直接读出这些行的所有列,再执行剩下的谓词即可。这样应该是性能最优的设计。