Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Widoki - problem w wydajnościa
Forum PHP.pl > Forum > Bazy danych > PostgreSQL
kr27
Witam. Mam następujący problem:

Mam widok powiedzmy "A". Widok ten składa dane z trzech różnych tabel.
Robie następujące zapytania na widoku:

Select A.* FROM A WHERE pole1=1 AND pole2=2 AND pole3=3

Select A.* FROM A INNER JOIN TABELA ON A.klucz=TABELA.klucz WHERE TABELA.pole1=1 AND TABELA.pole2=2 AND TABELA.pole3=3


Pierwsze zapytanie wlecze się strasznie (nawet 30 sek) i obciąża procesor 100% - są założone indeksy na polach w warunkach - rekordów jest parę tysięcy.

Drugie zapytanie zwraca wynik momentalnie - a różnica tylko taka, że łączę ponownie JOINEM jedną tabelę zawartą w tym widoku i zakładam warunki bezpośrednio na tabeli (a nie na widoku, który zwraca pola z tej tabeli).

Czy możecie mnie oświecić dlaczego tak dziwnie się to zachowuje?
Pozdrawiam
prond
Wyślij jak możesz explain plan, to będę Ci mógł powiedzieć, w czym problem.

Teraz mogę Ci jedynie powiedzieć, że generalnie duże zużycie zasobów (w Twoim przypadku obciążenie procesora nawet w 100%) jest przy złączeniach typu 'hash'.

Można pobawić się podpowiedziami do optymalizatora, np.:
  1. SET enable_nestloop = ON/off;
kr27
ZAPYTANIE 1: Działa bardzo szybko:

SELECT b_faktury_v_10_n.* FROM b_faktury_v_10_n INNER JOIN b_faktury ON b_faktury_v_10_n.kod_faktury=b_faktury.kod_faktury WHERE b_faktury.podmiot=2 AND b_faktury.status_dokumentu = 1 ORDER BY pozycja DESC

Sort (cost=734.54..734.55 rows=1 width=633)
Sort Key: public.b_faktury.pozycja
-> Hash Join (cost=243.48..734.53 rows=1 width=633)
Hash Cond: (("outer".kod_faktury)::text = ("inner".kod_faktury)::text)
-> Hash Left Join (cost=181.80..656.88 rows=3192 width=633)
Hash Cond: (("outer".kod_faktury)::text = ("inner".kod_faktury)::text)
-> Hash Left Join (cost=145.52..451.02 rows=3192 width=601)
Hash Cond: (("outer".kod_faktury)::text = ("inner".kod_faktury)::text)
-> Seq Scan on b_faktury (cost=0.00..135.92 rows=3192 width=505)
-> Hash (cost=145.02..145.02 rows=200 width=164)
-> Subquery Scan k (cost=141.52..145.02 rows=200 width=164)
-> HashAggregate (cost=141.52..143.02 rows=200 width=107)
-> Seq Scan on b_pozycje (cost=0.00..102.76 rows=3876 width=107)
-> Hash (cost=35.77..35.77 rows=200 width=100)
-> Subquery Scan p (cost=33.27..35.77 rows=200 width=100)
-> HashAggregate (cost=33.27..33.77 rows=200 width=81)
-> Seq Scan on b_platnosci (cost=0.00..28.85 rows=885 width=81)
-> Hash (cost=61.68..61.68 rows=1 width=68)
-> Index Scan using b_fakturyi6 on b_faktury (cost=0.00..61.68 rows=1 width=68)
Index Cond: (status_dokumentu = 1)
Filter: (podmiot = 2)



ZAPYTANIE 2: 100% procesora i 15 sekund:

SELECT * FROM b_faktury_v_10 WHERE b_faktury_v_10.podmiot=2 ORDER BY pozycja DESC

Sort (cost=247.49..247.50 rows=1 width=633)
Sort Key: b_faktury.pozycja
-> Nested Loop Left Join (cost=174.80..247.48 rows=1 width=633)
Join Filter: (("outer".kod_faktury)::text = ("inner".kod_faktury)::text)
-> Nested Loop Left Join (cost=141.52..209.20 rows=1 width=601)
Join Filter: (("outer".kod_faktury)::text = ("inner".kod_faktury)::text)
-> Index Scan using b_fakturyi6 on b_faktury (cost=0.00..61.68 rows=1 width=505)
Index Cond: (status_dokumentu = 1)
Filter: (podmiot = 2)
-> Subquery Scan k (cost=141.52..145.02 rows=200 width=164)
-> HashAggregate (cost=141.52..143.02 rows=200 width=107)
-> Seq Scan on b_pozycje (cost=0.00..102.76 rows=3876 width=107)
-> Subquery Scan p (cost=33.27..35.77 rows=200 width=100)
-> HashAggregate (cost=33.27..33.77 rows=200 width=81)
-> Seq Scan on b_platnosci (cost=0.00..28.85 rows=885 width=81)


I teraz tak:
Widok [b_faktury_v_10_n] zawiera w sobie złączenia 3 tabel w tym [b_faktury]. Widok ten nie zawiera w sobie żadnych warunków WHERE. Wszystkie warunki "wyciągniete są na zewnątrz" i zakładane na [b_faktury].

Widok [b_faktury_v_10] zawiera w sobie złączenia 3 tabel w tym [b_faktury]. Widok ten zawiera w sobie warunek na "status_dokumentu = 1".

Dziękuje bardzo. Pozdrawiam
prond
Pierwsze zapytanie używa złączeń typu HASH, drugie NESTED LOOPS.

W zdecydowanej większości przypadków HASH jest dużo szybszy dlatego spróbuj przed wykonaniem zapytania (tego 'wolnego') zmienić ustawienia optymalizatora zapytań :

  1. SET enable_nestloop = off;


To powinno zmusić SZBD do korzystania ze złączeń typu HASH.
kr27
Dziękuje bardzo. Pomogło:) Śmiga tak samo szybko jak to pierwsze.
Jeszcze raz wielkie dzięki.

Pozdrawiam
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.