带同表聚合子查询的SQL调优:大表查询性能提升求助
SQL查询性能优化方案(针对2000万条数据的table1)
嘿,我来帮你拆解这个慢查询的问题!你的查询耗时30秒,核心是两个致命性能瓶颈,我们一步步来优化:
1. 先修复最严重的笛卡尔积问题
你原查询里from table1 t1, table2 t3没有写任何关联条件,这会生成2000万 × 1万 = 200亿条临时数据,后续的distinct还要对这么大数据去重,这绝对是性能杀手!首先必须补上t1和t3的关联条件,比如假设它们通过code关联,那要写成JOIN table2 t3 ON t1.code = t3.code(根据实际业务逻辑调整关联字段)。
2. 替换低效的关联子查询
原查询里的(select min(t2.dat) from table1 t2 where t2.code=t1.code)是关联子查询,会对table1的每一行单独执行一次min计算——2000万条数据就等于全表扫2000万次,这完全没必要。我们可以提前用分组查询算出每个code的最小日期,再和原表关联:
优化后的查询语句(用CTE提前计算)
DECLARE @PreviousMonthDate DATETIME; -- 简化上月初日期的计算方式 SET @PreviousMonthDate = DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) - 1, 0); -- 提前计算每个code的最小日期,过滤出符合条件的code WITH CodeValid AS ( SELECT code FROM table1 GROUP BY code HAVING MIN(dat) > @PreviousMonthDate ) -- 关联查询获取所需字段,注意补上t1和t3的关联条件 SELECT DISTINCT t1.code, t1.ent, t3.lib, t3.typ FROM CodeValid cv JOIN table1 t1 ON cv.code = t1.code JOIN table2 t3 ON t1.code = t3.code -- 这里替换成实际的关联字段!
如果t1.ent、t3.lib、t3.typ对于每个code都是唯一值,那DISTINCT可以直接去掉,进一步减少开销。
3. 加索引加速查询
索引是大数据量查询的关键,针对这个场景建议创建两个复合索引:
- 给
table1的code和dat建索引,包含需要查询的ent字段,这样分组计算min(dat)时直接走索引,不用扫全表:
CREATE NONCLUSTERED INDEX IX_table1_code_dat_ent ON table1 (code) INCLUDE (dat, ent);
- 给
table2的关联字段(比如code)建索引,包含lib、typ字段,加速连接查询:
CREATE NONCLUSTERED INDEX IX_table2_code_lib_typ ON table2 (code) INCLUDE (lib, typ);
4. 额外优化建议
- 查看执行计划:在SSMS里按
Ctrl+M打开实际执行计划,看看是否还有全表扫描、哈希匹配(笛卡尔积残留)等问题,针对性调整。 - 避免不必要的字段:如果
table1或table2有其他冗余字段,不要在查询中返回,减少数据传输量。
内容的提问来源于stack exchange,提问作者david hale
相关产品推荐
相关产品推荐

