2 选择还是 1 加入查询?

Posted

技术标签:

【中文标题】2 选择还是 1 加入查询?【英文标题】:2 Select or 1 Join query? 【发布时间】:2011-03-03 05:57:26 【问题描述】:

我有 2 张桌子:

book (id, title, age) ----> 1 亿行

作者 (id, book_id, name,born) ----> 1000 万行

现在,假设我有一本书的通用 ID。我需要打印此页:

Title: mybook

authors: Tom, Graham, Luis, Clarke, George

那么...最好的方法是什么?

1) 像这样的简单连接:

Select book.title, author.name 
From book, author 
WHERE ( author.book_id = book.id ) AND ( book.id = 342 )

2) 为了避免加入,我可以做两个简单的查询:

Select title FROM book WHERE id = 342

Select name FROM author WHERE book_id = 342 

什么是最有效的方法?

【问题讨论】:

【参考方案1】:

第一个。这只是一次往返。它需要一些处理才能将作者的行折叠成一个逗号分隔的列表,就像你想要的那样,但这基本上是样板代码。

单独的相关查询是一个坏习惯,它会比大多数事情更快地破坏你的性能。

【讨论】:

数据库不会将行折叠成逗号分隔的列表,客户端可能会使用一些脚本语言。 @Evan - 它可以与 GROUP_CONCAT 或类似的。 我没说做不到。我只是想暗示它没有完成,它是问题的外部。【参考方案2】:

最好的选择是在您自己的服务器上运行速度测试。根据同时访问和分开访问不同表的频率,任何一个都可能更快。

这个之前已经深度回答过:LEFT JOIN vs. multiple SELECT statements

【讨论】:

【参考方案3】:

第一个,特别是如果您有关于 author.book_id 的索引。如果您有很多作者 pr 书并且有可能,则封闭索引将是最好的,否则非封闭索引也会对您有很大帮助。

【讨论】:

【参考方案4】:

最小化往返行程和促进健全的执行计划是我的绩效清单上最突出的项目。

如果查询中的字段之间存在静态依赖关系,从而阻止优化器使用索引,那么在使用索引和数据集的行数增加时,将它们分解为单独的查询可能会带来巨大的性能提升。对于大多数数据库传输协议,额外的结果集等于额外的往返。如果通过 WAN 定期访问数据,这可能会对性能产生影响。幸运的是,有很多方法可以让你的蛋糕也可以吃:

Select title,NULL AS name FROM book WHERE id = 342 
UNION ALL
Select NULL,name FROM author WHERE book_id = 342 

在您的具体示例中,我会选择 #1 并发出警告,以考虑如果给定书籍没有作者存档会发生什么。

【讨论】:

【参考方案5】:

我知道这不应该是一个考虑因素,但第一个查询会返回一个这样的结果集:

title     name
-----------------
mybook    Tom
mybook    Graham
mybook    Luis
mybook    Clarke
mybook    George

而第二对将返回一对这样的结果集:

title
-------
mybook

name
--------
Tom
Graham
Luis
Clarke
George

所以每种方法都以不同的方式返回数据。在这个简单的例子中,书名的重复不会很重要,但是如果你返回第一章而不是标题(比如说),那么效率会降低,因为会有很多重复的数据。因此,虽然第二个可能在数据库中花费更长的时间,但在通过网络发送数据时可能会更快、更高效。

你需要测试你的实际结果,看看哪一个表现最好。

【讨论】:

是的,我知道...但我想知道什么是最有效的方法 :) 如果 VI 或 Emacs 更好,您也可以。所有情况都没有“正确”的答案。使用循环运行一百或一千个测试查询,看看哪个需要更长的时间。使用另一个。 @xRobot - 我同意@cletus 和@jweber 的观点,join 可能是最有效的,但就像@Aaron 所说,您应该通过运行一些测试自己验证这一点。我只是指出您每个都返回不同的数据。

以上是关于2 选择还是 1 加入查询?的主要内容,如果未能解决你的问题,请参考以下文章

MySQL:在 1:N 关系中哪个更快?加入还是两个查询? [复制]

搜索查询加入 3 个表,1 个表有日期

SQL 查询 - 加入多对多关系,有选择地过滤/加入

ORM 选择n+1个性能;加入或不加入

如何在不选择新实例的情况下将一个查询的结果加入另一个查询的结果? [复制]

从列列表中删除选择子查询到主查询