Parquet文件对于每一个Row group的每一行都包含了MIN/MAX的统计,这能够让Spark跳过不必要的数据块,以下看看这是怎么回事。
在我们测试中我使用了4个row group以及在product列有以下MIN/MAX统计信息:
我们基于此文件建立了events表,运行以下sql:
SELECT name, location FROM events WHERE product = 'Orange';
根据每个row group的最大最小值统计信息,spark只读取row group2(MIN: Grape, MAX: Pineapple)和row group 3(MIN: Lemon, MAX: Peach)并且试着去找满足product=‘orange’条件的数据。
spark并没有读取row group1 和row group4,是因为orange已经超过了最大最小值的范围。
如果你看这个查询的EXPLAIN EXTENDED输出,你可以看到PushedFilters EqualTo:
== Physical Plan ==
*(1) Project [product#22]
+- *(1) Filter (isnotnull(product#22) && (product#22 = Orange))
+- *(1) FileScan parquet events...
PushedFilters: [IsNotNull(product), EqualTo(product,Orange)]
LIKE ‘%value%’
让我看看product LIKE ‘%Orange%’ 条件
SELECT name, location FROM events WHERE product LIKE '%Orange%';
物理计划如下:
== Physical Plan ==
*(1) Project [product#22]
+- *(1) Filter (isnotnull(product#22) && (product#22 = Orange))
+- *(1) FileScan parquet events...
PushedFilters: [IsNotNull(product), StringContains(product,Orange)]
虽然spark 试着去下推StringContains过滤条件,但是spark还是必须得读取所有row group,因为MIN/MAX统计信息并不能推断是否满足该条件。
你也可以看到执行完该sql后,Input Size 和Records 的统计信息指标。
LIKE ‘value%’
让我们看看product like ‘orange%’条件。
物理计划如下:
== Physical Plan ==
*(1) Project [product#22]
+- *(1) Filter (isnotnull(product#22) && (product#22 = Orange))
+- *(1) FileScan parquet events...
PushedFilters: [IsNotNull(product), StringStartsWith(product,Orange)]
和product LIKE '%Orange%'条件不一样,product LIKE ‘Orange%’ 可以让spark 利用MIN/MAX统计信息,并且跳过row group1 和row group4。
你也可以执铜鼓行完该sql后,Input Size 和Records 的统计信息指标来进行校验。