如果我想建立一个订单对象数组并嵌入订单对象中的两个选项是客户对象我有两个选择。
一个。第一个查询订单表。 湾循环记录并查询人员表以获取人员的记录
这就像是:
Select * from APplications
Select * from Customer where id = 1
Select * from Customer where id = 2
Select * from Customer where id = 3
Select * from Customer where id = etc . . .
一个。在所有领域进行联接
它显然是#2,因为你只进行一次查询而不是1 + [numberOforders]查询(可能是数百或更多)
这就像是:
Select * from Applications a, Customers c
Innerjoin c.id = a.customerID
我的主要问题是,如果我在订单表中有10个其他表(类似于客户),那么你在订单表中有了id。如果你做一个连接这10个表的单个查询,或者在某个时候这样做效率很低:
任何建议都有帮助..是否有任何优化以确保快速性能
答案 0 :(得分:19)
我同意所有人说过,即使有很多桌子,单个连接也可能更有效率。与在应用程序代码中完成工作相比,它的开发工作量也更少。这假定表被适当地索引,每个外键列都有一个索引,并且(当然)每个主键列都有一个索引。
您最好的选择是首先尝试最简单的方法(大连接),看看它的表现如何。如果它表现良好,那么很棒 - 你已经完成了。如果它表现不佳,请对查询进行概要分析并查找表中缺少的索引。
由于网络往返次数(如anijhaw所述),您的选项#1不太可能表现良好。这有时被称为“选择N + 1”问题 - 您执行一个SELECT以获取N个应用程序的列表,然后在循环中执行N个SELECT以获取客户。对于应用程序员来说,这种一次性记录循环是很自然的;但是,当您一次操作整组数据时,SQL的效果会更好。
如果选项#2即使有良好的索引也很慢,您可能需要查看缓存。您可以在应用程序中(如果有足够的RAM)或在专用缓存服务器(如memcached)中缓存数据库(使用摘要表或物化/索引视图)。当然,这取决于您的查询结果需要的最新状态。如果所有内容都必须完全是最新的,那么每当更新基础表时,都必须更新任何缓存 - 它变得复杂并且变得不那么有用。
这听起来像是一个报告查询,报告通常不需要是实时的。所以缓存可能能够帮助你。
根据您的DBMS,需要考虑的另一件事是此查询对其他查询到同一数据库的影响。如果您的DBMS允许读者阻止编写者,那么如果需要很长时间才能运行,则此查询可能会阻止对表的更新。那会很糟糕。 Oracle没有这个问题,在“读取提交的快照”模式下运行时,SQL Server也没有。我不知道MySQL。
答案 1 :(得分:7)
如果此customer_id在您的customer-table中是唯一的(并且其他ID在其他表中是唯一的),那么您的查询每个Application只返回1行,那么执行单个SELECT肯定会更有效。
在一个查询中加入所有需要的客户将得到优化,而使用大量单个SELECT则不能。
修改强>
我尝试使用带有50.000个应用程序和50.000个匹配客户的Oracle PL / SQL。
在一个查询中选择所有内容的解决方案
0.172 s
在单个SELECT中选择每个客户的解决方案
1.984 s
对于其他客户或通过网络访问,这很可能会变得更糟。
答案 2 :(得分:2)
单个连接应该更快,主要有两个原因。
如果您通过网络查询,则使用查询次数而不是单个查询会产生开销。
使用查询优化器在DBMS内部优化连接,因此比执行多个查询更快。
答案 3 :(得分:1)
在我看来,单个连接仍然会更快,因为DBMS将始终在执行连接之前执行where子句。这意味着在发生之前和加入时,所涉及的所有表都已被削减到最小可能的大小。
事实上,为了获得你想要的东西,你必须在某个时间点从所有这些表中读取...所以这样做一次仍然会更有效率。
这里的关键是在加入之前表格都被减少到最小尺寸,并且我们正在使用内连接。如果这两个条件都发生了变化(某些外连接可以正常),那么您可能会遇到问题。
答案 4 :(得分:1)
你应该做一个连接这10个表的单个查询,或者在某些时候是低效的
所有这些表都加入订单 - 返回的所有记录都是相关的。在尽可能少的查询或操作中抓取所有相关内容没有任何低效率。
使用单独的查询会增加查询之间数据可能发生变化的风险。