JOIN查询与多个查询

JOIN查询比几个查询更快吗? (您运行主查询,然后根据主查询的结果运行许多其他SELECT)

我在问,因为join它们会使我的应用程序的devise变得复杂

如果他们更快,谁能粗略估计多less? 如果它是1.5倍,我不在乎,但如果是10倍,我想我可以。

这太模糊了,给你一个与你的具体情况相关的答案。 这取决于很多东西。 杰夫·阿特伍德(这个网站的创始人)实际上写了这个 。 但是,大多数情况下,如果你有正确的索引,而且你正确地做了JOIN,那么做一次旅行通常会比几个快。

对于内部联接,单个查询是有意义的,因为只有匹配的行。 对于左连接,多个查询要好得多…请看下面的基准:

  1. 带有5个连接的单个查询

    查询: 8.074508秒

    结果大小:2268000

  2. 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方言:

http://javaforlearn.com/100-sql-queries-learn/

有几个因素,这意味着没有二进制答案。 什么是最好的performance取决于你的环境。 顺便说一句,如果你的单个标识符select不是次要的,你的configuration可能有问题。

真正的问题是要如何访问数据。 单选支持后期绑定。 例如,如果您只需要员工信息,则可以从Employees表中进行select。 外键关系可以用来在以后和根据需要检索相关资源。 select将已经有一个关键指向,所以他们应该是非常快,你只需要检索你所需要的。 必须始终考虑networking延迟。

联合会一次检索所有的数据。 如果您正在生成报告或填充网格,这可能正是您想要的。 在这种情况下,编译和optomized联接只会比单个select更快。 请记住,即席连接速度可能不尽如人意 – 您应该将它们编译(存储到一个存储过程中)。 速度答案取决于执行计划,该计划详细说明DBMS采取何种步骤来检索数据。

是的,使用连接的一个查询会更快。 虽然不知道你正在查询的表格的关系,你的数据集的大小,或主键的位置,但几乎不可能说多快。

为什么不testing两种情况,那么你肯定会知道…