【问题标题】:Which provides better performance one big join or multiple queries?哪个提供更好的性能一个大连接或多个查询?
【发布时间】:2010-12-28 06:28:25
【问题描述】:

我有一个名为 orders 的表。订单上的一列是 customer_id
我有一个名为 customers 的表,有 10 个字段

如果我想建立一个订单对象数组并嵌入一个订单对象是一个客户对象,那么有两个选项,我有两个选择。

选项 1:

一个。首先查询订单表。 湾。遍历记录并查询人员表以获取人员的记录

这可能是这样的:

 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:

一个。对所有字段进行连接

这是一个明显的 #2,因为您只执行一个查询而不是 1 + [numberOforders] 个查询(可能是数百个或更多)

这可能是这样的:

 Select * from Applications a, Customers c
 Innerjoin c.id = a.customerID

我的主要问题是,如果我有 10 个其他表不在订单表(类似于客户)中,而您在订单表中有 id。您是否应该执行一个查询来连接这 10 个表,或者在某些时候这样做效率低:

任何建议都会有所帮助.. 是否有任何优化以确保快速性能

【问题讨论】:

  • 对不起,如果我的帖子不清楚。我的意思是,每个应用程序都会返回一行,对吧?
  • 这里的大多数答案都非常模糊,是由甚至没有在 SQL 中处理过大数据的新手提出的。 (是的,用 SQL 处理大数据很愚蠢,但有时你别无选择)
  • 我运行了一个基准测试并将结果发布到an article on Medium。我会在这里添加一个答案,但是already did it on another question,并且对多个问题发布相同的答案是frowned upon

标签: sql database database-design query-optimization


【解决方案1】:

我同意每个人所说的单个连接可能会更有效,即使有很多表也是如此。与在应用程序代码中进行工作相比,它的开发工作量也更少。这假设表已适当索引,每个外键列都有一个索引,(当然)每个主键列都有一个索引。

最好的办法是先尝试最简单的方法(大连接),然后看看它的性能如何。如果它表现良好,那就太好了——你已经完成了。如果性能不佳,请分析查询并查找表上缺少的索引。

由于网络往返次数过多(如 anijhaw 所述),您的选项 #1 不太可能表现良好。这有时被称为“选择 N+1”问题——您执行一次 SELECT 以获取 N 个应用程序的列表,然后在循环中执行 N 次 SELECT 以获取客户。这种一次记录的循环对于应用程序程序员来说是很自然的。但是当您同时操作整个数据集时,SQL 的效果会更好。

如果选项 #2 即使有良好的索引也很慢,您可能需要考虑缓存。您可以缓存在数据库(使用汇总表或物化/索引视图)、应用程序(如果有足够的 RAM)或专用缓存服务器(如 memcached)中。当然,这取决于您的查询结果需要保持多长时间。如果一切都必须是最新的,那么无论何时更新基础表都必须更新任何缓存 - 它变得复杂并且变得不那么有用。

这听起来像是一个报告查询,而且报告通常不需要是实时的。所以缓存也许能帮到你。

根据您的 DBMS,需要考虑的另一件事是此查询对访问同一数据库的其他查询的影响。如果您的 DBMS 允许读取器阻止写入器,那么如果运行需要很长时间,此查询可能会阻止对表的更新。那会很糟糕。 Oracle 没有这个问题,SQL Server 在“读取提交快照”模式下运行时也没有这个问题。不过我不知道 MySQL。

【讨论】:

  • 中断查询对我来说效果更好,我的表中有 1400 万行,连接速度非常慢。所以我处理了代码,它比加入快 100 倍。虽然我不喜欢用 SQL 来处理这么大的行,但是我的公司有这么多年的堆栈,我懒得改变它,所以优化 SQL 是更好和懒惰的选择。
【解决方案2】:

如果这个 customer_id 在您的客户表中是唯一的(并且其他 ID 在其他表中是唯一的),那么您的查询每个应用程序只返回 1 行,那么执行单个 SELECT 肯定会更有效。

在一个查询中连接所有需要的客户将得到优化,而使用大量单个 SELECT 则不能。

编辑
我在 Oracle PL/SQL 上尝试了这个,有 50.000 个应用程序和 50.000 个匹配的客户。

在一个查询中选择所有内容的解决方案采用
0.172 s

在单个 SELECT 中选择每个客户的解决方案采用
1.984 s

这很可能在其他客户端或通过网络访问时变得更糟。

【讨论】:

  • 我更新了这个问题,使其更加清晰。这不会返回一行。 .
  • 不是每个应用程序只有一行吗?应用程序是架构中最“详细”的实体吗?或者(例如)您是否有一个 ApplicationItems 表,每个应用程序包含多行?
【解决方案3】:

单连接应该更快,主要有两个原因。

如果您通过网络进行查询,那么使用多个查询而不是单个查询会产生开销。

将使用查询优化器在 DBMS 内优化连接,因此比执行多个查询要快。

【讨论】:

  • 并不总是适用。如果两个表都有超过 1400 万行,那就太糟糕了。我不得不中断查询并在代码中处理它。
  • 同意。对于具有 10k 行的小型数据库,单连接是有意义的。当您进入表中 100MM+ 行的世界(在我的情况下接近 1B)时,与 N+1 选择解决方案相比,连接将非常糟糕。您必须进行基准测试和实验。
  • 尊敬的评论者,您介意解释一下为什么一旦数据集变大,JOINs 的效率最终会低于单个 SELECTs 吗?
【解决方案4】:

在我看来,单连接仍然会更快,因为 DBMS 总是会在执行连接之前执行 where 子句。这意味着在连接发生之前,所有涉及的表都已经被缩减到最小的可能大小。

事实仍然是,为了得到你想要的东西,你必须在某个时间点从所有这些表中读取......所以这样做一次仍然会让我更有效率。

这里的关键是表在加入之前都被缩减到最小大小,并且我们正在使用内部联接。如果这两个条件都发生了变化(一些外部连接没问题),那么您可能会遇到问题。

【讨论】:

  • 我将问题更新为更清晰。 .我没有任何where子句
【解决方案5】:

你应该做一个单一的查询来连接这 10 个表还是在某些时候效率低下

所有这些表都连接到订单 - 所有返回的记录都是相关的。在尽可能少的查询或操作中获取所有相关内容并没有什么低效的。

使用单独的查询,数据可能在查询之间发生变化的风险增加。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-19
    • 2011-11-24
    • 2013-09-23
    • 2019-05-06
    • 1970-01-01
    • 2019-06-18
    相关资源
    最近更新 更多