Drei Tabellen:
product
: mit Spalten: ( a, g, ...a_lot_more... )
a: PK, clustered
g: bit-column
main
: mit Spalten: ( c, f, a, b, ...a_lot_more... )
c: PK, clustered
f: bit-column
(a, b): UQ
lookup
mit Spalten: ( a, b, c, i )
(a, b): PK, clustered
a: FK to product(a)
c: UQ, FK to main(c)
i: bit-column
Ich kann keine guten Indizes für den Join finden:
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
Ich habe einen Covering-Index ausprobiert product (g, a, ...)
und er wird verwendet, aber nicht mit spektakulären Ergebnissen.
Einige Kombinationen von Indizes in der lookup
Tabelle erzeugen Ausführungspläne mit Indexzusammenführung mit einem leichten Effizienzgewinn gegenüber dem vorherigen Plan.
Gibt es eine offensichtliche Kombination, die mir fehlt?
Könnte eine Neugestaltung der Struktur helfen?
Das DBMS ist MySQL 5.5 und alle Tabellen verwenden InnoDB.
Tischgrößen:
product: 67K , g applied: 64K
main: 420K , f applied: 190K
lookup: 12M , b,i applied: 67K
mysql
mysql-5.5
optimization
ypercubeᵀᴹ
quelle
quelle
Antworten:
Das schmerzt mich ...
Ich musste vorher temporäre Tabellen mit InnoDB verwenden. Laden Sie sie mit Filtern, erstellen Sie einen Index und verbinden Sie diese temporäre Tabelle.
Ich denke, das Problem ist, wenn diese InnoDB nur über einen Nested Join-Algorithmus verfügt: Die erwachsenen RDBMS-Abfrageoptimierer haben mehr zu verwenden. Dies basiert auf dem Versuch, Ladevorgänge vom Typ Data Warehouse in InnoDB auszuführen.
Temp-Tabellen ziehen die Gesamtkomplexität auf die Ebene des MySQL-Abfrageoptimierers ...
quelle
main
) durch Denormalisierung von Daten zu entfernenlookup
?Es sieht aus wie ein kartesisches Produkt. Wiederholen Sie die JOIN-Kriterien
ALTERNATIVER VORSCHLAG
Dies mag unorthodox erscheinen und riecht wahrscheinlich nach SQL Anitpattern, aber hier geht es ...
Ich habe das
product.g = 1
und nichtmain.f = 1
in Unterabfragen verschoben, da es sich um Bitfelder handelt und nur an dieser Stelle ein Tabellenscan durchgeführt wird. Selbst wenn die Bitfelder Indizes wären, würde das Abfrageoptimierungsprogramm einen solchen Index einfach ignorieren.Natürlich können Sie zu wechseln
SELECT * FROM lookup
,SELECT a FROM lookup
wenn Ihr SELECT nichts von benötigtlookup
Nehmen Sie möglicherweise a, b in die Verbindung zwischen Lookup und Main auf, wenn dies sinnvoll ist
oder setzen Sie c zurück und verbinden Sie drei Spalten (Index der drei Spalten in
main
undlookup
)quelle
main.f
undproduct.g
??? Wenn die Kardinalität vonmain.f
undproduct.g
für den Wert 1 weniger als 5% der Tabellenzeilen beträgt, ist ein Index fürmain.f
undproduct.g
möglicherweise gerechtfertigt.main.f
undproduct.g
2 ist, können Sie diese Indizes fallen lassen.