Tres mesas:
product
: con columnas: ( a, g, ...a_lot_more... )
a: PK, clustered
g: bit-column
main
: con columnas: ( c, f, a, b, ...a_lot_more... )
c: PK, clustered
f: bit-column
(a, b): UQ
lookup
con columnas: ( a, b, c, i )
(a, b): PK, clustered
a: FK to product(a)
c: UQ, FK to main(c)
i: bit-column
No puedo encontrar buenos índices para la unión:
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
Intenté un índice de cobertura product (g, a, ...)
y se usa pero no con resultados espectaculares.
Algunas combinaciones de índices en la lookup
tabla producen planes de ejecución con fusión de índice, con una ligera ganancia de eficiencia sobre el plan anterior.
¿Hay alguna combinación obvia que me estoy perdiendo?
¿Podría ayudar un rediseño de la estructura?
El DBMS es MySQL 5.5 y todas las tablas están usando InnoDB.
Tamaños de mesa:
product: 67K , g applied: 64K
main: 420K , f applied: 190K
lookup: 12M , b,i applied: 67K
mysql
mysql-5.5
optimization
ypercubeᵀᴹ
fuente
fuente
Respuestas:
Esto me duele ...
He tenido que usar tablas temporales con InnoDB antes. Cárguelos con filtros, cree un índice, únase a esta tabla temporal.
Creo que el problema es que si InnoDB solo tiene un algoritmo de unión anidada: los optimizadores de consultas RDBMS adultos tienen más para usar. Esto se basa en intentar ejecutar cargas de tipo Data Warehouse en InnoDB.
Las tablas temporales arrastran la complejidad general por el nivel del optimizador de consultas MySQL ...
fuente
main
) desnormalizando datos enlookup
?Parece un producto cartesiano. Rehacer los criterios de JOIN
SUGERENCIA ALTERNATIVA
Esto puede parecer poco ortodoxo y probablemente huele a SQL Anitpattern, pero aquí va ...
No moví el
product.g = 1
ymain.f = 1
a las subconsultas porque son campos de bits y solo haré un escaneo de la tabla en el punto. Incluso si los campos de bits fueran índices, el Optimizador de consultas simplemente ignoraría dicho índice.Por supuesto, puede cambiar
SELECT * FROM lookup
aSELECT a FROM lookup
si su SELECT no necesita nada delookup
Quizás implique a, b en la UNIÓN entre búsqueda y principal si esto tiene sentido
o vuelva a colocar c y únase en tres columnas (Indice las tres columnas en
main
ylookup
)fuente
main.f
yproduct.g
??? Si la cardinalidad demain.f
yproduct.g
para el valor es 1 es inferior al 5% de las filas de la tabla, un índice enmain.f
yproduct.g
puede ser justificable.main.f
yproduct.g
es 2, podría deshacerse de esos índices.