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
Hai un indice per ordine per colonne? –
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
Hai eseguito l'analisi dopo aver creato gli indici? –