更新:
只是在更加明显的地方提及它。当我将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
)
)
每张表中只有大约5000行,因此它不应该太慢。
答案 0 :(得分:16)
(将我的评论作为答案发布,因为显然它确实有所作为!)
如果更改
IN
,则有任何区别 到=
?
如果有人想进一步调查,我刚刚做了一个测试,发现它很容易重现。
创建表
CREATE TABLE `filler` (
`id` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
)
创建程序
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
填充表
call prc_filler(5000)
查询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
)
)
Equals Explain Output 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
)
)
In Explain Output http://img291.imageshack.us/img291/8129/52037513.png
答案 1 :(得分:12)
Here is a good explanation why = is better than IN
Mysql内部查询存在问题 - 不能很好地使用索引(如果有的话)。
反正:
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
答案 2 :(得分:4)
您可以使用EXPLAIN
来了解查询如何执行得如此之慢。
MySQL并不真正喜欢嵌套的子选择,所以可能会发生的事情是它会在磁盘上进行排序以获得最小值和最大值并且无法重用结果。
重写为联接可能会有所帮助。
如果只是寻找快速解决方法,请尝试:
SET @temp1 =
(
SELECT MIN(IdQuestionLaw)
FROM question_law
WHERE IdQuestion = 236 AND IdQuestionLaw > 63
)
SET @temp2 =
(
SELECT MAX(IdQuestionLawVersion)
FROM question_law_version
WHERE IdQuestionLaw = @temp1
)
SELECT IdLawVersionValidFrom
FROM question_law_version
WHERE IdQuestionLawVersion = @temp2