COUNT mit JOINs und sub-queries kriechend langsam
Moin zusammen,
ich habe mit 6 Tabellen eine Artikeldatenbank unter MYSQL / MyISAM zusammengebastelt. Darin sind gegenwärtig je 60'000 Positionen gespeichert - ausser bei der Tabelle 'labels', die für jeden Artikel eine Beschreibung in drei Sprachen enthält, also rund 180'000 Einträge. Die Tabellen haben zusammen ein Gewicht von ca. 30MB. Die grundsätzlich erzeugte Liste (d.h. ohne Filtereinstellungen) zeigt jeweils 30 Sätze pro Seite an, und um weitere Seiten anwählen zu können, benötige ich einen COUNT, um die Anzahl der Folgeseiten auszurechnen, bzw. die Anzahl der gefundenen Datensätze anzuzeigen. Der COUNT sieht folgendermassen aus: Code:
SELECT COUNT Code:
mysql_result($num, 0, 0) Diese Abfrage dauert auf einem Dual Core 1,6 MHz MS Vista Laptop rund 10 Sekunden. Durch entfernen der Subqueries werden daraus 5 Sekunden - aber leider brauche ich diese Routinen ja... Dieselbe Abfrage als SELECT und LIMIT 0,30 dauert 0,0675 Sekunden. Natürlich habe ich alle relevanten Spalten ordnungsgemäss indiziert (glaub' ich wenigstens). COUNT(*) und mysql_num_rows habe ich mit leicht schlechteren Ergebnissen ausprobiert. Ich halte die paar Einträge eigentlich nicht für so viel, wenn man berücksichtigt, dass MySQL mit Millionen von Einträgen prima umgehen kann. Aber vielleicht zwinge ich MySQL mit der o.g. Abfrage tatsächlich in die Knie? Entsprechen die von mir gemachten Angaben tatsächlich der Realität oder gibt es gegenteilige Meinungen, bzw. Vorschläge, wie ich es besser machen kann? Im letzteren Fall würde ich gerne die Tabellenstrukturen, Indizies, EXPLAIN-Auswertungen etc. posten. Vielen Dank für Euer Feedback und bis denne David |
AW: COUNT mit JOINs und sub-queries kriechend langsam
Um bei Performancefragen richtig helfen zu können, bedarf es folgender Informationen (für alle beteiligten Tabellen):
* SHOW CREATE TABLE tbl; -- liefert engine, indexes * SHOW TABLE STATUS LIKE 'tbl'; -- liefert die Tabellengrößen * EXPLAIN SELECT ...; -- EXPLAIN Ausgabe für den Zugriffpfad * SHOW VARIABLES LIKE '%buffer%'; -- wichtige MySQL Server Einstellungen Beispiel EXPLAIN.. Code:
mysql> EXPLAIN SELECT * FROM kunde; Grüße Thomas |
AW: COUNT mit JOINs und sub-queries kriechend langsam
Moin Thomas,
Danke fürs Antworten. anbei die letzteren drei; falls die Tabellenstrukturen notwendig werden, schiebe ich sie nach, denn die brauchen ein bisschen mehr Platz ;-) Code:
SHOW TABLE STATUS LIKE 'tbl' Code:
EXPLAIN SELECT... Code:
SHOW VARIABLES LIKE '%buffer%' David |
AW: COUNT mit JOINs und sub-queries kriechend langsam
...und hier endlich die Tabellenstrukturen.
Code:
SHOW CREATE TABLE tbl |
AW: COUNT mit JOINs und sub-queries kriechend langsam
Zitat:
Wie in dem EXPLAIN zu sehen ist, findet MySQL keinen passenden Index bei der Tabelle p12 (suppliers). In Betracht kommen zwar die Index "deleted,artikleid", aber verwendet wird keiner (siehe Spalte "key") Zur Lösung: Ich empfehle mal einen Index zu entfernen und einen neuen zusammengesetzen Index einzubauen. Bitte anschließend nochmal den EXPLAIN ausführen und die aktuelle CREATE TABLE der Tabelle suppliers zeigen. Code:
ALTER TABLE suppliers Thomas |
AW: COUNT mit JOINs und sub-queries kriechend langsam
Danke für die Blumen... Du hast ja auch 'ne prima Vorlage gemacht. Allerdings ist der Dump aus dem mysql command tool ein bisschen mühsam. Was benutzt Du für ein Tool?
Performance ist leider kaum besser. Anbei die Auswertungen: Code:
EXPLAIN SELECT COUNT(t1.id)... Code:
SHOW CREATE TABLE suppliers Grüsse David |
AW: COUNT mit JOINs und sub-queries kriechend langsam
Zitat:
Als Tool verwende ich "Notepad" und MySQL-Console ;-) Die tinyINT sind das Feintuning. Soweit ich weiß, belegt ein TinyINT(1) und TinyINT(4) gleich viel Platz in der Datenbank. Es ist nur eine Anzeigeformatierung. So nun zum zweiten Änderungvorschlag: Code:
ALTER TABLE articles Und nun wieder der bekannte EXPLAIN und abschließend der aktuelle CREATE TABLE von articels. Grüße Thomas |
AW: COUNT mit JOINs und sub-queries kriechend langsam
Zitat:
Grüße Thomas |
AW: COUNT mit JOINs und sub-queries kriechend langsam
Tolle Programme. Wo kann ich die kaufen...?
Der neue Index ist drinne aber ich denke die EXPLAIN Auswertung gibt sich ein wenig ignorant: Code:
EXPLAIN SELECT COUNT(t1.id)... Code:
SHOW CREATE TABLE articles Aber: durch die Anpassung der Buffer hat sich der COUNT von 9,8 auf 9.3 Sekunden verbessert. Tataa! ;-) Aber um die Server-Einstellungen mache ich mir eh keine Sorgen, da früher oder später das Script beim Profi gehostet wird. Ich glaube, ich komme langsam hinter die Logik Deiner Vorschläge: Die 'deleted' Spalte wurde mit der entsprechenden 'id' zusammen indiziert und damit muss MySQL nur einmal den Aspekt t1.id / t1.deleted prüfen? Im Moment sind dort keine 'deleted' geflagt; ergab sich deshalb keine Verbesserung? Die 'deleted' Spalte in allen Tabellen führt im Moment kein Flag. Kann das Problem eventunnel damit zusammenhängen? Grüsse David |
AW: COUNT mit JOINs und sub-queries kriechend langsam
Hallo David,
Wenn MySQL die Spalten ID + DELETED zusammen im Index findet, ist dies schneller, da sich MySQL den Zugriff auf die tatsächliche Basistabelle erspart. I/O werden weniger. Wenn DELETED wenig ausprägungen hat ( nur 0 oder 1), dann ist ein eigener Index auf diese Spalte nahezu wertlos, da die Selektivität/Kardinalität denkbar schlecht ist. Mal abgesehen vom Using index; zugriff, wie ich ihn durch die kombinierten Indices versuche. Zwischendurch ein paar Kleinigkeiten zur SQL-Abfrage Was für Werte soll oder kann den DELETED in Zukunft annehmen. Nur 0 ( = FALSE) oder 1 (= TRUE) ? Dann ist es sinnvoll das Prädikat immer auf = abzufragen, also t1.deleted = 0 a) Bitte mal alle xx.deleted != '1' Prädikate umschreiben auf xx.deleted = t1.deleted alt: Code:
ON Code:
ON alt: Code:
WHERE Code:
WHERE So, nun bitte wieder den EXPLAIN ausführen und den kompletten neuen SQL zeigen (Damit wird immer vom Selben reden). Grüße Thomas |
Alle Zeitangaben in WEZ +2. Es ist jetzt 11:25:54 Uhr. |
Powered by vBulletin® Version 3.8.3 (Deutsch)
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.