2013-12-09 11 views
5

ich nicht brillant bin, wenn es darum geht, über die Grundlagen mit MySQL zu gehen, aber ich versuche, eine Abfrage zu optimieren:Indizes und Optimierung

SELECT DATE_FORMAT(t.completed, '%H') AS hour, t.orderId, t.completed as stamp, 
     t.deadline as deadline, t.completedBy as user, p.largeFormat as largeFormat 
    FROM tasks t 
    JOIN orders o ON o.id=t.orderId 
    JOIN products p ON p.id=o.productId 
    WHERE DATE(t.completed) = '2013-09-11' 
    AND t.type = 7 
    AND t.completedBy IN ('user1', 'user2') 
    AND t.suspended = '0' 
    AND o.shanleys = 0 
    LIMIT 0,100 

+----+-------------+-------+--------+----------------------------+-----------+---------+-----------------+-------+-------------+ 
| id | select_type | table | type | possible_keys    | key  | key_len | ref    | rows | Extra  | 
+----+-------------+-------+--------+----------------------------+-----------+---------+-----------------+-------+-------------+ 
| 1 | SIMPLE  | o  | ref | PRIMARY,productId,shanleys | shanleys | 2  | const   | 54464 | Using where | 
| 1 | SIMPLE  | p  | eq_ref | PRIMARY     | PRIMARY | 4  | sfp.o.productId |  1 |    | 
| 1 | SIMPLE  | t  | ref | NewIndex1     | NewIndex1 | 5  | sfp.o.id  |  6 | Using where | 
+----+-------------+-------+--------+----------------------------+-----------+---------+-----------------+-------+-------------+ 

Bevor einige der Indizes hinzugefügt wurden, wurde die Durchführung Vollständige Tabelle scannt sowohl in der Tabelle als auch in der Tabelle o.

Im Grunde, dachte ich, dass MySQL würde:

Grenze nach unten die Zeilen aus der Aufgaben-Tabelle mit den where-Klauseln (sollte 84 Zeilen sein, ohne dass die Verbindungen)

dann auf die Produkte der Auftragstabelle durch Tabelle, um eine Flagge zu erhalten (largeFormat).

Meine Fragen sind, warum MySQL 50000+ Zeilen nachschlägt, wenn es nur 84 verschiedene IDs zu suchen gibt, und gibt es eine Möglichkeit, die Abfrage zu optimieren?

Ich kann keine neuen Felder oder neue Tabellen hinzufügen.

Vielen Dank im Voraus!

+0

Das sieht ziemlich gut aus. Ist Leistung ein Problem? – Strawberry

+0

Ich habe @ DRapps Antwort unten verwendet, im Wesentlichen die Verwendung der Datumsfunktion führte dazu, dass das Nachschlagen 7,98 Sekunden dauerte und jetzt 0,04 Sekunden dauert. : p –

Antwort

5

SQL muss auf verfügbaren Indizes funktionieren am besten, um die Abfrage zu qualifizieren

ich auf (Typ, suspendiert, completedby, abgeschlossen) entsprechen den Kriterien haben Sie ... Ihre Aufträge eine Verbindung Index haben würde und Produkttabellen erscheinen mit ihren vorhandenen Indizes in Ordnung.

SELECT 
     DATE_FORMAT(t.completed, '%H') AS hour, 
     t.orderId, 
     t.completed as stamp, 
     t.deadline, 
     t.completedBy as user, 
     p.largeFormat as largeFormat 
    FROM 
     tasks t 
     JOIN orders o 
      ON t.orderId = o.id 
      AND o.shanleys = 0 
      JOIN products p 
       ON o.productId = p.id 
    WHERE 
      t.type = 7 
     AND t.suspended = 0 
     AND t.completedBy IN ('user1', 'user2') 
     AND t.completed >= '2013-09-11' 
     AND t.completed < '2013-09-12' 
    LIMIT 
     0,100 

ich, dass suspendierte den Verdacht ist ein Flag und ist numerisch (int) basiert, wenn ja, lassen Sie die Kriterien als numerisches und nicht String in Anführungszeichen in ‚0‘ gewickelt wird.

für Datetime-Felder, wenn Sie versuchen, Funktionen darauf anzuwenden, es kann nicht den Index nutzen gut ... so, wenn Sie nur über den einen Tag (oder einen Bereich in anderen Abfragen) kümmern, Mitteilung Ich habe die datetime field> = '2013-09-11' was impliziert ist von 12:00:00 Uhr, UND das datetime Feld ist WENIGER ALS '2013-09-12' das erlaubt bis zu 11:59:59 PM auf der 2013- 09-11 das ist der ganze Tag UND der Index kann davon profitieren.

+1

Wow! Das ist eine massive Leistungsverbesserung von 7,98 Sekunden auf 0,04 Sekunden. Vielen Dank und vielen Dank für die Erklärung! –

+2

@RossWilson, Sie sind willkommen, und ich versuche regelmäßig, WARUM hinter meinen Antworten zu helfen, anderen zu helfen, WARUM zu lernen, und kann solche Argumentation in ihren zukünftigen Fragen anwenden, die auftreten können. Sie können sich die Fragen von irgendjemandem ansehen, indem Sie darauf klicken und ihre Tags durchsuchen (wie [mysql]) oder was auch immer ... vielleicht helfen Ihnen bereits andere Antworten, bevor Sie Fragen stellen müssen - nicht, dass Fragen immer ein sind schlechte Sache. – DRapp

+1

+1 DRapp .. @RossWilson, Wenn Bereiche beteiligt sind, sollten Sie immer zuerst die Gleichheiten indizieren, dies erlaubt MySQL, mehr Teile aus dem Index zu verwenden (was den Index selektiver auscheckt key_len in der Erklärung mit dieser Abfrage könnte dies sein) größere Zahl jetzt). Ein Bereichsscan mit> = kann nur die linke Präfixspalte verwenden, um nicht übereinstimmende Datensätze herauszufiltern. –