【问题标题】:Performance Penalties for Unused Joins未使用连接的性能惩罚
【发布时间】:2011-08-17 03:00:00
【问题描述】:

我正在编写一个脚本,该脚本基于使用多个连接在一起的表的查询生成报告。脚本的输入之一将是报告所需字段的列表。根据请求的字段,可能不需要某些表。我的问题是:如果在 SELECT 或 WHERE 子句中未引用连接,是否包含一个 [显着] 性能损失?

考虑下表:

mysql> SELECT * FROM `Books`;
+----------------------+----------+
| title                | authorId |
+----------------------+----------+
| Animal Farm          |        3 |
| Brave New World      |        2 |
| Fahrenheit 451       |        1 |
| Nineteen Eighty-Four |        3 |
+----------------------+----------+

mysql> SELECT * FROM `Authors`;
+----+----------+-----------+
| id | lastName | firstName |
+----+----------+-----------+
|  1 | Bradbury |       Ray |
|  2 |   Huxley |    Aldous |
|  3 |   Orwell |    George |
+----+----------+-----------+

SELECT
    `Authors`.`lastName`
FROM
    `Authors`
WHERE
    `Authors`.`id` = 1

跑赢大盘:

SELECT
    `Authors`.`lastName`
FROM
    `Authors`
JOIN
    `Books`
    ON `Authors`.`id` = `Books`.`authorId`
WHERE
    `Authors`.`id` = 1

?

在我看来,MySQL 应该只知道完全忽略 JOIN,因为 SELECT 或 WHERE 子句中没有引用该表。但不知何故,我怀疑情况是否如此。当然,这是一个非常基本的例子。所涉及的实际数据会复杂得多。

实际上,这并不是什么大不了的事情......我只需要知道我的脚本是否需要对连接“智能”,并且只有在请求的字段依赖它们时才包含它们。

【问题讨论】:

  • 您列出的案例确实可以返回不同的结果。当您加入表格时,返回的结果将不是所有作者,而是所有写过书的作者。
  • 哦,好点...如果它是左连接怎么办?然后它完全没有必要并返回相同的结果。在这种情况下,我想知道省略联接是否会带来性能优势?
  • 哦,但是即使使用左连接,也有可能出现重复(在这种情况下,如果 WHERE 子句是:Authors.id = 3)。所以 MySQL 总是需要首先查看该表中的内容......所以它总是会至少有一点性能下降。知道了。谢谢!
  • select 子句中未使用的LEFT JOINDISTINCT 会不会有性能差异?

标签: mysql performance join


【解决方案1】:

这实际上并没有被使用,因为这意味着只有存在于 Books 中的 Authors 才会包含在结果集中。

JOIN
    `Books`
    ON `Authors`.`id` = `Books`.`authorId`

但是,如果您“知道”每个 Author 都存在于 Book 中,那么删除连接会带来一些性能优势,但这在很大程度上取决于 idex 和表中的记录数以及连接中的逻辑(尤其是当进行数据转换)

【讨论】:

    【解决方案2】:

    这是一种无法回答的问题。是的,添加加入需要额外的时间;如果没有,嗯,呃....测量时间,就无法判断你是否能够测量那个时间。

    从广义上讲,如果 - 就像在您的示例中一样 - 您正在加入具有唯一索引的主键,则不太可能产生可衡量的差异。

    如果您有更复杂的联接(您暗示),或者在没有索引的字段上联接,或者如果您的联接涉及函数,则性能损失可能很大。

    当然,以这种方式编写多个基本相同的查询可能仍然更容易,除了删除不需要的连接。

    最后一点建议 - 尝试将查询抽象为视图。这样一来,您就可以优化一次性能,或许还可以以更简单的方式编写报表查询...

    【讨论】:

      【解决方案3】:

      加入总是需要时间的。

      副作用
      最重要的是inner join(这是默认连接)通过限制您获得的行数来影响结果。 因此,取决于所有authors 是否都在books 中,这两个查询可能相同也可能不同。

      此外,如果author 写入了多个book,则“已加入”查询的结果集将显示重复的结果。

      性能
      WHERE 子句中,您已将authors.id 声明为常量=1,因此(如果您在author.idbooks.author_id 上有索引)两张桌子。两个表之间的查询时间会很接近。

      一般来说,加入可能需要相当长的时间,而且所有附加的副作用只有在你真的想使用加入提供的额外信息时才应该进行。

      【讨论】:

        【解决方案4】:

        您似乎正在尝试确定两件事:两个 select 语句之间是否可以进行任何优化,以及这两个语句中哪一个执行速度最快。

        似乎由于连接确实限制了列表中有书籍的作者返回的结果,因此无法进行那么多优化。

        对于您描述的连接表对返回结果确实没有限制影响的情况,似乎没有连接表的查询会执行得更快。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-11-11
          • 2013-02-12
          • 1970-01-01
          • 2018-01-27
          • 1970-01-01
          • 2014-04-30
          • 2019-07-10
          • 2017-09-16
          相关资源
          最近更新 更多