Этот запрос SELECT занимает 180 секунд, чтобы закончить

ОБНОВИТЬ:

Просто чтобы упомянуть об этом в более заметном месте. Когда я изменил 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 строк, поэтому она не должна быть такой медленной.

3 ответа

Решение

(Публикация моего комментария как ответа, по-видимому, имела значение!)

Любая разница, если вы измените 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
    )
  )

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
    )
  )

http://img291.imageshack.us/img291/8129/52037513.png

Вот хорошее объяснение, почему = лучше, чем IN

Mysql имеет проблемы с внутренними запросами - не очень хорошо использовать индексы (если вообще).

  1. Убедитесь, что у вас есть индексы для всех полей в объединении / где / порядок и т. Д.
  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

Ты можешь использовать 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
Другие вопросы по тегам