Три стола:
product
: с колонками: ( a, g, ...a_lot_more... )
a: PK, clustered
g: bit-column
main
: с колонками: ( c, f, a, b, ...a_lot_more... )
c: PK, clustered
f: bit-column
(a, b): UQ
lookup
с колоннами: ( a, b, c, i )
(a, b): PK, clustered
a: FK to product(a)
c: UQ, FK to main(c)
i: bit-column
Я не могу найти хорошие индексы для объединения:
FROM
product
JOIN
lookup
ON lookup.a = product.a
JOIN
main
ON main.c = lookup.c
WHERE
product.g = 1
AND
main.f = 1
AND
lookup.i = 1
AND lookup.b = 17
Я примерил индекс покрытия, product (g, a, ...)
и он используется, но не с впечатляющими результатами.
Некоторые комбинации индексов в lookup
таблице создают планы выполнения с объединением индексов с небольшим приростом эффективности по сравнению с предыдущим планом.
Есть ли какая-то очевидная комбинация, которую мне не хватает?
Может ли помочь реструктуризация конструкции?
СУБД - MySQL 5.5, и все таблицы используют InnoDB.
Размеры стола:
product: 67K , g applied: 64K
main: 420K , f applied: 190K
lookup: 12M , b,i applied: 67K
mysql
mysql-5.5
optimization
ypercubeᵀᴹ
источник
источник
Ответы:
Это причиняет мне боль ...
Я должен был использовать временные таблицы с InnoDB раньше. Загрузите их с фильтрами, создайте индекс, присоединитесь к этой временной таблице.
Я считаю, что проблема заключается в том, что InnoDB имеет только алгоритм Nested Join: взрослые оптимизаторы запросов к RDBMS могут использовать больше. Это основано на попытке запустить загрузку типов хранилища данных на InnoDB.
Временные таблицы тянут общую сложность до уровня оптимизатора запросов MySQL ...
источник
main
) путем денормализации данных вlookup
?Это похоже на декартово произведение. Повторите критерии присоединения
АЛЬТЕРНАТИВНОЕ ПРЕДЛОЖЕНИЕ
Это может показаться неортодоксальным и, вероятно, пахнет SQL Anitpattern, но здесь все идет ...
Я не перемещал
product.g = 1
иmain.f = 1
в подзапросы, потому что они являются битовыми полями и просто будут выполнять сканирование таблицы в этой точке. Даже если бы битовые поля были индексами, Оптимизатор запросов просто проигнорировал бы такой индекс.Конечно, вы могли бы изменить ,
SELECT * FROM lookup
чтобы ,SELECT a FROM lookup
если ваш ВЫБРАТЬ не нужно ничего отlookup
Возможно, включите a, b в JOIN между lookup и main, если это имеет смысл
или вставьте обратно c и объедините три столбца (индекс по трем столбцам в
main
иlookup
)источник
main.f
иproduct.g
??? Если мощностьmain.f
иproduct.g
для значения 1 составляет менее 5% строк таблицы, индекс наmain.f
иproduct.g
может быть оправданным.main.f
иproduct.g
2, то вы могли бы угробить эти индексы.