当前位置: 首页 > 面试题库 >

为什么此简单的联接查询与子查询相比显着更快?

淳于健
2023-03-14
问题内容

我有两张表。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的了解非常有限。但是这些是我的想法:

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

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

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



 类似资料:
  • 问题内容: 我是一个老派的MySQL用户,并且始终喜欢子查询。但是如今,每个人都使用子查询,而我讨厌它。我不知道为什么 我缺乏理论知识来自行判断是否存在差异。子查询是否与a一样好,因此不必担心吗? 问题答案: 取自MySQL手册 (13.2.10.11将子查询重写为Joins): LEFT [OUTER] JOIN可以比同等子查询更快,因为服务器可能可以更好地对其进行优化-这不仅限于MySQL S

  • 问题内容: 我重构了从另一家公司继承来的应用程序的慢速部分,以使用内部联接而不是子查询,例如: 重构查询的运行速度大约快100倍。 (约50秒,约0.3秒)我期望有所改善,但是谁能解释为什么如此剧烈?where子句中使用的列均已建立索引。SQL是否在where子句中每行执行一次查询? 更新 -说明结果: 区别在于查询“(id)in()”的第二部分- vs 1带有连接的索引行: 问题答案: “相关子

  • 问题内容: 对于开发人员何时使用联接而不是子查询是否有经验法则还是相同的? 问题答案: 取决于RDBMS。您应该比较两个查询的执行计划。 根据我对Oracle 10和11的经验,执行计划始终是相同的。

  • 问题内容: 谁能看到以下查询出了什么问题? 当我运行它时,我得到: #1064-您的SQL语法有误;检查与您的MySQL服务器版本相对应的手册以获取正确的语法,以在第8行的’a where a.CompetitionID = Competition.CompetitionID’附近使用 问题答案: 主要问题是内部查询不能与外部语句上的子句相关,因为在内部子查询执行之前,where过滤器首先应用于要

  • 问题内容: 我重构了从另一家公司继承来的应用程序的慢速部分,以使用内部联接而不是子查询,例如: 重构后的查询运行速度提高了约100倍。 (约50秒,约0.3秒),我期望有所改善,但谁能解释为什么如此剧烈?where子句中使用的列均已建立索引。SQL是否在where子句中每行执行一次查询? 更新 -说明结果: 区别在于“(())中的id”查询的第二部分- vs 1带有连接的索引行: 问题答案: “相

  • 我只想检查一下QueryDSL版本3.1.1。-是否仍然不可能与子查询连接,就像这里的答案所写的:JPQL/querydsl:join subquery and get aliased column