2009-06-20 11 views
2

Ich habe einige Abfragen mit Ansichten, und diese laufen viel langsamer als ich erwarten würde, da alle relevanten Tabellen indiziert sind (und nicht so groß wie auch immer).Wie optimiert man MySQL Ansichten

Ich hoffe, dass ich das erklären kann:

Meine Haupt Abfrage sieht wie folgt aus (stark vereinfacht)

select [stuff] from orders as ord 
left join calc_order_status as ors on (ors.order_id = ord.id) 

calc_order_status eine Ansicht ist, definiert so:

create view calc_order_status as 
select ord.id AS order_id, 
(sum(itm.items * itm.item_price) + ord.delivery_cost) AS total_total 
from orders ord 
left join order_items itm on itm.order_id = ord.id 
group by ord.id 

Aufträge (ord) enthalten Bestellungen, order_items enthalten die einzelnen Artikel mit jeder Bestellung und ihre Preise zugeordnet.

Alle Tabellen korrekt indiziert sind, aber die Sache läuft langsam, und wenn ich ein erkläre ich

# id select_type table type possible_keys key key_len ref rows Extra 
    1 1 PRIMARY ord ALL customer_id NULL NULL NULL 1002 Using temporary; Using filesort 
    2 1 PRIMARY <derived2> ALL NULL NULL NULL NULL 1002 
    3 1 PRIMARY cus eq_ref PRIMARY PRIMARY 4 db135147_2.ord.customer_id 1 Using where 
    4 2 DERIVED ord ALL NULL NULL NULL NULL 1002 Using temporary; Using filesort 
    5 2 DERIVED itm ref order_id order_id 4 db135147_2.ord.id 2 

Meine Vermutung ist, bekommen „Derived2“ auf die Ansicht bezieht. Die einzelnen Items (itm) scheinen gut zu funktionieren, indiziert durch order_id. Das Problem scheint Zeile 4 zu sein, die anzeigt, dass das System keinen Schlüssel für die Auftragstabelle (ord) verwendet. Aber in der MAIN-Abfrage ist die Auftrags-ID bereits definiert: link Join calc_order_status als ors on (ors.order_id = ord.id) und ord.id (sowohl in der Hauptabfrage und in der Ansicht) beziehen sich auf die Primärschlüssel.

Ich habe irgendwo gelesen, dass MySQL vereinfacht Ansichten nicht so gut optimiert und Schlüssel möglicherweise unter bestimmten Bedingungen nicht verwendet, auch wenn verfügbar. Dies scheint einer dieser Fälle zu sein.

Ich würde mich über Vorschläge freuen. Gibt es eine Möglichkeit, MySQL zu zwingen, zu realisieren, "es ist alles einfacher als Sie denken, verwenden Sie einfach den Primärschlüssel, und alles wird gut"? Oder sind Ansichten der falsche Weg?

Antwort

4

Wenn es überhaupt möglich ist, sie diejenigen, schließt sich zu entfernen entfernen. Ersetzen Sie sie mit Subquerys wird es viel schneller.

Sie könnten auch versuchen, etwas wie diese zu laufen, um zu sehen, ob es irgendwelche Geschwindigkeitsdifferenz überhaupt hat.

select [stuff] from orders as ord 
left join (
    create view calc_order_status as 
    select ord.id AS order_id, 
    (sum(itm.items * itm.item_price) + ord.delivery_cost) AS total_total 
    from orders ord 
    left join order_items itm on itm.order_id = ord.id 
    group by ord.id 
) as ors on (ors.order_id = ord.id) 
+0

Ich glaube nicht, dass Sie die Anweisung "create view calc_order_status as" in Ihre Unterabfrage einfügen wollten. Ich nehme an, dass das ein Kopier-/Einfügefehler war. – Gruff

0

Ein Index ist nützlich, um ein paar Zeilen in einer großen Tabelle zu finden, aber wenn Sie jede Zeile abfragen, verlangsamt ein Index die Dinge nur. Daher erwartet MySQL wahrscheinlich, dass die gesamte Tabelle [order] verwendet wird, also sollte kein Index verwendet werden.

können Sie versuchen, wenn es durch forcing MySQL schneller sein würde, einen Index zu verwenden:

from orders as ord force index for join (yourindex) 
+1

Tut nicht den Trick ... – jms

+0

Nach dem Lesen der Frage, die Sinn macht. Schritt 4 verwendet eine temporäre Tabelle, und natürlich ist ein Index für [Aufträge] für eine temporäre Tabelle nicht gültig. Um den Index zu verwenden, müssen Sie die Abfrage so umgestalten, dass die Verknüpfung ausgeführt wird, bevor sie mit der Verwendung von temporären Tabellen beginnt. – Andomar

Verwandte Themen