比较产生相同结果的不同sql查询之间的性能

时间:2017-04-11 19:21:02

标签: mysql sql

假设两个不同的表供应商和订单中有100M供应商和1B订单。我试图了解哪些查询在数据量很高时会表现得更好,尽管结果是相同的。我知道EXPLAIN PLAN会告诉逻辑计划和查询的成本,但我想了解哪个查询在简单的英语单词中运行得更快以及为什么。

SELECT s.supplier_id
FROM suppliers s
INNER JOIN (SELECT DISTINCT o.supplier_id FROM orders o) o
    ON o.supplier_id = s.supplier_id

SELECT s.supplier_id
FROM suppliers s
WHERE EXISTS (SELECT * FROM orders o WHERE o.supplier_id = s.supplier_id)

SELECT s.supplier_id 
FROM suppliers s 
WHERE s.supplier_id IN (SELECT o.supplier_id FROM orders o)

SELECT s.supplier_id
FROM suppliers s
INTERSECT
SELECT o.supplier_id
FROM orders o

2 个答案:

答案 0 :(得分:0)

这可能比你的例子更好:

SELECT s.supplier_id
FROM suppliers s
INNER JOIN orders o
    ON o.supplier_id = s.supplier_id

子查询具有固有的执行成本,前三个示例使用这些成本。大型数据集的成本要高得多。

第4个示例基本上与我提供的示例相同,不同之处在于它将导致两个表的完整表扫描,以及执行交叉的临时表。

答案 1 :(得分:0)

查询1最可能的执行计划是:

  • 对订单执行subselect并将结果存储在表变量
  • 从供应商处选择,加入subselect where found。

优化包括加入行为; SQL引擎试图加入,索引或没有索引,因为它是查询中遇到的最常见的操作之一。如果订单上的供应商列被编入索引,我预计这将是最快的整体。缺点包括DISTINCT运算符。必要的是,由于订单与供应商之间存在一对多的关系,但最佳实现设置了一个哈希表,它与订单的数量呈线性关系,但增加了几层开销并且内存效率非常低,而天真的实现是N平方的复杂性,这对于如此大的源表是完全不合适的。

查询2的可能计划是:

  • 从供应商中选择所有内容
  • 对于每个供应商,索引扫描(或表扫描)订单,直到找到该供应商的订单。

此查询非常依赖于表和数据结构。如果对订单上的供应商列编制索引,则此查询将是行为中的NlogN,并且" N"问题将是供应商的数量,而不是订单的数量,将搜索空间减少一个数量级。如果它没有编入索引,那么供应商没有任何订单的最坏情况需要一个10亿条记录的表扫描来确定这一事实,根据订单表大小接近N平方的复杂性。

查询3的计划是:

  • 执行子选择并将结果存储在内存中
  • 执行父查询,扫描找到要过滤的每一行的子选择结果。

最好的情况是,查询引擎将此简化为订单的索引供应商列上的联接。最糟糕的情况是,对于每个100米供应商,查询引擎最多可扫描10亿行。

查询4的计划是:

  • 选择1亿供应商
  • 选择10亿个订单
  • 对于每个供应商,扫描订单结果以查找与供应商的订单。

这是非常可怕的,几乎是最好的N平方复杂性;除非引擎做出假设,否则确实没有一种优化它的好方法。在做出这些假设时,有些SQL引擎比其他引擎更好。