2008-11-22 2 views
1

ПРИМЕЧАНИЕ: исходный вопрос спорный, но сканирование на дно для чего-то важного.Как оптимизировать запросы MySQL с помощью констант?

У меня есть запрос, я хочу, чтобы оптимизировать, который выглядит примерно так:

select cols from tbl where col = "some run time value" limit 1; 

Я хочу знать, что используются клавиши, но все, что я пройти, чтобы объяснить, что может оптимизировать ИНЕКЕ ничто («Невозможно, ГДЕ заметило ...»), потому что я накормил его постоянной.

  • Есть ли способ сказать mysql не делать постоянные оптимизации в объяснении?
  • Я что-то пропустил?
  • Есть ли лучший способ получить необходимую информацию?

Редактировать: EXPLAIN, похоже, дает мне план запроса, который будет получен из постоянных значений. Поскольку запрос является частью хранимой процедуры (и планы запросов IIRC в файлах создаются до их вызова), это делает меня нехорошим, потому что значение не является постоянным. Я хочу, чтобы узнать, какой план запроса будет генерировать оптимизатор, когда он не знает, что такое фактическое значение.

Я пропустил что-то?

Редакция 2: Кажется, что MySQL в запросах в другом месте, по-видимому, всегда регенерирует планы запросов, если вы не уходите с пути, чтобы повторно использовать их. Даже в хранимых процедурах. Из этого, похоже, мой вопрос спорный.

Однако это не делает то, что я действительно хотел бы знать, спорный вопрос:Как оптимизировать запрос, содержащий значения, которые постоянны в пределах какого-либо конкретного запроса, но где я, программист, не известны заранее какое значение будет использовано? - Например, мой код на стороне клиента генерирует запрос с номером в его статье where. Несколько раз число приводит к тому, что невозможно, если пункт в других случаях это не будет. Как я могу использовать объяснение, чтобы проверить, насколько хорошо оптимизирован запрос?

Лучший подход, который я вижу с самого начала, - это запустить EXPLAIN на нем для полной матрицы существующих/не существующих случаев. На самом деле это не очень хорошее решение, так как это будет трудно и непросто сделать вручную.

ответ

4

Например, мой код на стороне клиента генерирует запрос с номером в его разделе where.

Несколько раз число приведет к невозможному, если пункт, в противном случае он не будет.

Как я могу использовать объяснение, чтобы проверить, насколько хорошо оптимизирован запрос?

MySQL строит различные планы запросов для разных значений связанных параметров.

В этом article вы можете прочитать список, когда делает MySQL оптимизатор делает то, что:

 
    Action          When 

    Query parse         PREPARE 
    Negation elimination      PREPARE 
    Subquery re-writes       PREPARE 

    Nested JOIN simplification     First EXECUTE 
    OUTER->INNER JOIN conversions    First EXECUTE 

    Partition pruning       Every EXECUTE 
    COUNT/MIN/MAX elimination     Every EXECUTE 
    Constant subexpression removal    Every EXECUTE 
    Equality propagation      Every EXECUTE 
    Constant table detection     Every EXECUTE 
    ref access analysis       Every EXECUTE 
    range/index_merge analysis and optimization Every EXECUTE 
    Join optimization       Every EXECUTE 

Существует еще одна вещь отсутствует в этом списке.

MySQL может восстановить план запроса на каждый JOIN итерация: эдакий называется range checking for each record.

Если у вас есть составной индекс по таблице:

CREATE INDEX ix_table2_col1_col2 ON table2 (col1, col2) 

и запрос следующим образом:

SELECT * 
FROM table1 t1 
JOIN table2 t2 
ON  t2.col1 = t1.value1 
     AND t2.col2 BETWEEN t1.value2_lowerbound AND t2.value2_upperbound 

, MySQL не будет использовать индекс RANGE доступа от (t1.value1, t1.value2_lowerbound) к (t1.value1, t1.value2_upperbound). Вместо этого он будет использовать индекс REF на (t1.value) и просто отфильтровать неправильные значения.

Но если переписать запрос так:

SELECT * 
FROM table1 t1 
JOIN table2 t2 
ON  t2.col1 <= t1.value1 
     AND t2.col1 >= t2.value1 
     AND t2.col2 BETWEEN t1.value2_lowerbound AND t2.value2_upperbound 

, то MySQL будет перепроверить индекс RANGE доступа для каждой записи из table1 и решить, следует ли использовать RANGE доступ на лету.

Вы можете прочитать об этом в этих статьях в моем блоге:

Все эти вещи используют RANGE CHECKING FOR EACH RECORD

Возвращаясь к вашему вопросу: нет никакого способа узнать, какой план будет MySQL использовать для каждого заданных постоянная, так как нет никакого плана до того, как будет задана константа.

К сожалению, нет никакого способа заставить MySQL использовать один план запроса для каждого значения связанного параметра.

Вы можете управлять эс JOIN порядка и INDEX»выбирается с помощью STRAIGHT_JOIN и FORCE INDEX положения, но они не заставят определенный путь доступа по индексу или запретить IMPOSSIBLE WHERE.

С другой стороны, для всех JOIN, MySQL используется только NESTED LOOPS. Это означает, что если вы построите правильный JOIN или выберите нужный указатель, MySQL, вероятно, выиграют от всех IMPOSSIBLE WHERE.

5

Вы получаете сообщение «Impossible WHERE заметил», потому что указанное вами значение не находится в столбце, а не только потому, что оно является константой. Вы можете либо 1) использовать значение, которое существует в столбце или 2) просто сказать col = col:

explain select cols from tbl where col = col; 
+0

Пустота из тех, которые решают мою проблему. Я хочу знать, что такое план запроса, где оптимизатор * не знает *, если значение находится в столбце. – BCS 2008-11-23 03:01:28

+0

Вот как это работает: Оптимизатор определяет, возможен ли выбор, читая таблицы констант и системы, если это тогда, вы получаете план запроса. Мое решение даст вам план запроса, потому что оптимизатор не остановится раньше, потому что считает, что запрос невозможно. – 2008-11-23 03:28:24

+0

Да, это даст вам план запроса и позволит избежать проблемы с предложением where, которое никогда не будет передано, но тогда оно будет считать, что предложение where всегда будет проходить, и это тоже не так. Я хочу знать, как все будет работать в обоих случаях. (см. edit2) – BCS 2008-11-23 21:19:28

0

Как оптимизировать запрос со значениями, которые являются постоянными только в запросе, но где я, программист , заранее не знаете, какое значение будет использовано?

Использование индексов в конкретных столбцах (или даже при комбинации столбцов, если вы всегда запрашиваете данные столбцы вместе). Если у вас есть индексы, планировщик запросов будет потенциально использовать их.

Что касается «невозможных» значений: планировщик запросов можно сделать вывод, что данное значение не в таблице из нескольких источников:

  • если есть индекс на определенном столбце, то можно заметить, что конкретный значение велико или меньше любого значения в индексе (значения min/max принимают постоянное время для извлечения из индексов)
  • , если вы ошибаетесь в том же типе (если вы запрашиваете числовой столбец равным тексту)

PS. В общем, создание плана запроса не дорогое, и его лучше воссоздавать, чем повторное использование, поскольку условия могут измениться с момента создания плана запроса и может возникнуть лучший план запроса.

Смежные вопросы