MySQL Explain Speed Problem
mixmastertobsi
- datenbank
0 Rolf B
Hallo,
ich habe folgende Abfrage und finde hier leider keine Lösung, die SQL ABfrage zu beschleunigen. Kurz - ich habe eine Produktsuche und diese gibt dann die Artikelnummern zurück. Über die Artikelnummern mache ich dann weitere SQL Abfragen und je nach Suche, kommen da schon einige Artikelnummern in den "IN" Operator zusammen.
Was mich wundert, ist das "Materialized" im Explain - was ist das?
Wie bekomme ich die Rows "1231" auf einen niedrigeren wert?
Gibt es ggf. eine schnellere Variante, um die Artikelnummern zu laden?
SELECT COUNT(distinct artikel.anr) as anzahl, artikel_attribut_value.value
FROM artikel
JOIN artikel_attribut ON artikel_attribut.anr=artikel.anr
JOIN artikel_attribut_name ON artikel_attribut_name.anr=artikel.anr AND artikel_attribut_name.attribut='größe'
JOIN artikel_attribut_value ON artikel_attribut_value.attribut=artikel_attribut_name.attributnr AND artikel_attribut_value.atrnr=artikel_attribut.atrnr
WHERE (artikel.available IS TRUE) AND (artikel.anr IN (100000762,100000772......))
GROUP BY artikel_attribut_value.value
HAVING COUNT(distinct artikel.anr)>3
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
---|---|---|---|---|---|---|---|---|---|
1 | PRIMARY | ALL | distinct_key | 1231 | Using temporary; Using filesort | ||||
1 | PRIMARY | artikel | eq_ref | PRIMARY | PRIMARY | 4 | tvc_0._col_1 | 1 | Using where |
1 | PRIMARY | artikel_attribut_name | ref | index_anr_value,index_attribut,index_anr_attribut,index_anr,index_attribut_anr | index_anr_value | 13 | tvc_0._col_1,const | 1 | Using index condition; Using where |
1 | PRIMARY | artikel_attribut | ref | PRIMARY,index_anr,index_anr_available_preis,index_anr_lieferzeit,index_anr_preis_available,index_anr_preis,index_atrnr | index_anr | 4 | slewo_live.artikel.anr | 4 | Using index |
1 | PRIMARY | artikel_attribut_value | ref | UNIQUE,index_atrnr_attribut,index_atrnr,index_atrnr_attribut_value | UNIQUE | 9 | slewo_live.artikel_attribut.atrnr,slewo_live.artikel_attribut_name.attributnr | 1 | Using index condition |
2 | MATERIALIZED | ALL | 1231 | ||||||
3 | DERIVED | No tables used |
(Edit: Tabellendaten als Tabelle formatiert)
Hallo mixmastertobsi,
mich hat kurz der Spaltenname attribut in der artikel_attribut_value verwirrt - da steht eine Attributnummer drin, ja? Warum hast Du die Spalte nicht attributnr benannt, so wie in artikel_attribut_name?
Hast Du da eine IN Klausel mit 1231 Artikelnummern??? Und sehe ich es richtig, dass nur eine einzige davon in der Artikeltabelle vorhanden AND available ist? Anders kann ich mir in den Zeilen 2 und 3 den Wert für rows nicht erklären.
Was ich an deinem Datenmodell nicht ganz verstehe, ist die Aufteilung in artikel_attribut_name und artikel_attribut_value. Entweder hat man eine feste Liste von Attributnamen, die für alle Artikel gelten. Dann braucht die attribut_name Tabelle keinen Artikelbezug. Oder man hat eine variable Liste von Attributen für jeden Artikel, dann sollte man pro Artikel eine Name-Value Liste in einer einzigen Tabelle führen. Die Trennung in Name und Value hat auf den ersten Blick keinen Vorteil, kostet Dich hier aber ordentlich Join-Aufwand.
Was es mit Materialisierung auf sich hat, steht hier, ich verstehe allerdings auch nicht recht, was er hier materialisiert.
Die Zeilen mit type="ref" könnten Optimierungspotenzial bergen. Du hast auf der artikel_attribut_name Tabelle fünf Indexe liegen, wie es scheint, aber er schafft damit keinen eq_ref Zugriff. Hast Du einen Plan, welche Indexe für welche Query nützlich sind? Hast Du einen Index, der die Spalten anr und attribut als die beiden ersten Spalten enthält? Es hat nämlich oft nur wenig Sinn, wenn man Spalten einzeln indiziert. MYSQL nutzt immer nur einen Index für einen Zugriffsschritt, es kombiniert keine Indexe.
Angesichts der Row-Zahlen verstehe ich aber nicht, warum der Zugriff langsam ist. Wie lange braucht er? Kannst Du die Query mal teilweise ausführen (z.B. nur artikel mit available-Abfrage und IN-Klausel, ohne die Joins)?
Rolf