概述
尽管上述 I/O 优化可以显著减少数据读取量,但它们仍然假定:在执行排序、聚合或
LIMIT 等操作之前,必须先加载所有通过 WHERE 子句的行所对应的全部列。但如果某些列要到后续阶段才需要,或者某些数据虽然通过了 WHERE 子句,实际上却根本不会被用到,又该怎么办?
这正是 惰性物化 发挥作用的地方。它是一种正交增强,补全了整个 I/O 优化栈:
- 索引结合
PREWHERE,可确保只处理匹配WHERE子句中列过滤条件的行。 - 惰性物化 在此基础上,进一步将列读取推迟到查询执行计划实际需要时才进行。
即使在过滤之后,也只会立即加载下一步操作所需的列——例如排序所需的列。
其他列会延后读取,并且由于
LIMIT的存在,通常只会部分读取,仅读取足以生成最终结果的数据。 这使得 惰性物化 对 Top N 查询尤其有效,因为最终结果可能只需要从某些列 (而这些列往往很大) 中取出少量几行。
一个完整示例
PREWHERE 中受益,查询需要具备过滤条件:对于索引,过滤条件需作用于主键列;对于 PREWHERE,则可以作用于任意列。
惰性物化 可以自然地叠加在这些优化之上,但与前面提到的其他优化不同,它甚至还能加速完全没有列过滤条件的查询。
来看下面这个示例查询:它会找出 helpful votes 数量最多的 Amazon 评论,不考虑日期、产品、评分或验证状态,并返回前 3 条评论及其 title、headline 和全文。
首先,在禁用 惰性物化 (使用 query_plan_optimize_lazy_materialization) 的情况下运行该查询 (文件系统缓存处于冷状态) :
Query
Response
Query
Response
如何在查询执行计划中确认惰性物化
EXPLAIN 子句查看该查询的逻辑执行计划,以观察前一个查询中惰性物化的使用情况: