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

时间:2017-07-28 13:30:08

标签: mysql sql performance subquery

我有两张桌子。 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表,它使用索引,该索引为{{1} }。我不够精明,不知道如何解释这一点,以了解为什么这会产生重大影响。

我在命令行上运行这些查询。

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

总结:

为什么使用子查询可以显着加快这种简单的连接查询?

1 个答案:

答案 0 :(得分:7)

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

您的桌子没有索引。 然后,连接必须读取整个第二个表,以便比较第一个表的每一行。

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

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