Potrzebuję wskazówek, jak optymalizować zapytania pobierane z dużych tabel.Optymalizowanie zapytania PostgreSQL z wieloma złączeniami, kolejność i mały limit
W tym przykładzie Mam 5 tabel:
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
muszę zapytać o uporządkowanej listy zasobów, ograniczone, więc jest to ogólne podejście użyłem:
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
To działa szybko na małych stołach, ale gdy tabele rosną, zapytanie staje się bardzo kosztowne. Z 3,5 mln rzędów w magazynie, 300 tys. W prod_attributes, 25K produktów, które wykonuje w ponad 8800ms, co jest dla mnie nie do przyjęcia.
Wszystkie klucze forgein mają indeksy, a baza danych została ostatnio zanalizowana pod kątem próżni.
Wiem, że problem leży w części ORDER BY, ponieważ zapytanie nie korzysta z indeksów i wykonuje sekwencyjne skanowanie. Jeśli usuniemy zamówienie, zapytanie jest bardzo szybkie.
W celu rozwiązania tego problemu wiem, że mogę usunąć ZAMÓWIENIE, ale nie jest to dla mnie możliwe. Oddolna normalizacja DB lub zmaterializowanego widoku mogłaby tu również pomóc - znowu chciałbym tego uniknąć, jeśli to możliwe.
Co jeszcze mogę zrobić, aby przyspieszyć to zapytanie?
EXPLAIN ANALYSE:
- slow o zamówienie przez: http://explain.depesz.com/s/AHO
- szybko, bez zlecenia przez: http://explain.depesz.com/s/NRxr
Czy masz indeks na zamówienie według kolumn? –
Cześć, tak. Dodałem indeksy do zamówienia według kolumn jako takich: CREATE INDEX i_p_name ON products USING btree (p_name); Dodałem je jako oddzielne indeksy - 1 dla każdego zamówienia według pola. Porządek ASC i NULL OSTATNIE. Nic się nie zmieniło w planie po ponownym uruchomieniu zapytania. – Lucius
Czy uruchomiłeś analizę po utworzeniu indeksów? –