MySQL: очень медленный запрос с использованием составного ключа в предложении WHERE IN - PullRequest
0 голосов
/ 06 ноября 2018

У меня есть таблица MySQL с составным первичным ключом: (id1, id2). Я хочу получить все строки, где (id1, id2) среди списка пар, например. ((1,2), (2,6), (1,6)). Когда этот список пар содержит только один элемент, кажется, что индекс используется, поскольку запрос выполняется очень быстро. Если список пар содержит более одного элемента, запрос выполняется крайне медленно:

mysql> SELECT id1, id2 FROM my_table WHERE (id1, id2) in ((1817279, 0));
+---------+--------+
|   id1   |   id2  |
+---------+--------+
| 1817279 |      0 |
+---------+--------+
1 row in set (0.00 sec)

mysql> SELECT id1, id2 FROM my_table WHERE (id1, id2) in ((1819781, 2));
+---------+--------+
|   id1   |   id2  |
+---------+--------+
| 1819781 |      2 |
+---------+--------+
1 row in set (0.00 sec)

mysql> SELECT id1, id2 FROM my_table WHERE (id1, id2) in ((1817279, 0), (1819781, 2));
+---------+--------+
|   id1   |   id2  |
+---------+--------+
| 1817279 |      0 |
| 1819781 |      2 |
+---------+--------+
2 rows in set (1 min 22.72 sec)

Я попытался использовать FORCE INDEX (PRIMARY) безуспешно. Есть идеи, почему MySQL не может использовать индекс?

Вот моя версия MySQL: mysql Ver 14.14 Distrib 5.6.33, for debian-linux-gnu (x86_64) using EditLine wrapper

1 Ответ

0 голосов
/ 07 ноября 2018

«Конструкторы строк» ​​не оптимизировались до 5.7.3. Пример WHERE (id1, id2) = (11, 22). Из журнала изменений: 2013-12-03 5.7.3

Milestone 13 - Функциональность добавлена ​​или изменена:

Теперь оптимизатор может применять метод доступа к сканированию диапазона Запросы этой формы:

ВЫБРАТЬ ... ОТ t1 ГДЕ (col_1, col_2) IN (('a', 'b'), ('c', 'd' ));

Раньше для сканирования диапазона необходимо было выполнить запрос записывается как:

ВЫБРАТЬ ... ОТ t1 ГДЕ (col_1 = 'a' И col_2 = 'b') ИЛИ (col_1 = 'c' AND col_2 = 'd');

Чтобы оптимизатор использовал сканирование диапазона, запросы должны удовлетворять этим Условия:

  • Можно использовать только предикаты IN, но не IN.

  • В конструкторе строк могут быть только ссылки на столбцы в левой части предиката IN.

  • В правой части предиката IN должно быть несколько конструкторов строк.

  • Конструкторы строк в правой части предиката IN должны содержать только константы времени выполнения, которые являются литералами или локальными ссылки на столбцы, которые связаны с константами во время выполнения.

Вывод EXPLAIN для соответствующих запросов изменится с полной таблицы или индексное сканирование для сканирования диапазона. Изменения также видны, проверив значения Handler_read_first , Handler_read_key , а также Handler_read_next переменные состояния.

...