Article View: pl.comp.bazy-danych
Article #194318Re: PostgreSQL - jak zbudować optymalne zapytanie?
From: M.M.
Date: Fri, 13 Mar 2015 04:54
Date: Fri, 13 Mar 2015 04:54
191 lines
9435 bytes
9435 bytes
On Thursday, March 12, 2015 at 4:14:39 PM UTC+1, nk...@toya.net.pl wrote: > W dniu czwartek, 12 marca 2015 13:22:41 UTC+1 użytkownik M.M. napisał: > > On Thursday, March 12, 2015 at 8:48:10 AM UTC+1, nk...@toya.net.pl wrote: > > > W dniu poniedziałek, 9 marca 2015 12:23:28 UTC+1 użytkownik M.M. napisał: > > > > > > > > Sorki, ale nadal nie kumam. > > > > Testujesz najpierw: > > > > where x < 5; > > > > A potem: > > > > where x < 5 AND x < 6 OR x < 5; > > > > > > > > Wyszły Ci czasy t1 i t2. Załóżmy że t1<t2 to co wywnioskujesz? I na > > > > odwrót, że t1>t2. > > > > > > Po prostu sprawdzasz czy system poprzestaje na sprawdzeniu > > > pierwszego członu warunku i dalej już nie sprawdza np.: > > > > > > if (p1<>NULL and p2=p3) czas wykonania ~0,03 sek > > > if (p2=p3 and p1<>NULL) czas wykonania ~0,08 sek > > > > > > > > > to co to oznacza? > > Problem w tym, że to może oznaczać bardzo dużo. Zobacz jak > > dużo dzieje się w trakcie takiego głupiego zapytania. Najpierw > > połączenie z bazą po TCP-IP. Zobacz jak dużo dzieje się na > > tym poziomie: uprawnienia, firewalle, szyfrowanie, kompresja, > > korekcja błędów. Potem zapytanie dostaje się do bazy, i znowu: > > parsowanie, uprawnienia, silnik bazy danych musi sprawdzić czy > > chociaż są w bazie tabele o podanych nazwach. Potem pracuje > > kompilator i optymalizator zapytania. Optymalizator może > > czasami gromadzić statystyczne dane. Potem bufor systemu > > plików i bufor silnika bazy danych. Sorki, ale ja nadal nie > > umiem wyciągnąć żadnych wniosków z tego co przedstawiłeś. > > Pokazałeś że jeden czas jest krótszy od drugiego, intuicja > > podpowiada, aby wybrać ten krótszy - pomijam fakt że > > trzykrotna różnica w czasach, z powodu samej zmiany kolejności > > wyrażeń, już jest podejrzana. Potem do bazy dodaję > > jeden rekord, albo nawet tę samą bazę odtwarzam z kopii > > zapasowej i co może się stać? Czasy mogą się zupełnie zmienić, > > prawda? > > > > > > > Do testowania najlepiej używać najwolniejszego komputera > > > bo wtedy te czasy są bardzo widoczne, > > Nie zgodzę się, najlepiej użyć warunków najbardziej podobnych do > > tych, w jakich baza będzie pracowała. > > > > > no i testowane pola > > > nie powinny mieć indeksów (sprawdzasz tu tylko warunek). > > Ale dlaczego w ogóle taki test wykonywać, jeśli potem w > > realnym działaniu można indeks założyć? > > > > > > Pozdrawiam > > Dlatego od pewnego czasu dałem sobie spokój z czasami wykonywania > bo są tak krótkie, że taka walka trochę mija się z celem. > Te testy wykonywałem za czasów krasnala i wówczas było o co walczyć > bo mój wypasiony komp miał ok 600 MHz na procku. Ja może spokoju sobie nie dałem, ale nie liczę na odnalezienie jakiejś reguły. Często sprawdzam 2-3 wersje jakiegoś zapytania, ale zwykle jestem zdziwiony czasami zapytań. Kiedyś, gdy bardzo dużo optymalizowałem w języku C/C++, to wyrobiłem sobie intucję i z reguły odgadywałem, które rozwiązanie przyspieszy o 0.5%. Robiłem 20 poprawek w kodzie i zyskiwałem łączne przyspieszenie rzędu 10-30%. A w bazach danych to chyba zawsze jest loteria. Mam w przybliżeniu takie zapytanie: select tabela.pole1, tabela.pole2, podzapytanie1, podzapytanie2, podzapytanie3 from tabela where tabela.id > parametr order by tabela.id limit 1000. Dodam, że podzapytania są skomplikowane, np. mają kolejne podzapytania. Zapytaniem tym, zwiększając parametr w każdej iteracji, wyciągam z bazy po 1000 'rekordów'. Zapytanie działa rewlacyjnie około 20 razy. 20 zapytań, czyli wyciągnięcie 20tys rekordów, trwa może 20 sekund. Potem nagle zapytanie 21 trwa np. 120 sekund. I nie mam pojęcia co zrobić. W drugim rozwiązaniu dałem coś takiego: select tabela.pole1, tabela.pole2, podzapytanie1, podzapytanie2, podzapytanie3 from tabela where tabela.id in (id1,id2,...id1000) Działało wolniej niż pierwsze, ale nie było tego nagłego 120 sekundowego laga. Potem spróbowałem jeszcze jedną wersję: select tabela.pole1, tabela.pole2, podzapytanie1, podzapytanie2, podzapytanie3 from tabela where tabela.id <= max AND tabela.id > min To ostatnie działa najlepiej. Oczywiście to i powyższe zapytanie wymaga dodatkowego zapytania które wyciągnie z bazy ograniczenia na tabela.id. Ta ostatnia wersja wymaga mniej/więcej: select max(tabela.id), from ( select tabela.id, from tabela where tabela.id > prev_max order by tabela.id limit 1000. ); Czyli ta ostatnia wersja to nic innego, jak rozbicie jednego dużego zapytania na dwa małe. A jednak nie ma tego nagłego spowolnienia o 60 razy! Mnie ręce opadają, dlaczego baza sobie nie radzi? > Pytanie dotyczyło właśnie o kolejność członów w warunku WHERE > i tu moja podpowiedź - od nakrótszego do najwolniejszego oczywiście > jeśli system tak działa, że po nie spełnieniu pierwszego członu > dajmy na to "p1 IS NOT NULL" dalszych już nie sprawdza bo po co. > Kolega pisał, że aż 90% rekordów ma NULLe to chyba lepiej jak > już na wstępie system zrezygnuje ze sprawdzania dalszych członów. W sumie racja, jeśli pola w danym silniku są zorganizowane jako tabele kolumnowe, to nie musi dociągać pozostałych danych. Można obliczenia wykonywane w klauzuli where przyspieszyć ze 1.5 raza. A to w niektórych przypadkach może dać zysku z 10% na całym zapytaniu. Pytanie czy warto się bić o te 10%? > Tu testowanie nie dotyczy pracy sieci ale pracy systemu bazodanowego > na serwerze www. Im sprawniejszy system bazodanowy tym więcej zapytań > obsłuży. Każde zapytanie blokuje bazę na czas jego wykonania. Tak, ale zobacz. Operacje na danych trwają np. 0.1 sekundy. A nawiązanie polączenia, transfer, parsering zapytania, testy uprawnień, logowanie, budowanie statystyk przez optymalizator, trwa np. 1s. Czyli łączny czas to 1.1s. Przyspieszysz operację na danych o 10%, czyli całość trwa 1.09s. Więc przyspieszenie jakie w praktyce widzisz to 1%. Pytanie czy w ogóle warto się brać za próbę takiego przyspieszania? Druga sprawa, baza danych to nie jest asembler wykonywany na określonym CPU. W każdej chwili, np. po dodaniu nowej kolumny, albo wręcz po dodaniu nowego rekordu, optymalizator może zapytanie wykonać zupełnie inaczej. W wyniku tego, ciężko uzyskane przyspieszenie, nagle zamieni się w spowolnienie. Generalnie z Tobą się zgadzam, ale mam wątpliwości, czy w ogóle warto się brać za taki tuning? > Tu kolega Marek chciałby aby to user decydował o warunkach w WHERE > i jest pytanie czy sprawdzać programowo zapytanie na obecność > flodów czy nie ma takiej potrzeby bo parser i tak odrzuci powtórzenia. To wiedzą tylko osoby które znają silnik bazy od podszewki. Myślę, że optymalizator raz zachowa się tak, a drugi raz inaczej. A po wgraniu nowej wersji silnika, albo po użyciu dysku SSD, może wszystko ulec kolejnej zmianie. > Na indeksach warunki działają tak samo, indeksy przyspieszają > wyszukiwanie ale tak jak pisałem, czy teraz przy tak krótkich czasach > ma to sens. Moim zdaniem nie działają tak samo. Jeśli indeks pasuje do warunku, to warunek w ogóle nie jest sprawdzany. W wyniku przeszukiwania b-tree od razu dochodzimy do rekordów spełniających warunek. W przypadku indeksu w ogóle nie ma sensu testowanie kolejności - przynajmniej ja bym nie testował. Pozdrawiam
Technical Details
Message-ID:
<a1d9f705-3bd5-4e94-88b7-11dbb5b3b1f7@googlegroups.com>Path:
mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.icm.edu.pl!newsfeed.pionier.net.pl!newsfeed.fsmpi.rwth-aachen.de!newsfeed.straub-nv.de!proxad.net!feeder1-2.proxad.net!209.85.213.215.MISMATCH!hl2no7695940igb.0!news-out.google.com!db6ni50316igc.0!nntp.google.com!hl2no11044888igb.0!postnews.google.com!glegroupsg2000goo.googlegroups.com!not-for-mailReferences:
<mci51m$dju$1@news.icm.edu.pl> <fk06sb-jtf.ln1@depesz.com> <mctd2q$q6k$1@news.icm.edu.pl> <5bb452da-87e3-46b6-bbe4-51cd8e95fc73@googlegroups.com> <c57ea06e-2252-4f0c-ad4b-a2a2fed94ac4@googlegroups.com> <ef9d0ff9-dc2b-4ce1-845d-2f080e919ebd@googlegroups.com> <27b8c3e2-f0d5-4667-a74a-09a11cbeb915@googlegroups.com> <2330ae3c-1ffb-4e8a-8327-3a7cb9cebc0b@googlegroups.com> <6a2452a5-2772-4d96-af45-9858c4435913@googlegroups.com> <bd8c25b1-9d49-44a0-987f-4370401878a8@googlegroups.com>Show Full Headers
Complete Article Headers
X-Received: by 10.140.235.83 with SMTP id g80mr46532135qhc.5.1426222488375; Thu, 12 Mar 2015 21:54:48 -0700 (PDT) X-Received: by 10.140.34.168 with SMTP id l37mr739127qgl.20.1426222488328; Thu, 12 Mar 2015 21:54:48 -0700 (PDT) Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.icm.edu.pl!newsfeed.pionier.net.pl!newsfeed.fsmpi.rwth-aachen.de!newsfeed.straub-nv.de!proxad.net!feeder1-2.proxad.net!209.85.213.215.MISMATCH!hl2no7695940igb.0!news-out.google.com!db6ni50316igc.0!nntp.google.com!hl2no11044888igb.0!postnews.google.com!glegroupsg2000goo.googlegroups.com!not-for-mail Newsgroups: pl.comp.bazy-danych Date: Thu, 12 Mar 2015 21:54:47 -0700 (PDT) In-Reply-To: <bd8c25b1-9d49-44a0-987f-4370401878a8@googlegroups.com> Complaints-To: groups-abuse@google.com Injection-Info: glegroupsg2000goo.googlegroups.com; posting-host=178.36.122.220; posting-account=xjvq9QoAAAATMPC2X3btlHd_LkaJo_rj NNTP-Posting-Host: 178.36.122.220 References: <mci51m$dju$1@news.icm.edu.pl> <fk06sb-jtf.ln1@depesz.com> <mctd2q$q6k$1@news.icm.edu.pl> <5bb452da-87e3-46b6-bbe4-51cd8e95fc73@googlegroups.com> <c57ea06e-2252-4f0c-ad4b-a2a2fed94ac4@googlegroups.com> <ef9d0ff9-dc2b-4ce1-845d-2f080e919ebd@googlegroups.com> <27b8c3e2-f0d5-4667-a74a-09a11cbeb915@googlegroups.com> <2330ae3c-1ffb-4e8a-8327-3a7cb9cebc0b@googlegroups.com> <6a2452a5-2772-4d96-af45-9858c4435913@googlegroups.com> <bd8c25b1-9d49-44a0-987f-4370401878a8@googlegroups.com> User-Agent: G2/1.0 MIME-Version: 1.0 Message-ID: <a1d9f705-3bd5-4e94-88b7-11dbb5b3b1f7@googlegroups.com> Subject: Re: PostgreSQL - jak zbudować optymalne zapytanie? From: "M.M." <mmarszik@gmail.com> Injection-Date: Fri, 13 Mar 2015 04:54:48 +0000 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit