Trois tables:
product
: avec colonnes: ( a, g, ...a_lot_more... )
a: PK, clustered
g: bit-column
main
: avec colonnes: ( c, f, a, b, ...a_lot_more... )
c: PK, clustered
f: bit-column
(a, b): UQ
lookup
avec des colonnes: ( a, b, c, i )
(a, b): PK, clustered
a: FK to product(a)
c: UQ, FK to main(c)
i: bit-column
Je ne trouve pas de bons index pour la jointure:
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
J'ai essayé un indice de couverture product (g, a, ...)
et il est utilisé mais pas avec des résultats spectaculaires.
Certaines combinaisons d'index sur la lookup
table produisent des plans d'exécution avec fusion d'index, avec un léger gain d'efficacité par rapport au plan précédent.
Y a-t-il une combinaison évidente qui me manque?
Une refonte de la structure pourrait-elle aider?
Le SGBD est MySQL 5.5 et toutes les tables utilisent InnoDB.
Tailles de table:
product: 67K , g applied: 64K
main: 420K , f applied: 190K
lookup: 12M , b,i applied: 67K
mysql
mysql-5.5
optimization
ypercubeᵀᴹ
la source
la source
Réponses:
Cela me fait mal ...
J'ai déjà dû utiliser des tables temporaires avec InnoDB. Chargez-les avec des filtres, créez un index, rejoignez ces tables temporaires.
Le problème, comme je le pense, est que InnoDB ne dispose que de l'algorithme Nested Join: les optimiseurs de requête RDBMS adultes ont plus à utiliser. Ceci est basé sur la tentative d'exécution de charges de type Data Warehouse sur InnoDB.
Les tables temporaires entraînent la complexité globale au niveau de l'optimiseur de requêtes MySQL ...
la source
main
) en dénormalisant les données danslookup
?Il ressemble à un produit cartésien. Refaire les critères JOIN
SUGGESTION ALTERNATIVE
Cela peut sembler peu orthodoxe et sent probablement comme SQL Anitpattern, mais ici ça va ...
Je n'ai pas déplacé le
product.g = 1
etmain.f = 1
dans les sous-requêtes car ce sont des champs de bits et je vais juste faire un scan de table à ce point. Même si les champs de bits étaient des index, l'Optimiseur de requête ignorerait simplement un tel index.Bien sûr, vous pouvez changer
SELECT * FROM lookup
deSELECT a FROM lookup
si votre SELECT ne pas besoin de quoi que ce soitlookup
Peut-être impliquer a, b dans la jointure entre recherche et principal si cela a du sens
ou remettre c et joindre sur trois colonnes (Index sur les trois colonnes dans
main
etlookup
)la source
main.f
etproduct.g
??? Si la cardinalité demain.f
etproduct.g
pour la valeur est 1 est inférieure à 5% des lignes du tableau, un index surmain.f
etproduct.g
peut être justifié.main.f
etproduct.g
est 2, vous pouvez abandonner ces index.