2016-11-19 8 views
0

Ich habe ein Problem mit der folgenden Abfrage. Es wählt Protokolldatensätze aus einer Datenbanktabelle aus.Sehr langsame MySQL-Abfrage (20 bis 60 Sekunden!) - warum?

SELECT paymentslog.*, user.username, user.usergroupid, user.displaygroupid, 
     purchase_temp.threadid 
    FROM " . TABLE_PREFIX . "paymentslog AS paymentslog 
    LEFT JOIN " . TABLE_PREFIX . "user AS user 
     ON (paymentslog.userid = user.userid) 
    LEFT JOIN " . TABLE_PREFIX . "paymenttransaction AS paymenttransaction 
     ON (paymentslog.transactionid = paymenttransaction.transactionid) 
    LEFT JOIN " . TABLE_PREFIX . "paymentinfo AS paymentinfo 
     ON (paymenttransaction.paymentinfoid = paymentinfo.paymentinfoid) 
    LEFT JOIN " . TABLE_PREFIX . "purchase_temp AS purchase_temp 
     ON (paymentinfo.hash = purchase_temp.hash) $filterlogs_where 
    GROUP BY paymentslog.logid 
    ORDER BY paymentslog.dateline DESC 
    LIMIT $startat, $perpage 
  • alle Joins benötigt threadid mit Ausnahme der mit Benutzertabelle verbinden auf SELECT für den Zugriff auf Benutzernamen für den Zugriff auf usergroupid und displaygroupid
  • es wurde 20 Sekunden benötigt, um zu laufen (!), Und während meiner try um es zu beheben, nach dem Hinzufügen von INDEX für Spalte transactionid (der Tabelle Paymentslog), jetzt braucht es ... 60 Sekunden!
  • aus irgendeinem Grund war es eine bestimmte Zeile mehrere Male zurückkehren, und aus diesem Grund Ich reparierte sie durch eine „GROUP BY paymentslog.logid“

ich feststellen, dass muss hinzufügen:
- $ filterlogs_where PHP-Variable hat das WHERE der Abfrage (ich baue über PHP verschiedene Filter für das Paymentslog). $ filterlogs_where hat standardmäßig einen Wert von "1 = 1", und wenn ich einen Filter anwenden muss, füge ich ein. = "AND paymentslog.userid = X" usw.

Jede Idee, warum diese Abfrage ist so langsam?
Ich glaube, ich habe kompliziertere Abfragen gesehen und geschrieben, die in ein paar Sekunden oder Millisekunden ablaufen. Warum dieses Problem mit der obigen Abfrage?

+0

Während Beitritt auf Hash ist möglich, nur auf Integers Beitritt sollte viel schneller sein. Über wie viele Daten sprechen wir, Sie haben es versäumt, uns das zu sagen. – Xorifelse

+5

Joining auf Ganzzahlen kann teilweise schneller sein, aber das ist alles. Es ist unmöglich, mit diesem Problem ohne CREATE TABLE-Anweisungen für alle relevanten Tabellen und ein EXPLAIN für die obige Abfrage zu helfen. – Strawberry

+0

@Xorifelse - Es gibt keinen 'HASH'-Index. Wie auch immer, Hash ist nur geringfügig schneller als BTree. –

Antwort

0

Zuerst muss ich Sie ermahnen, nicht mehrere Tabellen mit dem gleichen Schema zu haben. Das ist normalerweise ein schlechtes Design.

Benötigen Sie wirklich LEFT? Das heißt, Sie möchten eine Zeile zurückgegeben, auch wenn die 'richtige' Tabelle nichts hat? Wenn nicht, einfach JOIN verwenden.

Loswerden der LEFTs kann die GROUP BY loswerden. Joins gefolgt von GROUP BY verursachen normalerweise "die Anzahl der Zeilen aufzublasen", gefolgt von "deflate via group by". Dies erzeugt eine riesige temporäre Tabelle in dem Prozess und verlangsamt dadurch die Dinge.

Dann muss ich darauf hinweisen, dass Pagination via Offset ist problematisch - oft zu langen Abfragezeiten führen. Allerdings müssen wir die GROUP BY loswerden, um diese Technik möglich zu machen.

Bitte verwenden Sie kürzere Aliase.

Nun, zurück zu Ihren Besonderheiten ... Nun, zuerst an dem Zeug oben arbeiten. Und liefern SHOW CREATE TABLE. Dann wird etwas wie dies Dinge beschleunigen:

SELECT ... 
    FROM (SELECT id 
       ORDER BY dateline DESC 
       LIMIT $startat, $perpage) AS pl 
    JOIN user ON ... 
    JOIN ... 
    ORDER BY dateline DESC; -- yes, needs repeating 
+0

Hallo Ricky und vielen Dank für die analytische Antwort! Wie ich mit Ihrem Beispiel verstehen konnte, schrieb ich die folgende Abfrage: http://pastebin.com/GQAWe9AZ Ist das korrekt? Es scheint, korrekte Ergebnisse mit vielen Datensätzen zurückzugeben, aber mit einem Test mit 2 Datensätzen erscheint niemand. Sorry für die langen Aliase, wird sie bald beheben. – user3594130

+0

Vielleicht brauchen Sie 'LINKS'. (Ich verstehe nicht die _intent_ der Abfrage.) –

+0

ok fertig! Die Abfrage funktioniert einwandfrei, vielen Dank :) – user3594130

Verwandte Themen