JOIN查询与多个查询
JOIN查询比几个查询更快吗? (您运行主查询,然后根据主查询的结果运行许多其他SELECT)
我在问,因为join它们会使我的应用程序的devise变得复杂
如果他们更快,谁能粗略估计多less? 如果它是1.5倍,我不在乎,但如果是10倍,我想我可以。
这太模糊了,给你一个与你的具体情况相关的答案。 这取决于很多东西。 杰夫·阿特伍德(这个网站的创始人)实际上写了这个 。 但是,大多数情况下,如果你有正确的索引,而且你正确地做了JOIN,那么做一次旅行通常会比几个快。
对于内部联接,单个查询是有意义的,因为只有匹配的行。 对于左连接,多个查询要好得多…请看下面的基准:
-
带有5个连接的单个查询
查询: 8.074508秒
结果大小:2268000
-
5个查询连续
合并查询时间: 0.00262秒
结果大小:165(6 + 50 + 7 + 12 + 90)
。
请注意,在这两种情况下我们都得到相同的结果(6 x 50 x 7 x 12 x 90 = 2268000)
左连接使用指数更多的内存与冗余数据。
内存限制可能没有那么糟糕,如果你只做两个表的连接,但通常是三个或更多,它变得值得不同的查询。
作为一个方面说明,我的MySQL服务器就在我的应用程序服务器旁边,所以连接时间可以忽略不计。 如果你的连接时间在几秒钟内,那么也许是有好处的
坦率
我实际上是为了自己find一个答案,在阅读给出的答案之后,我只能同意比较数据库查询性能的最好方法是获取真实世界的数字,因为只有很多variables需要考虑但是,我也认为比较它们之间的数字在几乎所有的情况下都是不好的。 我的意思是,这些数字应该总是与可接受的数字进行比较,绝对不能相互比较。
我可以理解,如果一种查询方式需要0.02秒,另一种需要20秒,这是一个巨大的差异。 但是如果一个查询方法需要0.0000000002秒,另一个需要0.0000002秒呢? 在这两种情况下,一种方法比另一种快1000倍,但是在第二种情况下它真的仍然“高”
底线我个人看到它:如果performance良好,去寻求简单的解决scheme。
做了一个快速testing,从一个50,000行的表中select一行,并从一个100,000行的表中连接一行。 基本上看起来像:
$id = mt_rand(1, 50000); $row = $db->fetchOne("SELECT * FROM table1 WHERE id = " . $id); $row = $db->fetchOne("SELECT * FROM table2 WHERE other_id = " . $row['other_id']);
VS
$id = mt_rand(1, 50000); $db->fetchOne("SELECT table1.*, table2.* FROM table1 LEFT JOIN table1.other_id = table2.other_id WHERE table1.id = " . $id);
两种select方法花了3.7秒钟,50,000次读取,而JOIN花了2.0秒,在我家里的慢速电脑上。 INNER JOIN和LEFT JOIN没有什么区别。 获取多行(例如,使用IN SET)产生了类似的结果。
根据数据库的复杂性与开发人员的复杂性相比,执行多个SELECT调用可能会更简单。
尝试针对JOIN和多个SELECTS运行一些数据库统计信息。 看看在你的环境中JOIN比SELECT更快/更慢。
然后,如果将其更改为JOIN将意味着额外的一天/一周/月的开发工作,我会坚持使用多个SELECT
干杯,
BLT
构build单独的查询和连接,然后分别对它们进行时间 – 没有什么比现实世界的数字更有帮助了。
那么更好 – 在每个查询的开头添加“EXPLAIN”。 这将告诉你MySQL有多less个子查询来回答你对数据的请求,以及为每个查询扫描了多less行。
真正的问题是: 这些logging是一对一关系还是一对多关系 ?
TLDR答案:
如果一对一,使用JOIN
语句。
如果是一对多,则使用一个(或多个) SELECT
语句进行服务器端代码优化。
为什么和如何使用SELECT进行优化
因为JOIN
具有指数级的内存泄漏问题,所以基于一对多关系对大量logging进行SELECT
(多个查询而不是连接)会产生最佳效率。 抓住所有的数据,然后使用服务器端脚本语言进行sorting:
SELECT * FROM Address WHERE Personid IN(1,2,3);
结果:
Address.id : 1 // First person and their address Address.Personid : 1 Address.City : "Boston" Address.id : 2 // First person's second address Address.Personid : 1 Address.City : "New York" Address.id : 3 // Second person's address Address.Personid : 2 Address.City : "Barcelona"
在这里,我在一个select语句中获取所有的logging。 这比JOIN
更好,它将一次一个地将这些logging中的一小部分作为另一个查询的子组件。 然后我parsing它的服务器端代码,看起来像…
<?php foreach($addresses as $address) { $persons[$address['Personid']]->Address[] = $address; } ?>
何时不使用JOIN进行优化
与一个单一logging基于一对一关系连接一大组logging产生了与多个SELECT
语句相比的最佳效率,一个接一个地获取下一个loggingtypes。
但是,在使用一对多关系获取logging时, JOIN
效率不高。
示例:数据库博客有3个感兴趣的表,博客帖,标签和评论。
SELECT * from BlogPost LEFT JOIN Tag ON Tag.BlogPostid = BlogPost.id LEFT JOIN Comment ON Comment.BlogPostid = BlogPost.id;
如果有1个blogpost,2个标签和2个评论,你会得到如下结果:
Row1: tag1, comment1, Row2: tag1, comment2, Row3: tag2, comment1, Row4: tag2, comment2,
注意每个logging是如何重复的。 好吧,2条评论和2条标签是4行。 如果我们有4条评论和4条标签呢? 你不会得到8行 – 你得到16行:
Row1: tag1, comment1, Row2: tag1, comment2, Row3: tag1, comment3, Row4: tag1, comment4, Row5: tag2, comment1, Row6: tag2, comment2, Row7: tag2, comment3, Row8: tag2, comment4, Row9: tag3, comment1, Row10: tag3, comment2, Row11: tag3, comment3, Row12: tag3, comment4, Row13: tag4, comment1, Row14: tag4, comment2, Row15: tag4, comment3, Row16: tag4, comment4,
添加更多的表格,更多的logging等,这个问题会迅速膨胀到数百行,这些行都是大部分冗余数据。
什么这些重复花费你? 内存(在SQL服务器和试图删除重复的代码)和networking资源(在SQL服务器和你的代码服务器之间)。
根据我的经验,我发现运行多个查询通常更快,特别是在检索大型数据集时。
当从另一个应用程序(如PHP)与数据库进行交互时,服务器之间的一次访问就有很多。
还有其他方法可以限制访问服务器的次数,并且仍然运行多个查询,这些查询通常不仅更快,而且还使应用程序更易于阅读 – 例如mysqli_multi_query。
在SQL方面,我并不是新手,我认为开发人员,尤其是后辈,有一种倾向,就是花费大量的时间去编写非常聪明的连接,因为他们看起来很聪明,而实际上有一些聪明的方法来提取看起来很漂亮的数据简单。
最后一段是个人意见,但我希望这有助于。 我同意别人,但谁说你应该基准。 这两种方法都不是银弹。
在吞吐量方面会更快吗? 大概。 但是它也可能一次locking更多的数据库对象(取决于数据库和模式),从而降低并发性。 根据我的经验,当数据库在同一局域网上的大多数OLTP系统上,实际上人们往往误以为“数据库往返次数less”,实际瓶颈很less是networking。
这里有100个有用的查询的链接,这些查询都在Oracle数据库中testing过,但是记住SQL是一个标准,Oracle,MS SQL Server,MySQL和其他数据库之间的区别是SQL方言:
有几个因素,这意味着没有二进制答案。 什么是最好的performance取决于你的环境。 顺便说一句,如果你的单个标识符select不是次要的,你的configuration可能有问题。
真正的问题是要如何访问数据。 单选支持后期绑定。 例如,如果您只需要员工信息,则可以从Employees表中进行select。 外键关系可以用来在以后和根据需要检索相关资源。 select将已经有一个关键指向,所以他们应该是非常快,你只需要检索你所需要的。 必须始终考虑networking延迟。
联合会一次检索所有的数据。 如果您正在生成报告或填充网格,这可能正是您想要的。 在这种情况下,编译和optomized联接只会比单个select更快。 请记住,即席连接速度可能不尽如人意 – 您应该将它们编译(存储到一个存储过程中)。 速度答案取决于执行计划,该计划详细说明DBMS采取何种步骤来检索数据。
是的,使用连接的一个查询会更快。 虽然不知道你正在查询的表格的关系,你的数据集的大小,或主键的位置,但几乎不可能说多快。
为什么不testing两种情况,那么你肯定会知道…