Data skew 很好理解,即数据倾斜。现实中的数据很多都不是正态分布的,譬如城市人口,东部沿海一个市的人口与西部地区一个市地区的人口相比,东部城市人口会多好几倍。
postgresql的skew的优化核心思想是"避免磁盘IO"。
优化器往往会选择小表和正态分布的表做inner table,这会导致 outer table要不更大,要不是非正态分布。如果outer table的表是非正态分布的话,会在batch0来处理那些most common value(MCV)
大致过程如下:
1、prepare skew hash table
- 确定skew hash table大小,默认分配2%内存
- 获取outer table的MCV统计信息,对于每个mcv计算其hash值,并放到对应的skew hash bucket中。由于此时没有处理inner table,所以bucket应该指向NULL。如果产生hash 冲突,采用线性扫描发,当前slot被占用,则寻找下一个可以占用的slot。
- 填充skew hash table:扫描inner table构建 main hashtable。如果tuple属于skew hash table,且对应的slot不为空,那就将tuple加入skew hash table,而非main hashtable。
之后就是扫描outer table的probe阶段了。
若该tuple是MCV tuple,则到skew hash table中去寻找匹配。
否则就进到hybrid hash join算法的处理逻辑中。
这样做的好处是,50%的mcv在batch0阶段就处理好了,就可以节约50%的磁盘IO。
(也就是说把常见数据放到了batch0中匹配,而且在batch0的处理是不需要从disk load 数据的,从而减少了IO)
参考:
全面解读PostgreSQL和Greenplum的Hash Join