在 JOIN 中重写慢速 SQL(子)查询

Posted

技术标签:

【中文标题】在 JOIN 中重写慢速 SQL(子)查询【英文标题】:Rewriting a slow SQL (sub) query in JOIN 【发布时间】:2015-05-29 07:31:51 【问题描述】:

所以我有大量慢速 SQL 查询,我已将其缩小为慢速子查询,因此我想将其重写为 JOIN。但我被卡住了......(由于MAXGROUP BY

SELECT *
FROM local.advice AS aa
  LEFT JOIN webdb.account AS oa ON oa.shortname = aa.shortname 
WHERE aa.aa_id = ANY (SELECT MAX(dup.aa_id)
                      FROM local.advice AS dup
                      GROUP BY dup.shortname) 
  AND oa.cat LIKE '111'
ORDER BY aa.ram, aa.cpu DESC
LIMIT 0, 30

【问题讨论】:

WHERE 子句中的 oa.cat LIKE '111' 使 LEFT JOIN 作为常规内部连接执行。如果您真的想要左连接,请将该条件移至 ON 子句。 感谢您提供信息,但您能否将其写为对我问题的回答,以便更清楚?提前致谢! 但这不是您问题的答案,这是另一个问题。你知道你想要左连接还是内连接? local.advice 表的左连接,因为我需要具有唯一短名称的每条记录的最大 ID 的记录。然后我用这个表加入 webdb 以获取有关该短名称的更多信息。 【参考方案1】:

这是您的查询的不同版本,其中子查询使用连接子句进行转换

select * from local.advice aa 
JOIN webdb.account oa ON oa.shortname = aa.shortname 
join(
 select max(aa_id) as aa_id,shortname from local.advice 
 group by shortname
)x on x.aa_id = aa.aa_id
where
oa.cat = '111'
order by aa.ram, aa.cpu DESC 
limit 0,30

此外,如果尚未添加索引,您可能需要应用索引

alter table local.advice add index shortname_idx(shortname);
alter table webdb.account add index cat_shortname_idx(cat,shortname);
alter table local.advice add index ram_idx(ram);
alter table local.advice add index cpu_idx(cpu);

我假设aa_id 是主键所以没有添加索引

确保在应用索引之前备份表

【讨论】:

别开玩笑了,这个疯了!将我的查询搜索速度提高了 26 倍! 现在需要多少时间?您也可以使用explain select.. 查看查询运行状况。 从13秒到0.5秒,记住1个表包含300万条记录,其他10K INDEX(ram, cpu) 会比INDEX(ram) 好; INDEX(cpu) 没用。如果aa_id 不是PRIMARY KEY of advice, then it needs INDEX(aa_id)` 和INDEX(short_name, aa_id)

以上是关于在 JOIN 中重写慢速 SQL(子)查询的主要内容,如果未能解决你的问题,请参考以下文章

将这些 DB2 SUBQUERY 重写为 Join

如何重写具有连接子查询的 SQL 查询

优化 SQL:如何重写此查询以提高性能? (使用子查询,摆脱 GROUP BY?)

如何让机器人在 discord.py 重写中为频道设置慢速模式?

在不使用相关子查询的情况下重写查询

将子查询(不在)重写为加入