如何将关联子查询中的OR条件转换为UNION以优化查询性能?
优化OR条件:用UNION替代提升性能
我平时在优化带OR的查询条件时,总会优先测试用UNION替代的性能表现。不少场景下UNION方案的性能会更出色,原因很简单:UNION能被数据库合理利用索引优化,而OR条件经常无法触发高效的索引扫描。
就拿你给出的这个查询示例来说:
SELECT * FROM posts WHERE posts.id = ( SELECT postid FROM comments WHERE comments.postid = posts.id AND (comments.userid = 5 OR comments.score = 8) ORDER BY postid LIMIT 1 );
这个子查询里的OR条件是性能瓶颈的潜在点,我们可以把它拆分成两个独立的子查询,用UNION系列语法来合并结果,改写后的查询可以参考下面两种形式:
形式一:保留IN逻辑(更通用)
SELECT * FROM posts WHERE posts.id IN ( SELECT postid FROM comments WHERE comments.userid = 5 UNION ALL SELECT postid FROM comments WHERE comments.score = 8 );
注:如果需要保证postid唯一,把
UNION ALL换成UNION DISTINCT即可;UNION ALL因为不去重,性能会更优,适合确定无重复数据的场景。
形式二:保留原查询的LIMIT 1逻辑
SELECT * FROM posts WHERE posts.id = ( SELECT postid FROM ( SELECT postid FROM comments WHERE comments.userid = 5 UNION ALL SELECT postid FROM comments WHERE comments.score = 8 ) AS combined_results ORDER BY postid LIMIT 1 );
这么做的核心优势在于,拆分后的两个子查询可以分别利用comments(userid)和comments(score)这两个索引(如果已创建的话),数据库能快速定位到符合条件的记录;而原来的OR条件可能会导致数据库放弃索引,转而做全表扫描——尤其是当comments表数据量较大时,两者的性能差距会非常明显。
内容的提问来源于stack exchange,提问作者Tom Shir
相关产品推荐
相关产品推荐

