PREWHERE 可通过减少读取的数据量提高筛选效率。默认情况下,即使查询未显式指定 PREWHERE,ClickHouse 也会将符合条件的条件从 WHERE 移至 PREWHERE,从而应用此优化。您可以显式指定 PREWHERE,以控制在此阶段应用哪些条件。
使用 PREWHERE 时,ClickHouse 首先仅读取评估条件所需的列。随后,仅对包含至少一行匹配数据的块读取查询所需的其他列。当条件使用的列少于查询其余部分所需的列,且能筛除大量块时,可减少读取的数据量。
手动控制 PREWHERE
PREWHERE。这样可以减少读取其余列的数据量。
一个查询可以同时包含 PREWHERE 和 WHERE。在这种情况下,会先计算 PREWHERE。
将 optimize_move_to_prewhere 设置为 0,以防止 ClickHouse 自动将条件从 WHERE 移至 PREWHERE。
对于带有 FINAL 修饰符的查询,只有在 optimize_move_to_prewhere 和 optimize_move_to_prewhere_if_final 均已启用时,ClickHouse 才会将条件从 WHERE 移至 PREWHERE。
默认情况下,
PREWHERE 会在 FINAL 之前计算。因此,当 PREWHERE 引用了表的 ORDER BY 键以外的列时,FROM ... FINAL 查询可能会产生意外结果。PREWHERE 与 JOIN
JOIN 的查询中,PREWHERE 条件最多只能直接引用一个表的列。ClickHouse 会在该表的行参与联接前对其应用该条件。
相比之下,WHERE 条件在逻辑上会过滤联接后的结果;但只要不改变结果,优化器也可能在联接前应用该条件。因此,在 PREWHERE 和 WHERE 中使用相同条件可能会产生不同结果,尤其是在外联接时。
以下示例创建两个表来说明这一差异:
PREWHERE 会在 LEFT JOIN 之前对 table_2 进行过滤,因此 table_1 中 id = 1 的行仍无法匹配:
WHERE 中使用相同条件会对 join 结果进行过滤,移除 id = 1 的行:
限制
PREWHERE 仅受 *MergeTree 家族的表支持。