此SELECT查询需要180秒才能完成

Ric*_*nop 12 mysql sql select

更新:

只是在更加明显的地方提及它.当我将IN更改为=时,查询执行时间从180下降到0.00008秒.可笑的速度差异.


此SQL查询需要180秒才能完成!怎么可能?有没有办法优化它更快?

SELECT IdLawVersionValidFrom 
FROM question_law_version 
WHERE IdQuestionLawVersion IN 
  (
  SELECT MAX(IdQuestionLawVersion) 
  FROM question_law_version 
  WHERE IdQuestionLaw IN 
    (
    SELECT MIN(IdQuestionLaw) 
    FROM question_law 
    WHERE IdQuestion=236 AND IdQuestionLaw>63
    )
  )
Run Code Online (Sandbox Code Playgroud)

每个表中只有大约5000行,所以它不应该这么慢.

Mar*_*ith 16

(将我的评论作为答案发布,因为它显然确实有所作为!)

如果你更改为IN=什么区别?

如果有人想进一步调查,我刚刚做了一个测试,发现它很容易重现.

创建表

CREATE TABLE `filler` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`)
) 
Run Code Online (Sandbox Code Playgroud)

创建程序

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
Run Code Online (Sandbox Code Playgroud)

填充表

  call prc_filler(5000)
Run Code Online (Sandbox Code Playgroud)

查询1

SELECT id 
FROM filler 
WHERE id =  (SELECT MAX(id) FROM filler  WHERE id =   
 ( SELECT MIN(id) 
    FROM filler
    WHERE id between 2000 and 3000
    )
  )
Run Code Online (Sandbox Code Playgroud)

等于解释输出http://img689.imageshack.us/img689/5592/equals.png

查询2(同样的问题)

SELECT id 
FROM filler 
WHERE id in  (SELECT MAX(id) FROM filler  WHERE id in   
 ( SELECT MIN(id) 
    FROM filler
    WHERE id between 2000 and 3000
    )
  )
Run Code Online (Sandbox Code Playgroud)

在解释输出中http://img291.imageshack.us/img291/8129/52037513.png

  • @Wade - 马克的答案已经覆盖了我认为http://stackoverflow.com/questions/3417074/why-would-an-in-condition-be-slower-than-in-sql/3417190#3417190 (3认同)

Ita*_*vka 12

这里有一个很好的解释为什么=比IN好

Mysql在内部查询方面存在问题 - 不能很好地使用索引(如果有的话).

  1. 确保您在join/where/order等中的所有字段都有索引.
  2. 在单独的查询中获取那些Max和MIN值(如果要跳过多个请求开销,或者只是使用多个查询执行请求,请使用存储过程进行此操作.

无论如何:

SELECT
         IdLawVersionValidFrom 
FROM 
         question_law_version 
    JOIN 
         question_law
      ON 
         question_law_version.IdQuestionLaw = question_law.IdQuestionLaw
WHERE 
         question_law.IdQuestion=236 
     AND 
         question_law.IdQuestionLaw>63

ORDER BY 
         IdQuestionLawVersion DESC, 
         question_law.IdQuestionLaw ASC
LIMIT 1
Run Code Online (Sandbox Code Playgroud)