MYSQL 中针对子查询的查询优化? [关闭]

Posted

技术标签:

【中文标题】MYSQL 中针对子查询的查询优化? [关闭]【英文标题】:Query optimization in MYSQL for a query with sub queries? [closed] 【发布时间】:2016-02-13 05:55:28 【问题描述】:

在一项作业中,我收到了一个查询并要求对其进行优化。 查询是:

选择 C.yearID 为年份, 名称为teamName, C.lgID 作为联赛, D.cnt 作为 totalBatters, C.cnt 如上AverageBatters 从 (选择 count(masterID) as cnt, A.yearID, A.teamID, A.lgID 从 (选择 主ID, 团队ID, 年号, lgID, 总和(AB), 总和(H), 总和(H)/总和(AB)作为平均值 从 击球 GROUP BY teamID , yearID , lgID , masterID) B, (select 团队ID, 年号, lgID, 总和(AB), 总和(H), 总和(H)/总和(AB)作为平均值 从 击球 其中 ab 不为空 GROUP BY teamID , yearID , lgID) A 在哪里 A.avg >= B.avg AND A.teamID = B.teamID AND A.yearID = B.yearID AND A.lgID = B.lgID GROUP BY teamID , yearID , lgID) C, (选择 count(masterID) as cnt, yearID, teamID, lgID 从 击球 其中 ab 不为空 GROUP BY yearID , teamID , lgID) D, 团队 在哪里 C.cnt / D.cnt >= 0.75 AND C.yearID = D.yearID AND C.teamID = D.teamID 和 C.lgID = D.lgID AND team.yearID = C.yearID AND 团队.lgID = C.lgID AND team.teamID = C.teamID

我想知道可以做些什么来优化它?我对这个概念很陌生,对如何进行有点困惑。一般来说,如何优化包含select语句的子查询?

【问题讨论】:

这对于 Stack Exchange 的“代码审查”站点来说是一个更好的帖子,因为您正在寻求有关代码的帮助,而不是一般的 SQL 问题/问题。这是正确的网站:Code Review @danjuggler 将来,您可以使用更简单的语法将链接嵌入到任何 SE 站点:[site.SE],在这种情况下,[CodeReview.SE] 将自动解析为 Code Review。 :) 您是否已尽力优化查询并寻求进一步改进?如果是这样,代码审查会是一个更好的地方,只要代码正常工作。 代码审查交叉帖子已作为题外话关闭,因为代码审查要求代码作者提出问题。 【参考方案1】:

一般来说,如何优化包含select语句的子查询?

这里有一些想法可以帮助您入门。我会尊重这是一项任务这一事实,最后,您将通过自己经历并不断学习来更好地理解 SQL 查询。

我希望作业中包含一种可以导入 mysql 的数据集,以便在进行更改时运行查询并注意对执行计划和整体性能的影响。


别名

在考虑优化之前,也许您可​​以先看看如何使代码更易于阅读、理解和维护。子查询的行为方式类似于常规表,因此,它们应该被赋予对数据集的含义有意义的别名/名称​​意味着

它们的别名为 BACD,看起来几乎是故意命名为混淆,但实际上你会惊讶于在现实生活中看到糟糕的命名/别名的频率,生产SQL 代码。

尝试单独查看(如果可以,运行)每个子查询,查看字段及其含义,然后用好名称替换别名,并相应地更新不同列中的引用。这将优化查询以获得更好的清晰度,并最终提高可维护性。


JOINs

希望到本次作业时,各种类型的JOIN 操作已经涵盖。如果没有,here is a good summary from a *** answer。还有大量其他资源涵盖了JOIN 的来龙去脉,包括TechOnTheNet 上的一篇好帖子。

让我们剥离子查询,看看整个查询的结构。我用 cmets 替换了逻辑以使其更明显:

SELECT
--columns
FROM 
(
    SELECT  
    --columns
    FROM 
    (
        select 
        --columns
        FROM batting
    ) B, 
    (
        select 
        --columns
    ) A
    WHERE
    --some comparisons of averages
) C,
(
    SELECT 
     --columns
    FROM batting
) D, 
teams
WHERE
    --a filter based on a calculation
    C.cnt / D.cnt >= 0.75
    --um... what is all this stuff doing down here?
    --shouldn't those be in a JOIN?
        AND C.yearID = D.yearID
        AND C.teamID = D.teamID
        AND C.lgID = D.lgID
        AND teams.yearID = C.yearID
        AND teams.lgID = C.lgID
        AND teams.teamID = C.teamID

你有没有注意到任何奇怪的东西或看起来很奇怪的东西?如果您以前没有读过这篇文章,我强烈建议您阅读Aaron Bertrand 的Bad habits to kick : using old-style JOINs。

读完之后,再看一下这个查询的骨架,你可以用现代的JOIN 做出的改进应该会很突出。这将使查询在清晰度和可维护性方面更加优化。


关键字大小写的一致性

另一种提高可读性的方法是使用一致的关键字大小写。实际上,使用CAPITAL CASEsmall case 大约是50/50。对于一个脚本来说,这似乎微不足道,但当这种不一致遍布整个代码库时,对于必须在其中开发和维护它的下一个人来说,它可能会非常烦人。


性能

所以,到目前为止,如果您已经应用了所有内容,那么代码应该更容易破译。就性能而言,有两件事对我来说是有害的。有很多聚合,因此有很多 GROUP BYs。

首先查看每个子查询本身,然后查看每个聚合。查看每个字段如何在整个查询的上下文中使用。看看你可以删除哪些,也许编写查询的人最初认为他们会需要,但最终没有使用并忘记删除它们。

GROUP BY 字段尝试相同的策略,这些字段是包含在具有一个或多个聚合操作的查询中的未聚合的每个字段。 GROUP BY 可能会变得非常昂贵,而且派生的子查询也有 GROUP BY


您还可以尝试一些其他技巧,这些技巧更高级,可以在 I/O 妥协的情况下改进执行,例如将一个或多个子查询的结果集提取到临时表中,这将释放主表。

像这样的优化本身不一定总是提高执行速度速度,但在数据库服务器处于负载状态的生产环境中,速度通常不是优化的主要考虑因素,而是“轻量级” (或尽可能减少服务器上的负载占用)通常比最终使用更多资源的原始速度更有价值。


我希望这会有所帮助!

【讨论】:

您写过关于文档的文章:“其他:所有这些示例都已经有自己的主题,这只是重复。”我没有找到这些主题,它们在哪里?因此,我创造了它们。很抱歉在这里发表评论,我不知道在哪里可以回复文档区域。 嗨@Matt 抱歉,在文档上交流并不容易。如果你去SQL and Database Product Docs 这是一个专门用于 SQL 文档的聊天室,那就太好了。我们可以在那里更轻松地讨论

以上是关于MYSQL 中针对子查询的查询优化? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

那个mysql 子查询和连接查询 一般常用哪个 谁效率高些

mysql 子查询 优化

mysql的子查询中有统计语句 我该如何优化

Mysql优化系列之——优化器对子查询的处理

MySQL:子查询检查超过 14000 行的子查询优化问题

MySQL5.7性能优化系列——SQL语句优化——使用物化策略优化子查询