合并同结构issues表后关联items表的慢查询优化求助
优化百万级数据的合并关联查询
你的查询之所以加载无响应,核心问题是先全表合并两个百万级的issues表,再做关联和过滤,这会导致临时表数据量巨大,而且没有利用索引优化。下面一步步帮你分析并给出优化方案:
原SQL的核心问题
- 先合并后过滤:
SELECT * FROM issues UNION SELECT * FROM old_issues会先扫描两个完整的大表,生成一个包含百万级数据的临时表,这一步的IO和内存开销极大。 - RIGHT JOIN 被WHERE条件转为INNER JOIN:你的WHERE子句里加了
new_issues.issuedate < '2018-01-01',这会过滤掉所有new_issues为NULL的记录,等同于用了INNER JOIN,RIGHT JOIN的逻辑完全没有意义。 - 缺少合适的索引:如果没有针对过滤和关联字段的索引,全表扫描会让查询速度慢到难以接受。
优化方案
1. 先过滤再合并,缩小临时表规模
对每个issues表单独过滤issuedate < '2018-01-01',再合并。如果不需要去重,用UNION ALL比UNION快很多——因为UNION会额外做去重校验,完全是不必要的性能损耗。
2. 先筛选目标items数据,再关联
先把items中符合location='DEP' AND ccode='ARACD'的数据筛选出来,再和过滤后的issues数据关联,大幅减少关联的数据量。
3. 建立必要的索引
给issues和old_issues表添加联合索引:
CREATE INDEX idx_issues_itemno_issuedate ON issues(itemno, issuedate); CREATE INDEX idx_oldissues_itemno_issuedate ON old_issues(itemno, issuedate);
给items表添加联合索引:
CREATE INDEX idx_items_itemno_loc_ccode ON items(itemnumber, location, ccode);
优化后的SQL
SELECT i.itemnumber AS itemno, filtered_issues.issuedate FROM ( -- 先过滤两个issues表,再合并 SELECT itemno, issuedate FROM issues WHERE issuedate < '2018-01-01' UNION ALL -- 如果需要去重就换成UNION,否则用ALL更高效 SELECT itemno, issuedate FROM old_issues WHERE issuedate < '2018-01-01' ) AS filtered_issues INNER JOIN ( -- 先筛选符合条件的items数据 SELECT itemnumber FROM items WHERE location = 'DEP' AND ccode = 'ARACD' ) AS i ON i.itemnumber = filtered_issues.itemno;
针对你的测试数据的预期结果
结合你提供的表数据,运行优化后的SQL会得到:
| itemno | issuedate |
|---|---|
| 200 | 2017-12-21 |
| 200 | 2017-12-20 |
解释:
- items中符合条件的是itemno 200、300
- 过滤后的issues数据只有old_issues里的200(两条)、400、500,但400的location不是DEP,500的ccode不是ARACD,所以最终只返回200的两条记录。
内容的提问来源于stack exchange,提问作者BoostBoy
相关产品推荐
相关产品推荐

