针对Crosses表,如何编写读取数据量更少的SQL查询?
解决方案
要减少对Crosses表的数据扫描量同时避免重复结果,可以从过滤逻辑优化和索引优化两方面入手:
1. 优化查询逻辑,减少无效匹配
当前的JOIN会让临时表的每一行都与Crosses表做匹配,即便临时表的CrossArticleId无重复,也会因Crosses中同一ArticleId对应多条记录而返回重复结果。可以先把临时表的关联字段提取为唯一集合,再进行匹配:
方式一:用IN子查询替代JOIN
直接用临时表的CrossArticleId作为过滤条件,配合DISTINCT获取唯一结果:
SELECT DISTINCT c.CrossArticleId FROM Crosses c WHERE c.ArticleId IN (SELECT CrossArticleId FROM @tempFlatCrosses)
方式二:先对临时表关联字段去重再JOIN
如果临时表的CrossArticleId存在重复(当前案例无,但通用场景需考虑),先对临时表的关联字段去重,再和Crosses表关联,减少匹配次数:
SELECT DISTINCT c.CrossArticleId FROM Crosses c INNER JOIN ( SELECT DISTINCT CrossArticleId FROM @tempFlatCrosses ) f ON c.ArticleId = f.CrossArticleId
2. 创建覆盖索引(核心优化)
逻辑优化能减少结果重复,但要真正降低表扫描量,必须依赖索引。给Crosses表的ArticleId字段创建包含CrossArticleId的非聚集索引,查询时可直接通过索引获取所需数据,无需扫描全表或回表读取:
CREATE NONCLUSTERED INDEX IX_Crosses_ArticleId ON Crosses (ArticleId) INCLUDE (CrossArticleId);
创建该索引后,无论是JOIN还是IN子查询,数据库都会走索引查找/扫描,大幅降低IO开销。
补充:用GROUP BY替代DISTINCT(可选)
如果更倾向于用分组去重,也可以用GROUP BY代替DISTINCT,在有索引的情况下性能差异不大:
SELECT c.CrossArticleId FROM Crosses c WHERE c.ArticleId IN (SELECT CrossArticleId FROM @tempFlatCrosses) GROUP BY c.CrossArticleId
内容的提问来源于stack exchange,提问作者Artur Makvetsyan
相关产品推荐
相关产品推荐

