2012-11-07 9 views
5

Ho bisogno di alcuni suggerimenti per ottimizzare le query di recupero da tabelle di grandi dimensioni.Ottimizzazione della query PostgreSQL con più join, ordine per e limite inferiore

In questo esempio ho 5 tabelle:

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 

Ho bisogno di una query con elenco ordinato di azioni, limitate, quindi questo è l'approccio generale che ho usato:

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 

Questo funziona veloce su piccole tabelle, ma quando le tabelle crescono la query diventa molto costosa. Con 3,5 M di righe in Azioni, 300 K in Prod_attributes, 25K Prodotti vengono eseguiti su oltre 8800 ms, il che non è accettabile per me.

Tutte le chiavi di forgein hanno indici e DB è stato analizzato sotto vuoto recentemente.

So che il problema si trova nella parte ORDER BY, perché la query non utilizza gli indici e non esegue scansioni sequenziali. Se rimuovo l'ordine, la query è molto veloce.

Per risolvere questo, so che posso rimuovere ORDER BY, ma per me non è un'opzione praticabile. Anche la de-normalizzazione del DB o della vista materializzata potrebbe aiutare in questo caso, anche in questo caso vorrei evitarlo, se possibile.

Cos'altro posso fare per velocizzare questa query?

SPIEGARE ANALIZZARE:
- lento con ordine da: http://explain.depesz.com/s/AHO
- veloce senza ordine da: http://explain.depesz.com/s/NRxr

+0

Hai un indice per ordine per colonne? –

+0

Ciao, sì. Ho aggiunto gli indici per ordine in base alle colonne: CREATE INDEX i_p_name SU prodotti UTILIZZO btree (nome_p); Li ho aggiunti come indici separati - 1 per ogni ordine per campo. Ordine ASC e NULL LAST. Nulla è cambiato nel piano dopo aver rieseguito la query. – Lucius

+0

Hai eseguito l'analisi dopo aver creato gli indici? –

risposta

1

Un modo possibile per andare è quello di rimuovere stores dal punto di giunzione. Invece, si potrebbe:

  • Loop attraverso stores (ordine da s_name) in una stored procedure o nel codice sorgente e, per ogni punto vendita, eseguire il join il filtraggio stocks.fk_store. Potresti interrompere il ciclo ogni volta che ottieni un numero sufficiente di record.

  • Se possibile, partizione stocks utilizzando la chiave fk_store, al fine di ridurre notevolmente il numero di tuple nel join.

In questo modo si dovrebbe avere un buon vantaggio.

Problemi correlati