10.2.1.22 Оптимизация выражений конструктора строк
Конструкторы строк позволяют одновременно сравнивать несколько значений. Например, эти два утверждения семантически эквивалентны:
SELECT * FROM t1 WHERE (column1,column2) = (1,1);
SELECT * FROM t1 WHERE column1 = 1 AND column2 = 1;
Кроме того, оптимизатор обрабатывает оба выражения одинаково.
Оптимизатор менее склонен использовать доступные индексы, если столбцы конструктора строк не охватывают префикс индекса. Рассмотрим следующую таблицу, которая имеет первичный ключ по (c1, c2, c3):
CREATE TABLE t1 (
c1 INT, c2 INT, c3 INT, c4 CHAR(100),
PRIMARY KEY(c1,c2,c3)
);
В этом запросе клаузула WHERE использует все столбцы в индексе. Однако сам конструктор строк не охватывает префикс индекса, в результате чего оптимизатор использует только c1 (key_len=4, размер c1):
mysql> EXPLAIN SELECT * FROM t1
WHERE c1=1 AND (c2,c3) > (1,1)\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t1
partitions: NULL
type: ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const
rows: 3
filtered: 100.00
Extra: Using where
В таких случаях переписывание выражения конструктора строк с использованием эквивалентного выражения без конструктора может привести к более полному использованию индекса. Для данного запроса выражения конструктора строк и эквивалентные выражения без конструктора:
(c2,c3) > (1,1)
c2 > 1 OR ((c2 = 1) AND (c3 > 1))
Переписывание запроса с использованием выражения без конструктора приводит к тому, что оптимизатор использует все три столбца в индексе (key_len=12):
mysql> EXPLAIN SELECT * FROM t1
WHERE c1 = 1 AND (c2 > 1 OR ((c2 = 1) AND (c3 > 1)))\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t1
partitions: NULL
type: range
possible_keys: PRIMARY
key: PRIMARY
key_len: 12
ref: NULL
rows: 3
filtered: 100.00
Extra: Using where
Таким образом, для достижения лучших результатов следует избегать смешивания конструкторов строк с выражениями AND/OR. Используйте один или другой.
В определенных условиях оптимизатор может применить метод диапазонного доступа к выражениям IN() с аргументами конструктора строк. См. Оптимизацию диапазонов выражений конструктора строк.
© 2025 Oracle
Licensed under the GPLv2 License.