如何改写无带子查询的PostgreSQL查询语句并提升其性能?
PostgreSQL查询改写与性能优化方案
无带子查询的改写版本
原查询的IN子查询可以直接转换为表JOIN的形式,同时通过DISTINCT ON避免重复结果(与原查询的DISTINCT逻辑保持一致):
SELECT DISTINCT ON (x1.id) x1.* FROM my_project.my_table x1 JOIN my_project.my_table x2 ON x1.data1 = x2.data1 - 1 WHERE x1.value = :value AND x1.name <> :name AND x2.name = :name ORDER BY x1.id ASC;
如果你的数据能保证x2中不会有多个行对应同一个data1 - 1值(即关联后不会产生重复的x1记录),可以去掉DISTINCT ON (x1.id),进一步简化查询。
性能提升方案
- 创建针对性复合索引
- 对于关联的
x2表部分,创建索引加速name过滤和data1取值:CREATE INDEX idx_my_table_name_data1 ON my_project.my_table (name, data1); - 对于
x1表的查询和排序,创建覆盖索引,让数据库无需回表即可获取所需数据:CREATE INDEX idx_my_table_value_name_data1_id ON my_project.my_table (value, name, data1, id);
- 对于关联的
- 更新表统计信息
执行ANALYZE my_project.my_table;,让PostgreSQL优化器获取最新的数据分布情况,生成更高效的执行计划。 - 考虑用EXISTS替代(可选)
如果你能接受存在子查询的形式,EXISTS通常比IN或JOIN在存在性判断上更高效,因为它找到匹配行后就会停止扫描:SELECT x1.* FROM my_project.my_table x1 WHERE x1.value = :value AND x1.name <> :name AND EXISTS ( SELECT 1 FROM my_project.my_table x2 WHERE x2.name = :name AND x1.data1 = x2.data1 - 1 ) ORDER BY x1.id ASC; - 避免不必要的去重
确认数据唯一性后去掉DISTINCT ON,减少数据库的去重计算开销。
内容的提问来源于stack exchange,提问作者Baran Emre Turkmen
相关产品推荐
相关产品推荐

