我正在编写一个脚本,该脚本基于使用连接在一起的多个表的查询生成报告。脚本的其中一个输入将是报告所需的字段列表。根据请求的字段,可能不需要某些表。我的问题是:如果在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子句中没有引用该表。但不知何故,我怀疑是这种情况。当然,这是一个非常基本的例子。所涉及的实际数据将会复杂得多。
实际上,这不是一个非常大的交易...我只需要知道我的脚本是否需要对连接“智能”,并且只有在请求的字段依赖它们时才包含它们。
答案 0 :(得分:3)
这实际上并未使用,因为这意味着只有书籍中存在的作者才会包含在结果集中。
JOIN
`Books`
ON `Authors`.`id` = `Books`.`authorId`
但是,如果您“知道”每个作者都存在于Book中,那么在删除连接时会有一些性能优势,但这在很大程度上取决于idexes以及表中的记录数和连接中的逻辑(特别是当进行数据转换)
答案 1 :(得分:1)
加入总是需要时间。
副作用
在inner join
(默认连接)之上,通过限制您获得的行数来影响结果。
因此,根据所有authors
是否在books
中,这两个查询可能相同也可能不相同。
此外,如果author
已写入多个book
,则“已加入”查询的结果集将显示重复结果。
<强>性能强>
在WHERE
条款中,您已声明authors.id
为常量=1
,因此(假设您有author.id
和books.author_id
上的索引)对于两个表,它将是一个非常快速的查找。两个表之间的查询时间非常接近。
一般情况下,连接可能需要花费很多时间,并且只有在您真正想要使用连接提供的额外信息时才应该进行所有添加的副作用。
答案 2 :(得分:1)
这是一个无法回答的问题。是的,添加联接将需要额外的时间;没有,好吧,呃......测量时间,你无法判断你是否能够衡量那段时间。
从广义上讲,如果 - 在你的例子中 - 你加入了具有唯一索引的主键,则不太可能产生可衡量的差异。
如果您有更复杂的连接(您提示),或者在没有索引的情况下加入字段,或者您的连接涉及函数,则性能损失可能很大。
当然,除了删除不需要的连接之外,以这种方式编写多个基本相同的查询可能更容易。
最后一点建议 - 尝试将查询抽象为视图。这样,您可以优化一次性能,并可能以更简单的方式编写报告查询...
答案 3 :(得分:0)
您似乎要确定两件事:如果在两个select语句之间可以进行任何优化,那么两个中的哪一个将是最快的执行。
似乎由于联接确实限制了列表中有书籍的作者的返回结果,因此无法进行那么多优化。
对于您正在描述联接表对返回结果没有限制作用的情况,似乎没有连接表的查询执行速度更快。