为什么IN条件比sql中的"="慢?

Ita*_*vka 28 mysql sql comparison performance

检查问题此SELECT查询需要180秒才能完成(检查问题本身的注释).
IN只能与一个值进行比较,但时差仍然很大.
为什么会那样?

Mar*_*ers 47

简介:这是MySQL中的一个已知问题,并在MySQL 5.6.x中得到修复.问题是由于使用IN的子查询被错误地识别为从属子查询而不是独立子查询时缺少优化.


当您在原始查询上运行EXPLAIN时,它返回:

1  'PRIMARY'             'question_law_version'  'ALL'  ''  ''  ''  ''  10148  'Using where'
2  'DEPENDENT SUBQUERY'  'question_law_version'  'ALL'  ''  ''  ''  ''  10148  'Using where'
3  'DEPENDENT SUBQUERY'  'question_law'          'ALL'  ''  ''  ''  ''  10040  'Using where'

当你改变IN=你得到这个:

1  'PRIMARY'   'question_law_version'  'ALL'  ''  ''  ''  ''  10148  'Using where'
2  'SUBQUERY'  'question_law_version'  'ALL'  ''  ''  ''  ''  10148  'Using where'
3  'SUBQUERY'  'question_law'          'ALL'  ''  ''  ''  ''  10040  'Using where'

每个从属子查询在其包含的查询中每行运行一次,而子查询仅运行一次.当有条件可以转换为连接时,MySQL有时可以优化从属子查询,但事实并非如此.

现在这当然留下了为什么MySQL认为IN版本需要是依赖子查询的问题.我已经制作了查询的简化版本以帮助调查此问题.我创建了两个表'foo'和'bar',其中前者只包含一个id列,后者包含id和foo id(虽然我没有创建外键约束).然后我用1000行填充了两个表:

CREATE TABLE foo (id INT PRIMARY KEY NOT NULL);
CREATE TABLE bar (id INT PRIMARY KEY, foo_id INT NOT NULL);

-- populate tables with 1000 rows in each

SELECT id
FROM foo
WHERE id IN
(
    SELECT MAX(foo_id)
    FROM bar
);
Run Code Online (Sandbox Code Playgroud)

此简化查询具有与以前相同的问题 - 内部选择被视为从属子查询,并且不执行优化,导致内部查询每行运行一次.查询需要几秒钟才能运行.再次更改IN=允许查询几乎立即运行.

我用来填充表格的代码如下,以防有人希望重现结果.

CREATE TABLE filler (
        id INT NOT NULL PRIMARY KEY AUTO_INCREMENT
) ENGINE=Memory;

DELIMITER $$

CREATE PROCEDURE prc_filler(cnt INT)
BEGIN
        DECLARE _cnt INT;
        SET _cnt = 1;
        WHILE _cnt <= cnt DO
                INSERT
                INTO    filler
                SELECT  _cnt;
                SET _cnt = _cnt + 1;
        END WHILE;
END
$$

DELIMITER ;

CALL prc_filler(1000);

INSERT foo SELECT id FROM filler;
INSERT bar SELECT id, id FROM filler;
Run Code Online (Sandbox Code Playgroud)

  • 有没有办法强制优化器将子查询视为子查询而不是从属子查询? (2认同)