Grzegorz G.

Grzegorz G. ASE / Systems
Architect, Syniverse

Temat: Jaki był najdłuższy ciąg...

Mieczyslaw B.:
A co zrobisz kiedy będziesz miał co kilkanaście/dziesiąt sekund
niewielką liczbę 500 requestów (dla Oracle niech będzie 5000) w
tym samym czasie, a zapytanie, które rzeczywiście dało się
zrobić w SQL będzie rzeźbiło po bazie 10 sekund?

Hmmm...Uruchomię je?
Mieczyslaw B.:
Zarżniesz bazę, kupisz super serwer, będziesz klastrować, czy
ściągniesz dane na zewnątrz i przetworzysz je kilkoma prostymi
pętlami lub w inny sposób? A jak komar lata, to z RPG się
strzela?:)

Poczekam na wynik. Zapytanie wymagające 10 sekund to nie jest jakiś killer, nie czarujmy się. To nie jest full scan bez partition pruning na tabeli faktów z kilkoma miliardami wierszy ;-) Skoro doskonale sobie baza radziła z 5000 transakcji to i z 5001 spodziewałbym się, że poradzi sobie równie dobrze.

Bez urazy, ale zdanie o ,,ściągnięciu danych na bok i przetworzeniu kilkoma prostymi pętlami'' dla mnie świadczy o tym, że na pewno nie jesteś programistą bazodanowym. Jesteś zapewne programistą Java lub programistą C#, względnie programistą C++ który nauczył się składni języka SQL nie wnikając co pod nim leży (disclaimer: nie wnikam tu w Twoje zdolności analityczne, managerskie etc. jako, że dyskusja toczy się na zdecydowanie techniczny temat).

Co do komara i RPG - o ironio, jest zupełnie odwrotnie. Dla pewnych specjalistycznych zastosowań bazy danych są zbyt kiepskie, zbyt mało wydajne. Wtedy należy właśnie wrócić do jakiegoś niskopoziomowego podejścia i samemu oprogramować zarządzanie danymi. Ale to nie jest ,,kilka prostych pętelek'' :-) W tym tutaj przypadku takie podejście raczej nie jest niezbędne...
Mieczyslaw B.:
Nie każda baza to Oracle b. często wyręczający swoimi mechanizmami programistę od myślenia lub optymalizacji..

To interesująca sentencja - możemy się wgłębić kapkę :>

A na koniec - nie gniewaj się o kilka uszczypliwych uwag...To nic personalnego, chodzi o to, że często spotykam się z opinią, że najlepiej być mądrzejszym od DBMS-a i przetwarzać dane samemu, bo ,,baza sobie nie radzi''. To wcale nie jest tak i to co robię to walka z herezjami :-) a nie ludźmi.

Kłaniam się,
Grzegorz.

konto usunięte

Temat: Jaki był najdłuższy ciąg...

Przepraszam, ale widać, że Panowie chyba nie wiedzą jak się przetwarza batchowo...

Rozwiązanie "SQL ponad wszystko" jest dobre, jeśli mamy bazę na swoim komputerze i nikomu nie dajemy do niej dostępu. Wtedy -może- baza SQL się wyrobi i rzeczywiście będzie to szybsze rozwiązanie od przetworzenia batchowego (na boku).

Ale batche stosujemy gdy:
- na bazie równolegle pracują setki/tysiące użytkowników
- mamy do przerobienia więcej niż 100 rekordów
- jest szansa, że dotkniemy wszystkich rekordów w tabeli
- przetworzyć możemy bezpośrednio na serwerze bazy (program uruchomiony na maszynie gdzie znajduje się serwer bazy)

Nie jest to jakaś głębsza filozofia - wystarczy sobie troszkę policzyć. Oczywiście przy małych rozwiązaniach jest to przerost formy nad treścią i w takich przypadkach lepiej pokombinować z SQL-ikami.
Mieczyslaw B.

Mieczyslaw B. e-Health, project
management

Temat: Jaki był najdłuższy ciąg...

Grzegorz G.:

(...)

Każdy robi w tym, czym robi:) Po profilu i wypowiedziach widzę, że ograniczasz się raczej tylko do Oracle i pomijasz proste DBMS. Nie przeczę, że w bazie danych można wiele, ale jakim kosztem... i to już inna bajka.
Poza tym trochę na bakier stoisz z obliczeniami:
5000 requestów x 10s = 50000s = 13,889h
500 requestów x 10s = 5000s = 1,3889h
Zgubiłeś się już w obliczeniach?:) I pomyśl, że taki atak na bazę trwa non stop co kilkanaście/kilkadziesiąt sekund, a minimum na daną chwilę to 100 (1000) requestów. Nadal będziesz pisać w SQL/nie zoptymalizujesz swojego kodu PL/SQL? Życzę powodzenia!

Pozdrawiam i miłego wekendu:)
Grzegorz G.

Grzegorz G. ASE / Systems
Architect, Syniverse

Temat: Jaki był najdłuższy ciąg...

5000 requestów x 10s = 50000s = 13,889h

Czyli - w Twoim rozumieniu - to normalna sytuacja, że mam system w którym na odpowiedź na 10-sekundowe pytanie trzeba czekać 14h (najbardziej pechowa transakcja)? Chyba że coś innego miałeś na myśli...Ale chyba tylko w takim kontekście to mnożenie ma sens.
Nadal będziesz pisać w SQL/nie zoptymalizujesz swojego kodu PL/SQL?

Z zasady optymalizuję przepisując jakieś proceduralne bzdury do SQL :-)
Nie przeczę, że w bazie danych można wiele, ale jakim kosztem... i to już inna bajka.

Jakim kosztem?
Ale batche stosujemy gdy:
- na bazie równolegle pracują setki/tysiące użytkowników
- mamy do przerobienia więcej niż 100 rekordów
- jest szansa, że dotkniemy wszystkich rekordów w tabeli
- przetworzyć możemy bezpośrednio na serwerze bazy (program
uruchomiony na maszynie gdzie znajduje się serwer bazy)

O rety...Pomiędzy jest spójnik lub czy też spójnik i? Generalnie nie ma to większego znaczenia, ale trochę ciekaw jestem.

Ukłony,
Grzegorz.
Mieczyslaw B.

Mieczyslaw B. e-Health, project
management

Temat: Jaki był najdłuższy ciąg...

Grzegorz G.:
5000 requestów x 10s = 50000s = 13,889h

Czyli - w Twoim rozumieniu - to normalna sytuacja, że mam system w którym na odpowiedź na 10-sekundowe pytanie trzeba czekać 14h (najbardziej pechowa transakcja)? Chyba że coś innego miałeś na myśli...Ale chyba tylko w takim kontekście to mnożenie ma sens.

Chodzi o sytuację gdy masz zapytanie SQL, które jednostkowo wykonuje się ok. 10s. Napisałeś: "jeżeli da się coś w nim sensownie zapisać to najprawdopodobniej to jest właściwa ścieżka". Z takim twierdzeniem nie zawsze mogę się zgodzić i jeśli się nie da zoptymalizować - niestety czasem trzeba wyciąć na zewnątrz. Nawet jak ustawisz na klastrze lub wieloprocesorowej maszynie, nie przebrniesz przez to.
Przykład:
0. Jesteś architektem powstającego systemu.
1. Zapytanie sensownie napisane w SQL przy jednoprocesorowej maszynie wykonuje się ok. 10s
2. Wiesz, że będzie minimum 1000 requestów/sekundę
3. Co kilkadziesiąt sekund zdarzy się sytuacja ekstremalna 5000 req.
4. Ilość requestów będzie oscylować pomiędzy 1000 a 5000.
W takim przypadku puszczenie do systemu produkcyjnego rozwiązania opisanego w (1) nie ma sensu. Zapewniam Cię, że systemy stają się coraz bardziej złożone i na 100% trafisz kiedyś sytuację nie do przejścia w SQL.

Jeśli się nie rozumiemy - przejmuję winę na siebie i koniec gadki, bo jest to poza tematem głównym wątku.
Z zasady optymalizuję przepisując jakieś proceduralne bzdury do SQL :-)

Zakładam, że jest już sensownie napisane, optymalizacja nic nie da.
Michał O.

Michał O. Kierownik Działu
Zarządzania Jakością
Produktów, Polska
T...

Temat: Jaki był najdłuższy ciąg...

Muszę powiedzieć, że zgadzam się w zupełności z Grzegorzem. W SQLu pisze się łatwo, prosto i przyjemnie. Dzięki temu można szybko generować potrzebne raporty z bazy. A jeśli są problemy z wydajnością, to wtedy można dane obrobić PL-SQLem, czy ewentualnie czymś niższego poziomu poza bazą.
Ale unikanie SQLa "z założenia", bo mniej wydajny, jest imho absurdem. I jeśli na każde zapytanie trzeba długo czekać, to rozwiązaniem jest (przy założeniu optymalności struktur bazy i zapytań) nie obrabianie danych na boku przy pomocy "kilku prostych pętli i procedur", tylko zwiększenie wydajności serwera.

pozdr.,

Michał
Tadeusz Pyś

Tadeusz Pyś ..czyli samo zuo ;)

Temat: Jaki był najdłuższy ciąg...

pozwole sobie dorzucic trzy grosze, bo chyba nie nikt nie zauwazyl innej mozliwosci.. jak dla mnie i przetwarzanie u klient i na bazie danych sa potrzebne, ale maja inny CEL!

przetwarzanie na bazie danych jest potrzebne aby, odczytac pierwotne dane zrodlowe, odfiltrowac te zbedne (po co je wysylac po sieci?), pobrac dane towarzyszace i powiazania pomiedzy nimi

a u klienta obrobic, sformatowac, przeliczyc, wyliczyc nowe wartosci wywiedzone itede

niech RDBMS zostanie baza danych, do tego jest stworzony.. zarowno pisanie plytkiego klienta ktory tylko umie wyswietac dane i zawalanie DB'a formatowaniem i obliczenami, jak i pisanie uber-ciezkiego klienta ktory za kazdym razem zrzyna cale tablice i potem pracuje offline'owo - mija sie generalnie z celem..

konto usunięte

Temat: Jaki był najdłuższy ciąg...

Michał O.:
Ale unikanie SQLa "z założenia", bo mniej wydajny, jest imho absurdem. I jeśli na każde zapytanie trzeba długo czekać, to rozwiązaniem jest (przy założeniu optymalności struktur bazy i zapytań) nie obrabianie danych na boku przy pomocy "kilku prostych pętli i procedur", tylko zwiększenie wydajności serwera.

Są klasy problemów, w których z założenia ustala się, że SQL jest mniej wydajny (nawet niespecjalnie się trzeba nad tym zastanawiać).
Jakie to problemy - już wylistowałem warunki powyżej.
Grzegorz - jeśli pytałeś o to czy między warunkami jest "OR" czy też "AND" to odpowiedź brzmi - im więcej tym lepiej. Tzn im więcej warunków zachodzi tym więcej "za" tym, aby stosować przetwarzanie batchowe. Nie spotkałem się natomiast z takim przetwarzaniem poza serwerem (tylko w obrębie tej samej maszyny).

To jest dość specyficzny temat i wierzę, że nawet 90% programistów bazodanowych się z nimi może nigdy w życiu nie spotkać. Ale właśnie ten przypadek idealnie pasuje do tego, aby zapomnieć o SQL-u (na chwilę).

Złożoność przetwarzania batchowego (na boku) jest prosta do wyliczenia, w tym wypadku (-bardzo- zgrubnie licząc) będzie to jakieś: O(a*n)
gdzie a to stała i zawiera:
1 odczyt z bazy per rekord
1 zapis pliku per rekord
1 odczyt pliku per rekord
1 przeliczenie per rekord
(ew) 1 zapis pliku per rekord
(ew) 1 odczyt pliku per rekord
1 zapis do bazy per rekord

Czyli w końcowym efekcie O(n).

Oczywiście I/O na plikach jest sekwencyjne (czyt. bardzo dobrze cachowalne), co nie zawsze można powiedzieć o I/O na bazie.

Jeśli się w którymś punkcie mylę to mnie poprawcie.Piotr Likus edytował(a) ten post dnia 13.01.08 o godzinie 23:11
Mirosław Serwaczyński

Mirosław Serwaczyński Analityk programista

Temat: Jaki był najdłuższy ciąg...

Zadziwiająca jest ta dyskusja.

Po to są robione bazy SQL w technologii klient-serwer, żeby klient tworzył zapytanie, przesyłał je po sieci, Serwer głęboko nad tym myślał, i zwracał stosunkowo mały wynik po sieci. Założenia są trzy: Serwer obrobi zapytanie szybciej niż maszyna lokalna, maksymalnie ograniczamy ruch w sieci, nie chcemy problemu z aktualnością danych.

Widziałem już rozwiązania, gdzie systemy "były oparte na SQL" (bo to nowoczesnie brzmi, nieprawdaż?), i przetwarzały rekord po rekordzie chcąc znaleźć cokolwiek. Efekt? Po przekroczeniu pewnej masy krytycznej (czyt. pewnej ilości rekordów) system zduszał sieć, otwierając klika tys. równoczesnych połączeń do serwera (każde, nawet bzdurne zapytanie do SQLa, trzyma przez pewien czas otwarty kanał).

JEŻLI baza jest na tyle duża, że nie da rady odpowiedzieć na zapytanie w kila-kilkanaście sekund, to TYM BARDZIEJ nie zdąży w tym czasie przesłać prawie-kompletu wszystkich rekordów do klienta. Jeżeli problemem jest równoczesne odpowiedzenie na ileś zapytań, to jakim problemem będzie równoczesne przesłanie kompletu danych do tych samych klientów?Mirosław Serwaczyński edytował(a) ten post dnia 14.01.08 o godzinie 08:22
Grzegorz G.

Grzegorz G. ASE / Systems
Architect, Syniverse

Temat: Jaki był najdłuższy ciąg...

Jeśli się w którymś punkcie mylę to mnie poprawcie.

Na samym początku - we wszystkich czterech punktach :-)

Reasumując: nie do końca rozumiem, po co wam bazy danych. Nie wygodniej byłoby wrócić do plików tekstowych?
Mieczyslaw B.

Mieczyslaw B. e-Health, project
management

Temat: Jaki był najdłuższy ciąg...

Popadamy ze skrajności w skrajność. Wszystko jest względne i wymaga zdroworozsądkowego podejścia. Ogólnie - bazy są po to, po co są, ale też nie do wszystkiego się wszystkie nadają, czy się to komuś podoba czy nie:) Co się da rozsądnie wykonać w DB, niech będzie stworzone w SQL, T-SQL, PL/SQL, ale nie znaczy to, że musi to być najwłaściwszym rozwiązaniem (ślepa wiara w ideologię bywa zgubna). Jedni będą robić wszystko w DB, inni przetwarzanie w złożonym systemie logicznie podzielą i rozdzielą obciążenie na kilka/naście/dziesiąt maszyn. Co kto woli, byle rozsądnie.
Temat tego wątku to jednak "Jaki był najdłuższy ciąg".
Leszek Trenkner

Leszek Trenkner Architekt BI

Temat: Jaki był najdłuższy ciąg...

Witam,
To mój pierwszy post w okolicy, ale za to długi będzie niemiłosiernie ;-)

Wracając do tematu "Jaki najdłuższy ciąg...", w wersji czysto-SQLowej możemy chyba popełnić takie zapytania (sprawdzone w Postgresie, chyba całkiem ANSI-SQL zgodne).

Dla każdego rekordu ustalamy id poprzedniego rekordu, kiedy ten sam klient kupił ten sam produkt (test to tabela zawierająca przykładowe dane):

select a.id, a.klient, a.prod,
coalesce((select max(id) from test b where b.klient=a.klient and a.prod = b.prod and b.id < a.id ),0) as prev_id
from test a;

Efekt:
id,klient,prod,prev_id
1,1,'A',0
2,1,'A',1
3,1,'B',0
4,1,'A',2
5,1,'A',4
6,1,'A',5
7,1,'A',6
8,1,'C',0

Albo ustalamy id poprzedniego rekordu, kiedy ten sam klient inny produkt:

select a.id, a.klient, a.prod,
coalesce((select max(id) from test b where b.klient=a.klient and a.prod <> b.prod and b.id < a.id ),0) as other_id
from test a;

Efekt:
id,klient,prod,other_id
1,4,'A',0
2,4,'A',0
3,4,'B',2
4,4,'A',3
5,4,'A',3
6,4,'A',3
7,4,'A',3
8,4,'C',7

Można to wrzucić w tabele tymczasowe jak danych będzie dużo/spodziewamy się wielu podobnych zapytań, to może nawet będzie sens dodatkowo poindeksować takie wyniki pośrednie.

Mając taką informację możemy pozliczać count(*) co chcemy w wybranych przedziałach i wybrać sobie z nich min, max czy też avg - co się komu podoba:

Ile razy z rzędu klient kupił X zanim kupił Y, albo kupił cokolwiek innego niż Y:

select klient, prod, max(kupil_a) as max_kupil_a, max(kupil_b) as max_kupil_b, max(kupil_c) as max_kupil_c, max(kupil_inny) as max_kupil_inny from (
select foo.*,
(select count(*) from test c where c.id > foo.prev_id and c.id<foo.id and c.klient=foo.klient and c.prod='A') as kupil_a,
(select count(*) from test c where c.id > foo.prev_id and c.id<foo.id and c.klient=foo.klient and c.prod='B') as kupil_b,
(select count(*) from test c where c.id > foo.prev_id and c.id<foo.id and c.klient=foo.klient and c.prod='C') as kupil_c,
(select count(*) from test c where c.id > foo.prev_id and c.id<foo.id and c.klient=foo.klient and c.prod<>foo.prod) as kupil_inny
from (select a.id, a.klient, a.prod,
coalesce((select max(id) from test b where b.klient=a.klient and a.prod = b.prod and b.id < a.id ),0) as prev_id
from test a) foo) foo2
group by klient,prod
order by klient,prod;

Duże trochę, ale cóż - ma raczej pokazać że się liczy co trzeba, normalnie dla n produktów raczej nie robilibyśmy n+1 podzapytań dla poszczególnych kolumn z danymi :-)

klient, prod, max_a, max_b, max_c, max_inny_niż_prod
1,'A',0,3,1,3
1,'B',5,0,1,6
1,'C',6,1,0,7

Ile razy maksymalnie kupił produkt X z rzędu:

select klient, prod, max(kupil_ten_sam) as max_kupil_ten_sam from (
select bar.*, (select count(*) from test c where c.id > bar.other_id and c.id<=bar.id and c.klient=bar.klient and c.prod=bar.prod) as kupil_ten_sam
from (select a.id, a.klient, a.prod,
coalesce((select max(id) from test b where b.klient=a.klient and a.prod <> b.prod and b.id < a.id ),0) as other_id
from test a) bar) bar2
group by klient,prod
order by klient,prod;

Efekt:
klient, prod, max_ten_sam_z_rzędu
1,'A',4
1,'B',3
1,'C',1

Zakładając że są na bazie sensowne indeksy (na id, kliencie i produkcie), wydaje mi się że żadne z tych zapytań nie powinno być zbyt skomplikowane ani zajmować szczególnie dużo czasu, żeby zarżnąć serwer.

Zbaczając z tematu:

Jeżeli serie danych zakupowych dla pojedynczych klientów byłyby typu B, 2mln*A, C, 5mln*A, B i to losowo wymieszane z 30 mln zakupów dla innych klientów, nie jestem przekonany, że przetwarzanie danych metodą sekwencyjna/batchową/kursorami dałoby jakąś sensowną wydajność - przy pytaniach o konktretne produkty konkretnego klienta wydaje mi się to jakoś mało prawdopodobne.Leszek Trenkner edytował(a) ten post dnia 16.01.08 o godzinie 03:36
Mirosław Serwaczyński

Mirosław Serwaczyński Analityk programista

Temat: Jaki był najdłuższy ciąg...

Dwie uwagi do rozwiązania:
select a.id, a.klient, a.prod,
coalesce((select max(id) from test b where b.klient=a.klient and
a.prod = b.prod and b.id < a.id ),0) as prev_id
from test a;

1. To zapytanie ma bardzo duży koszt wykonania - dla każdego przetwarzanego rekordu tabeli poszukujemy max(id) w tej samej tabeli, koszt = n*n

2. ISNULL też (chyba?) pójdzie szybciej niż COALESCE, no i jest bardziej czytelne (skoro mamy tylko jedno wyrażenie) - ale to już kwestia gustu :-)

konto usunięte

Temat: Jaki był najdłuższy ciąg...

Leszek Trenkner:
(ciach)
Albo ustalamy id poprzedniego rekordu, kiedy ten sam klient inny produkt:

select a.id, a.klient, a.prod,
coalesce((select max(id) from test b where b.klient=a.klient and a.prod <> b.prod and b.id < a.id ),0) as other_id
from test a;

Efekt:

Efekt to NIEINDEKSOWALNE zapytanie o wydajności O(n^2)...
Zbaczając z tematu:

Jeżeli serie danych zakupowych dla pojedynczych klientów byłyby typu B, 2mln*A, C, 5mln*A, B i to losowo wymieszane z 30 mln zakupów dla innych klientów, nie jestem przekonany, że przetwarzanie danych metodą sekwencyjna/batchową/kursorami dałoby jakąś sensowną wydajność - przy pytaniach o konktretne produkty konkretnego klienta wydaje mi się to jakoś mało prawdopodobne.

Jeśli chodzi o zapytanie o konkretnego klienta:

a) zrzucasz do pliku (tabeli tymczasowej) dane dla konkretnego klienta (indeksowalne) (n operacji)
b) przelatujesz kursorem (lub wczytujesz seryjnie wszystkie rekordy) i przeliczasz każdy po kolei (n operacji)
c) zapisujesz wynik do tabeli (tymczasowej) lub pliku (n operacji)

Kursor czy plik będzie tu zawsze szybszy. Oczywiście do zrzucania danych nie można używać swojego programu tylko odpowiednie narzędzie "bulk load / bulk dump".
Przy braku takiego można sobie potrenować z tabelą tymczasową. Też powinno być szybciej, ale nie wiem, czy aż tak jak z plikiem.

Z charakteru zapytania można wnioskować, że wystarczy je odpalić raz dziennie dla wszystkich klientów (w celu wygenerowania danych do raportu) - wtedy rozwiązanie "na boku" na pewno się sprawdzi.

Drobna uwaga: takie procesowanie jest optymalne na IBM DB2, gdy program pracuje na maszynie serwera SQL i masz dostępne narzędzia "bulk load". Z tego co wiem, także ma takie narzędzia Sybase i MS SQL (BCP).Piotr Likus edytował(a) ten post dnia 16.01.08 o godzinie 09:48
Łukasz K.

Łukasz K. 3AM software

Temat: Jaki był najdłuższy ciąg...

Jeśli chodzi o podejście do baz danych, to zacytuję tu T. Kyte'a ( http://www.oracle.com/technology/oramag/oracle/07-mar/... ) :
"I have a pretty simple mantra when it comes to developing database software, and I have written this many times over the years:

* You should do it in a single SQL statement if at all possible.
* If you cannot do it in a single SQL statement, do it in PL/SQL.
* If you cannot do it in PL/SQL, try a Java stored procedure.
* If you cannot do it in Java, do it in a C external procedure.
* If you cannot do it in a C external procedure, you might want to seriously think about why it is you need to do it.

If you can do it in a single SQL statement, by all means do it in a single SQL statement. Do not waste time, energy, and CPU cycles writing procedural code that will run slower than regular SQL."

W końcu bazy danych i optymalizatory w nich zastosowane nie są pisane tylko i wyłącznie po to, żeby mieć gdzie trzymać dane (bo równie dobrze można do tego celu wykorzystać pliki tekstowe, czy choćby XMLe) :)Łukasz K. edytował(a) ten post dnia 16.01.08 o godzinie 10:12
Grzegorz G.

Grzegorz G. ASE / Systems
Architect, Syniverse

Temat: Jaki był najdłuższy ciąg...

Piotr Likus:
Leszek Trenkner:
(ciach)
Albo ustalamy id poprzedniego rekordu, kiedy ten sam klient inny produkt:

select a.id, a.klient, a.prod,
coalesce((select max(id) from test b where b.klient=a.klient and a.prod <> b.prod and b.id < a.id ),0) as other_id
from test a;

Efekt:

Efekt to NIEINDEKSOWALNE zapytanie o wydajności O(n^2)...

SQL> create table test (klient number, prod number, id number);

Table created.

SQL> create index x_test on test(klient, id);

Index created.

SQL> explain plan for
2 select a.id, a.klient, a.prod,
3 coalesce((select max(id) from test b where b.klient=a.klient and a.prod <> b.prod and b.id < a.id ),0) as other_id
4 from test a;

Explained.

SQL> select * from table (dbms_xplan.display);

PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------------------------------------

Plan hash value: 76538233

---------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 39 | 2 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 39 | | |
|* 2 | TABLE ACCESS BY INDEX ROWID| TEST | 1 | 39 | 1 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | X_TEST | 1 | | 2 (0)| 00:00:01 |
| 4 | TABLE ACCESS FULL | TEST | 1 | 39 | 2 (0)| 00:00:01 |
---------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - filter("B"."PROD"<>:B1)
3 - access("B"."KLIENT"=:B1 AND "B"."ID"<:B2)

Note
-----
- dynamic sampling used for this statement

21 rows selected.


Zgadzam się że to zapytanie nie ma sensu (funkcje analityczne są tu właściwą techniką). Ale nie rozpędzajmy się tak z tym O(n^2). Indeks jest jak najbardziej na miejscu. Po pierwsze, mamy za darmo klienta. Po drugie, mamy posortowane ID - więc znając górne (a.ID) w czasie stałym (bo to B+-drzewo) znajdujemy właściwe (max(b.ID)). Przynajmniej w teorii mogłoby to tak wyglądać :-)

konto usunięte

Temat: Jaki był najdłuższy ciąg...

Grzegorz, nareszcie jakaś merytoryczna odpowiedź. Dzięki!

3 - access("B"."KLIENT"=:B1 AND "B"."ID"<:B2)

To oznacza jak dla mnie średnio 1/2*n dostępów (dla każdego rekordu - (n*1/2) czyli n*(n*1/2) operacji). Czyli indeks na pewno pomaga. I w takim wypadku pewnie ciężko będzie znaleźć lepsze (i proste) rozwiązanie oparte o jednego SQL-a.

2 - filter("B"."PROD"<>:B1)

Nie znam aż tak Oracla, ale czy to nie oznacza filtrowanie -wszystkich- rekordów? (dla każdego rekordu n operacji - n^2).
Leszek Trenkner

Leszek Trenkner Architekt BI

Temat: Jaki był najdłuższy ciąg...

Coś tutaj z edycją nie wyszło, więc post poniżej.Leszek Trenkner edytował(a) ten post dnia 16.01.08 o godzinie 15:31
Leszek Trenkner

Leszek Trenkner Architekt BI

Temat: Jaki był najdłuższy ciąg...

Jeżeli tego typu raport mielibyśmy generować tylko kilka dziennie, to czy faktycznie byłby sens pisać batcha/coś w oparciu o kursory jeżeli zapytanie w czystym SQL zajęło by np. minutę, a bardziej wymyślny kawałek zewnętrznego kodu na dopalaczach robiłby to w 10 sekund? Można by z tego zrobic jakis 'materialized view' i nikt by nawet nie zauważył kiedy się to robi i ile czasu zajmuje.

Rozwiązanie moje jest być może wysoce nieoptymalne, ale robi to co trzeba "w jednym zapytaniu", więc są pewne przesłanki za stosowaniem takich rozwiązań.

Co do indeksowania - ciężko będzie jego wpływ sprawdzić na Postgresie, bo trzeba by było pogenerować sporo danych, żeby zmusić planner do użycia indeksu - dla takich ilości jak mamy w próbce to zawsze łatwiej odczytać tabelę sekwencyjnie z RAM niż cokolwiek robić z indeksem. I nie wiemy jakie są rozkłady wartosći dla produktów, klientów i dat, a to ma - przynajmniej w Postgresie - wpływ na to czy, jakie i w jakiej kolejności indeksy zostaną użyte.

Sam max i pozostałe warunki mogą korzystać ze wsparcia indeksów (można pozakładać indeksy częściowe i klastrować tabelę np. po kliencie i/lub produkcie, co zresztą i dla wersji 'batchowej' okazałoby się korzystne), więc nie sądzę żeby faktyczny średni koszt wyszukania takiego max(id) był aż tak duży, jak Panowie
pesymistycznie szacują.


2 - filter("B"."PROD"<>:B1)

Nie znam aż tak Oracla, ale czy to nie oznacza filtrowanie -wszystkich- rekordów? (dla każdego rekordu n operacji - n^2).

Baza danych stara się szacować kolejność zakładania warunków, tak aby zminimalizować 'n' obecne na każym kroku. Możemy się spodziewać, że ilość rożnych produktów jest istotnie mniejsza od ilości rekordów i klientów, więc dla tego warunku n' może być mocno mniejsze niż n dla całej tabeli czy konkretnego klienta/produktu, bo to będą prawdopodobnie 'tylko' -wszystkie rekordy które spełniły poprzednie warunki-. I być może wystarczy dla każdego produktu tylko raz wygenerować listę rekordów, których "B"."PROD"<>:B1. A może baza zrobi to za pomocą indeksów bitmapowych i prawie wszystkie warunki sprawdzi z wykorzystaniem indeksu?

Teoretyczne oszacowanie wpływu tych czynników może być trudne, bo każda baza może mieć tutaj inny pomysł na wykoanie zapytania, ale faktycznie ma to duże znaczenie dla wydajności.

Czy wyładowanie danych z tabeli ( dodatkowo okraszone jakimiś warunkami ) nie wymaga filtrowania wszytkich rekordów? Bulk dump musi te dane zdaje się i tak odczytać, żeby stwierdzić czy je dalej 'przekazać'.

Jeżeli danych jest mało, to przypuszczam że mechanizm cache'u bazy w połączeniu z SQL da mniejszy koszt operacji I/O niż jakakolwiek próba przerzucenia danych 'na zewnątrz'.

Jak danych będzie dużo, to pewnie lepiej trzymać się z dala od każdego zbędnego zapisu/odczytu dysku, RAM i CPU jak na razie są na ogół znacznie szybsze od dowolnie wymyślnych dysków, więc zrobienie 1000 skanów wyników cząstkowych w RAM może być szybsze niż jeden odczyt sekwencyjny tabeli z dysku.

Wydaje mi się że porównywanie rozwiązań w oparciu o rozważania teoretyczne dotyczące ich złożoności obliczeniowej algorytmu ma sens o ile możemy zapewnić podobny 'koszt jednostkowy' pojedynczej operacji, w 'warunkach bojowych' może się okazać że koszty stałe niektórych operacji powodują - zakładając skończone zbiory danych - że algorytm O(n) może okazać się wolniejszy od O(n^2).

A i tak cała dyskusja ma już teraz charaketer raczej akademicki, bo kilka sposobów rozwiązania problemu przedstawiono, ale nie jesteśmy obecnie w stanie porównać ich wydajności w warunkach rzeczywistych, dla konkretnej implementacji, zbioru danych i sprzętu który miałby to wszystko wykonywać.Leszek Trenkner edytował(a) ten post dnia 16.01.08 o godzinie 15:30

konto usunięte

Temat: Jaki był najdłuższy ciąg...

Leszek Trenkner:
A i tak cała dyskusja ma już teraz charaketer raczej akademicki, bo kilka sposobów rozwiązania problemu przedstawiono, ale nie jesteśmy obecnie w stanie porównać ich wydajności w warunkach rzeczywistych, dla konkretnej implementacji, zbioru danych i sprzętu który miałby to wszystko wykonywać.

Z tym się akurat zgodzę. Propozycje rozwiązań już przedstawiono, pozostaje je przetestować i wcielić w życie.

Nie chce nikomu burzyć światopoglądu, więc jeśli ktoś uważa, że w SQL można wszystko to nie będę mu tego bronić... tolerancja ;-)

Pozdrawiam!Piotr Likus edytował(a) ten post dnia 16.01.08 o godzinie 16:43



Wyślij zaproszenie do