2012-11-07 12 views
5

Ich brauche einige Tipps zum Optimieren von Abfragen aus großen Tabellen.Optimieren der PostgreSQL-Abfrage mit mehreren Joins, Order by und Small Limit

In diesem Beispiel habe ich 5 Tische:

Brands 
- id_brand 
- b_name 

Products 
- id_product 
- p_name 
- ean 
... 
- fk_brand 

Prod_attributes 
- id_prod_att 
- size_basic 
... 
- fk_product 

Stores 
- id_store 
- s_name 
... 

Stocks 
- id_stock 
- stock_amount 
- fk_prod_att 
- fk_store 

ich eine Abfrage mit geordneten Liste von Aktien muß, begrenzt, so ist dies der allgemeine Ansatz, den ich verwenden:

SELECT stores.s_name, stocks.stock_amount, prod_attributes.size_basic, 
products.p_name, products.ean, brands.b_name 

FROM (stocks 
    INNER JOIN stores 
    ON stocks.fk_store = stores.id_store) 
    INNER JOIN (prod_attributes 
     INNER JOIN (products 
      INNER JOIN brands 
      ON products.fk_brand = brands.id_brand) 
     ON prod_attributes.fk_product = products.id_product) 
    ON stocks.fk_prod_att = prod_attributes.id_prod_att 

ORDER BY s_name, p_name, size_basic 

LIMIT 25 OFFSET 0 

Das funktioniert schnell auf kleinen Tabellen, aber wenn die Tabellen wachsen, wird die Abfrage sehr teuer. Mit 3,5M Zeilen in Stocks, 300K in Prod_attributes, 25K Produkten wird es in über 8800ms ausgeführt, was für mich nicht akzeptabel ist.

Alle herkömmlichen Schlüssel haben Indizes und DB wurde kürzlich vakuumanalysiert.

Ich weiß, dass das Problem im ORDER BY-Teil liegt, deshalb verwendet die Abfrage keine Indizes und führt sequenzielle Scans durch. Wenn ich die Reihenfolge lösche, ist die Abfrage sehr schnell.

Für die Lösung dieses Problems weiß ich, dass ich ORDER BY entfernen kann, aber es ist keine machbare Option für mich. Eine De-Normalisierung der DB oder Materialized View könnte hier ebenfalls hilfreich sein - auch dies möchte ich nach Möglichkeit vermeiden.

Was kann ich noch tun, um diese Anfrage zu beschleunigen?

ANALYZE ERKLÄREN:
- langsam mit Auftrag von: http://explain.depesz.com/s/AHO
- schnell ohne Auftrag von: http://explain.depesz.com/s/NRxr

+0

Haben Sie einen Index für die Reihenfolge nach Spalten? –

+0

Hallo, ja. Ich habe die Indizes für die Reihenfolge nach Spalten als solche hinzugefügt: CREATE INDEX i_p_name ON Produkte VERWENDUNG btree (p_name); Ich fügte sie als separate Indizes - 1 für jede Reihenfolge von Feld. ASC-Reihenfolge und NULLEN LETZT. Nach der erneuten Ausführung der Abfrage hat sich nichts im Plan geändert. – Lucius

+0

Haben Sie nach dem Erstellen von Indizes eine Analyse ausgeführt? –

Antwort

1

Ein möglicher Weg zu gehen, ist stores aus dem Join zu entfernen. Stattdessen könnten Sie:

  • Schleife durch stores (Reihenfolge von s_name) in einer Stored Procedure oder im Quellcode und für jedes Geschäft, führen Sie die Filterung auf stocks.fk_store verbinden. Sie können die Schleife unterbrechen, wenn Sie eine ausreichende Anzahl von Datensätzen erhalten.

  • Wenn möglich, Partition stocks mit fk_store Schlüssel, um die Anzahl der Tupel in der Join stark zu reduzieren.

Auf diese Weise sollten Sie einen guten Nutzen haben.