【问题标题】:Why is this simple join query significantly quicker with a sub-query?为什么这个简单的连接查询与子查询相比要快得多?
【发布时间】:2018-01-04 14:27:31
【问题描述】:

我有两张桌子。 order_details 是 100,000 行,outbound 是 10,000 行。

我需要将它们加入一个名为 order_number 的列中,这两个列都是 VARCHAR(50)。 order_number 在出站表中不是唯一的。

CREATE TABLE `outbound` (
    `outbound_id` int(12) NOT NULL,
    `order_number` varchar(50) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `order_details` (
    `order_details_id` int(12) NOT NULL,
    `order_number` varchar(50) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

这是我的初始查询,运行时间超过 60 秒:

SELECT o.order_number
FROM outbound o
INNER JOIN order_details od
    ON o.order_number = od.order_number

此查询得到相同的结果,运行时间不到一秒:

SELECT o.order_number
FROM outbound o
INNER JOIN
(
    SELECT order_number
    FROM order_details
) od
ON (o.order_number = od.order_number)

这让我很惊讶,因为通常子查询要慢得多。

运行EXPLAIN(我仍在学习如何理解)表明子查询版本使用derived2 表,它正在使用索引,并且该索引是auto_key0。我不够精明,不知道如何解释这一点以理解为什么这会产生重大影响。

我正在通过命令行运行这些查询。

我正在为 Linux (x86_64) CentOS 运行 MySQL Ver 14.14 Distrib 5.6.35。

总结:

为什么这个简单的连接查询使用子查询明显更快?

【问题讨论】:

  • MySQL 的优化器不好?您是否也与EXISTSIN 进行了比较? SELECT o.order_number FROM outbound o WHERE EXISTS( SELECT order_number FROM order_details AS od WHERE o.order_number = od.order_number)SELECT o.order_number FROM outbound o WHERE order_number IN ( SELECT order_number FROM order_details )
  • @dnoeth 第一个查询需要一分钟,第二个查询是即时的。
  • 正如我所说,一个体面的优化器应该将所有四个相似处理(事实上,当order_details.orde_number 不是唯一的时,连接可能会得到不同的结果)。
  • @dnoeth order_number 在出站表中不是唯一的。

标签: mysql sql performance subquery


【解决方案1】:

我对 MySQL 的了解非常有限。但这是我的想法:

您的表没有索引。 然后连接必须读取整个第二个表才能比较第一个表的每一行。

子查询读取第二张表一次并创建索引,则不需要为第一张表的每一行读取整个第二张表。它只需要检查索引,这要快得多。

要验证我是否正确,请尝试为两个表中的 order_number 列创建索引(CREATE INDEX ...),然后再次运行这两个查询。您的第一个查询应该只需要不到一秒钟而不是一分钟。

【讨论】:

  • 将数据拉到我的开发人员进行测试很痛苦,但是当我这样做时,我发现您的答案是准确的。感谢您的回答,有道理。
猜你喜欢
  • 2017-06-17
  • 1970-01-01
  • 2019-12-22
  • 2011-12-11
  • 2011-05-15
  • 2010-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多