Этот запрос SELECT занимает 180 секунд.
UPDATE:
Просто упомянуть об этом на более заметном месте. Когда я изменил IN for =, время выполнения запроса перешло от 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 строк, поэтому он не должен быть настолько медленным.
Ответы
Ответ 1
(Опубликуя мой комментарий в качестве ответа, поскольку, по-видимому, это имело значение!)
Любая разница, если вы измените 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 Объяснить вывод 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
)
)
В Explain Output http://img291.imageshack.us/img291/8129/52037513.png
Ответ 2
Вот хорошее объяснение, почему = лучше, чем IN
Mysql имеет проблемы с внутренними запросами - не очень хорошо использует индексы (если вообще).
- Убедитесь, что у вас есть индексы во всех полях в файле join/where/order и т.д.
- получить те значения 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
Ответ 3
Вы можете использовать EXPLAIN
, чтобы узнать, как это возможно, чтобы запрос выполнялся так медленно.
MySQL не очень любит вложенные подзапросы, поэтому, вероятно, происходит то, что он идет, и делает сортировки на диске, чтобы получить min и max и не использовать повторно результаты.
Переписывание в виде объединений, вероятно, поможет ему.
Если вы ищете быстрое исправление, попробуйте:
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