CPU Cache掷中率差。一行的多列(字段)数据的内存紧挨在一起,哪怕只对其中的一个字段做操作,其他字段所占的内存也必要加载进来,这会抢占稀缺的Cache资源。Cache命失会导致被哀求的数据从内存加载进Cache,等待内存操作完成会导致CPU执行指令停息(Memory Stall),这会增加延时,还大概浪费内存带宽。
变长字段影响盘算服从。假设一行包括int、string、int三列,其中int类型是固定长度,而string是变长的(一样平常表现为int len + bytes content),变长列的存在会导致无法通过行号算offset做快速定位。
从业界发展情况来看,近几年OLAP引擎发展迅速,该场景追求极致的查询速度,向量化技能在Clickhouse、Doris等Native引擎中得到广泛使用,降本增效的趋势也逐渐扩展到数仓生产。2022年6月DataBricks发表论文《Photon-
A Fast Query Engine for Lakehouse Systems》,Photon是DataBricks
Runtime中C++实现的向量化执行引擎,相比DBR性能均匀提升4倍,并已应用在Databricks贸易版上,但没有开源。2021年Meta开源Velox,一个C++实现的向量化执行库。2022
Databricks Data & AI Summit 上,Intel 与Kyligence先容了合作开源项目Gluten,旨在为Spark
SQL提供Native Vectorized
Execution。Gluten+Velox的组合,使Java栈的Spark也可以像Doris、Clickhouse等Native引擎一样发挥向量化执行的性能上风
。
从美团内部来看,数仓生产有数万规模盘算节点,许多业务决议依赖数据及时产出,若应用向量化执行技能,在不升级硬件的情况下,既可得到可观的资源节省,也能加速作业执行,让业务更快看到数据和做出决议。根据Photon和Gluten的公开数据,应用向量化Spark执行服从至少可以提升一倍,我们在物理机上基于TPC-
H测试Gluten+Velox相Spark 3.0也有1.7倍性能提升。
count distinct结果错误 。比如如许一条SQL:select A, B, count(distinct userId), sum(amt) from t group by 1,2 ,Gluten会把count(distinct userId) 变为count(userId),通过把userId加到GroupingKey里来实现distinct语义。具体处理过程如下:
浮点类型转换精度错误 。形如查询SELECT concat(col2, cast(max(col1) as string)) FROM (VALUES (CAST(5.08 AS FLOAT), 'abc_')) AS tab(col1, col2) group by col2; 在Spark中返回abc_5.08,在Gluten中返回abc_5.079999923706055。浮点数5.08不能用二进制分数准确表达,近似表现成5.0799999237060546875。Velox通过函数folly::to<std::string>(T val)来实现float类型到string类型的转换,这个函数底层依赖开源库google::double-conversion, folly里默认设置了输出宽度参数DoubleToStringConverter::SHORTEST(可以准确表现double类型的最小宽度),转换时颠末四舍五入之后返回 5.079999923706055。我们把宽度参数改为DoubleToStringConverter::SHORTEST_SINGLE(可以准确表现float类型的最小宽度),转换时颠末四舍五入之后返回 5.08。