2014-11-05 2 views
2

У меня есть очень простой MYSQL таблица с 2 столбцами и я бегом этого вопроса:MYSQL повысить производительность запросов при использовании OR

SELECT * FROM table WHERE (col1 = '123' AND col2 = '456') 
         OR (col1 = '456' AND col2 = '123') 

Col1 и col2 являются составным первичным ключом: PRIMARY KEY('col1','col2'). Каждый из обоего также внешнего ключа для первичного ключа в другой таблице

Когда я запускал команду EXPLAIN для вышеуказанного запроса я получил следующее:

id select_type table type possible_keys key key_len ref rows Extra 
1 SIMPLE  table index PRIMARY,col2 col2 8 NULL 1 Using where; Using index 

type в приведенном выше результате index, который очень похож на All и поэтому очень вероятно, что он будет медленным в большой базе данных. Есть ли способ улучшить приведенную выше команду select

ответ

3

В действительности заявления, такие как likely to be slow on a large database, должны быть красным флагом.

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

В любом случае, давайте ответим на вопрос.

Да, гипотетически, поскольку мы используем индексный файл, и если у вас есть огромное количество данных и вы можете запросить эту таблицу, это может быть потенциально оптимизировано путем разделения запроса на несколько наборов исполнений, а не на использование операторов выражений в запросе , если вы только собираетесь запросить в два раза, как в вашем примере вы могли бы достичь более высокой производительности с union, такие как:

(
    SELECT * FROM test 
    WHERE 
    (
     col1 = 123 AND col2 = 456 
    ) 
) 
UNION 
(
    SELECT * FROM test 
    WHERE 
    (
     col1 = 456 AND col2 = 123 
    ) 
) 

EXPLAIN для этого запроса выглядит следующим образом:

ID  SELECT_TYPE TABLE  TYPE POSSIBLE_KEYS KEY KEY_LEN REF ROWS EXTRA 
1  PRIMARY  test  ref PRIMARY PRIMARY 4 const 1 Using where; Using index 
2  UNION  test  ref PRIMARY PRIMARY 4 const 2 Using where; Using index 
(null) UNION RESULT <union1,2> ALL (null) (null) (null) (null) (null) 

Взгляните на этот скрипт SQL http://sqlfiddle.com/#!2/9dc07a/1/0 для простого тестового примера.

Язык, который я использовал в этом сообщении, например, «возможно», «может» и т. Д., Потому что я не загрузил этот пример сотнями миллионов записей - я бы настоятельно предложил вам сделать это, детализируйте свой запрос более подробно.

К сожалению, с оптимизацией не всегда есть ясный и простой ответ на выполнение x, чтобы получить большую производительность. Оптимизатор запросов - это сложный зверь, и иногда попытка получить каждую каплю производительности может фактически повредить ваше приложение (I ' m, говорящий из опыта здесь), пожалуйста, если вам не нужно беспокоиться об этих микрооптимизациях - не делайте этого, если вы затем оцените, профиль и протестируйте его полностью, прежде чем принимать решение о подходе.

1

Оптимизатор, основанный на затратах, выбирает план выполнения на основе статистики, имеющейся в таблице. Он знает, что там не так много строк, и поэтому пустая трата времени делает что-то умное. Увеличьте количество строк в таблице и убедитесь, что у вас высокая мощность (много разных значений) и снова запустите план объяснения, и вы увидите изменение выполнения.

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