Этот запрос 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