This SELECT query takes 180 seconds to finish
UPDATE:
Just to mention it on a more visible place. When I changed IN for =, the query execution time went from 180 down to 0.00008 seconds. Ridiculous speed difference.
This SQL query takes 180 seconds to finish! How is that possible? is there a way to optimize it to be faster?
SELECT IdLawVersionValidFrom
FROM q开发者_如何转开发uestion_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
)
)
There are only about 5000 rows in each table so it shouldn't be so slow.
(Posting my comment as an answer as apparently it did make a difference!)
Any difference if you change the
IN
to=
?
If anyone wants to investigate this further I've just done a test and found it very easy to reproduce.
Create Table
CREATE TABLE `filler` (
`id` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
)
Create Procedure
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
Populate Table
call prc_filler(5000)
Query 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
Query 2 (same problem)
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
Here is a good explanation why = is better than IN
Mysql has problems with inner queries - not well using indexes (if at all).
- Make sure you have indexes on all the fields in the join/where/order etc.
- get those Max and MIN values in a separate query (use stored procedure for this entire thing if you want to skip the multiple requests overhead Or just do a request with multiple queries.
Anyway:
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
You can use EXPLAIN
to find out how is it possible for a query to execute so slow.
MySQL does not really like nested subselects so probably what happens is that it goes and does sorts on disk to get min and max and fail to reuse results.
Rewriting as joins would probably help it.
If just looking for a quick fix try:
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
精彩评论