комбинированный запрос
select a, b from A where a > 5 and b in (select b from B where c = "some")
занимает примерно в 30 раз больше времени, чем фиксированный запрос
select a, b from A where a > 5 and b in (1, 2, 3)
хотя
select b from B where c = "some"
приводит к тому же набору строк, который использовался в фиксированном запросе, (1, 2, 3)
select b from B where c = "some"
в одиночку требуется 0,01 с для выполнения
select a, b from A where a > 5
требуется 0,3 с.
Есть индекс над (a, b) на A.
Анализ комбинированного запроса:
analyze select a, b from A where a > 5 and b in (select b from B)
*************************** 1. row ***************************
id: 1
select_type: PRIMARY
table: A
type: range
possible_keys: idx_a_b
key: idx_a_b
key_len: 8
ref: NULL
rows: 126459
r_rows: 66181.00
filtered: 100.00
r_filtered: 100.00
Extra: Using index condition; Using temporary; Using filesort
*************************** 2. row ***************************
id: 1
select_type: PRIMARY
table: B
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 2
ref: A.b
rows: 1
r_rows: 1.00
filtered: 100.00
r_filtered: 0.09
Extra: Using where
Обратите внимание, что r_rows = 66181 соответствует select a, b from A where a > 5
.
Похоже, MariaDB использует только часть индекса и игнорирует b, которые она должна получить из подзапроса на первом шаге. расширенные объяснения показывают, что MariaDB заменяет мой запрос на
select b, a from B join A where ((B.b = A.b) and (A.a > 5) and (B.c = "some"))
Странно, если при заданном фиксированном наборе (1, 2, 3), возвращаемом подзапросом, вместо самого подзапроса, MariaDB действительно, кажется, использует одновременно и a, и b индекса, как это может быть наблюдается при анализе фиксированного запроса:
analyze select a, b from A where a > 5 and y in (1, 2, 3)
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: A
type: range
possible_keys: idx_a_b
key: idx_a_b
key_len: 10
ref: NULL
rows: 126459
r_rows: 59.00
filtered: 100.00
r_filtered: 100.00
Extra: Using index condition; Using temporary; Using filesort
r_rows = 59 соответствует размеру результирующего набора для обоих запросов (комбинированный и фиксированный).
Как я могу заставить MariaDB использовать тот же план запроса, что и в фиксированном запросе, используя как a, так и подзапрос b из индекса A?