The strange case of the underestimated Merge Join node
4 months ago
- #Query Optimization
- #PostgreSQL
- #Performance Tuning
- 客户报告了一个查询问题:批量处理后首次执行很慢,但后续运行很快,且执行计划不同。
- 最初怀疑是批量处理后未自动执行autoanalyze,但检查发现执行间隔期间并未进行vacuum或analyze操作。
- 该查询涉及两个表通过LEFT JOIN连接,且连接列的直方图数据没有重叠区间。
- 首次执行使用Merge Join,由于优化器基于不完整的直方图数据估算导致成本很高。
- 第二次执行使用Nested Loop Join,得益于清理后的索引元组提供了准确的极值信息。
- 优化器的get_actual_variable_endpoint()函数在首次执行时过早终止,导致估算不准确。
- 提供的复现脚本演示了死亡堆元组如何影响索引扫描,重现了这个场景。
- 该案例揭示了一个罕见现象:即使数据和统计信息未更新,索引元组清理也会导致执行计划变化。