谓词下推(Predicate Pushdown,简称 PPD),是指尽量将 SQL 查问中的谓词(where 条件)提前执行,缩小后续操作的数量和计算量。在 Hive 中默认是开启的,也能够通过配置 SET hive.optimize.ppd=true;
显式开启。例如,对于如下 SQL
select a.*, b.*
from a join b on (a.col1 = b.col1)
where a.col1 > 20 and b.col2 > 40
如果开启了谓词下推,在 join 之前会先执行 where 语句中对两个表的过滤操作,从而缩小读取和计算的数据量。否则,会先 join 再过滤。
除了 SQL 语句执行层面,在文件存储层面(ORC、Parquet 等格局),也会有谓词下推的思维。
以 ORC 为例,每个 ORC 文件保留了三个层级的索引:
- file level:蕴含整个文件每列的统计信息
- stripe level:每个 stripe 内每列的统计信息
- row level:在同一个 stripe 内每 10000 行进行统计,失去每列的统计信息
file 和 stripe 级别的统计信息保留在 file footer 中,能够疾速过滤 where 条件中不须要读取的文件。row 级别索引蕴含了每个 row group 的列统计信息和 row group 的起始地位。
列统计信息根本都会蕴含其取值数量、是否蕴含 null,大部分根本类型的列还会蕴含最小值(min)、最大值(max),数值型的列还有总和(sum)。所有层级的索引都能够用于对须要读取的数据进行过滤。例如,有一个查问语句心愿获取年龄大于 100 岁的记录,where 条件中的语句应该为 age > 100
,那么执行时只会读取蕴含年龄大于 100 岁的文件、stripe 或 row groups。
但要留神有些操作会使文件存储层面的谓词下推生效,在写代码的时候须要留神。例如,有个日志工夫字段 log_time
,其存储的数据格式为 2023-01-01 10:00:00,当初须要取某一天的数据,可能会利用 to_date
函数:
select
*
from table_a
where to_date(log_time) = '2023-01-09';
但下面的语句就无奈利用 ORC 文件索引来疾速过滤不须要的文件、stripe 或 row group,因为对字段 log_time
调用了函数 to_date
,导致在真正开始运算前无奈晓得 to_date(log_time)
的理论值。如果批改为应用如下写法,则能够利用文件层面的疾速过滤:
select
*
from table_a
where log_time >= '2023-01-09';
and log_time < '2023-01-10';
另外,下面咱们提到文件、strip、row group 的统计信息会存储相应数据中是否蕴含 null,因而倡议应用 null 而不是 ”-“、”” 等来示意空逻辑。
对以上内容做个小结,利用好谓词下推来晋升 Hive 性能,咱们能够:
- 先过滤再 join。Hive 中默认开启,无需特地关注
- 在 where 语句中,尽量不要应用函数,例如
to_date
等 - 应用 null 而不是 ”-“、”” 等来示意空逻辑
参考资料:
Apache ORC 文档:Indexes
Hive Optimization — Quick Refresher
什么是谓词下推,看这一篇就够了
大数据:Hive-ORC 文件存储格局