10 wartych poznania cech motoru bazy danych
Dopiszesz #11 ?
Nie dopiszę 11, za to mam pewną uwagę: stosowanie logiki biznesowej w samej bazie danych np. triggery, ma pewne zalety ale też minusy. Największy to taki, że kiedy jest jakiś błąd w tej logice, albo trzeba ją zmienić to zaczynają się problemy. W sytuacji kiedy bazę danych traktujemy tylko jako CRUD bez logiki, a logikę trzymamy w aplikacji, zmiana tej logiki jest mniej bolesna, chociażby dlatego, że możemy ręcznie przez SQL naprawić coś w samych danych nie uruchamiając jednocześnie w samej bazie triggerów i logiki tej kórą właśnie chcemy naprawić / zmienić. Niby można tymczasowo wyłączyć triggery, ale mamy nad całym procesem mniejszą kontrolę. Mogę podać też inne problemy wynikające z przenoszenia logiki do warstwy danych.
@TomRZ: inny problem, to trudniejsze wersjonowanie takiej logiki opartej o triggery, procedury itd. Niby da się, ale wtedy musisz trzymać np. katalog z migracjami, w której będzie sobie żyła każda kolejna wersja schematu / triggerów etc. i utrzymywać tam albo natywny SQL, albo jakieś dziwne konfiguracje narzędzi migracyjnych, albo oba. W dodatku aplikowanie dużej liczby migracji jedna po drugiej będzie coraz bardziej czasochłonne, aż w końcu ktoś zdecyduje o zrobieniu baseline / spłaszczeniu migracji i cyk, i tak musisz krążyć po gicie by ustalić cokolwiek na temat przeszłości. Już prościej mieć to jako wersjonowany kod pod VCS.
Dochodzi jeszcze kwestia skorelowania wersji logiki w SQL z wersją aplikacji, szczególnie jak już sobie gdzieś żyje ;)
@superdurszlak @TomRZ trzeci problem to problem skalowalności. Aplikację bezstanową skaluje się dużo prościej niż stanową. Baza danych z założenia jest stanowa. Jak triggery i procedury składowane zaczynają się nie wyrabiać to mamy duży problem. No i czwarty problem że programowanie w PL(PG)SQLu jest ciężkie. Już wolę Javę :(
Triggery to zło - i powinny być stosowane w ostatecznych przypadkach. W bazie powinna znaleźć się ta logika, która ewidentnie operuj tylko na danych w bazie - czyli w takim wypadku przepychanie danych między bazą a klientem jest zbędnym narzutem. PLSQL jest akurat prosty - czasem wręcz ubogi - brak wielu struktur danych itp.
@KamilAdam: Programowanie w PL SQLu jest ciężkie - bo język to rak. Nie wiem jak pozostałe, bo umiem tylko w PL SQL, ale to najgorszy język programowania z jakim mam do czynienia - potwór żywcem przeniesiony z koszmarów lat 80tych. Absurdalna składnia, zerowe możliwości abstrakcji, tony dziwnych wyjątków w semantyce ... Nawet PHP wydaje się przy tym znośne. Chociaż.... może jakbym nie poznał żadnego innego języka to by mi wystarczał. (BASIC na C64 jest gorszy od PL/SQL, a kiedyś mi się podobał).
@vpiotr: to prawda. COBOL też jest straszny (ale w COBOLu nie piszę - więc o tym zapominam).
@jarekr000000: @KamilAdam przecież nie trzeba pisać procedur w PL SQL'u, można to robić w większości znanych języków :)
@nullpt4: to, że Oracle tak twierdzi to nie znaczy, że jest to prawda. Sam przerabiałem javowe procedury na PL/SQL. 1. po pierwsze to nie były tak do końca javowe - tylko w jakiejś pseudojavie w jakimś antycznym standardzie 2. nie działały (z różnych powodów - a to nie ta wersja Oracla, a to admin coś zapomniał doinstalować, za dużo problemów to robiło). 3. Poj... ny deployment i debug tego to kwiatek do kożucha - człowiek w javie jest przyzwyczajoiny do jakichś sensownych komunikatów, stack traców, a nie ORA-71830 Nie, bo nie
Podsumowując - najlepiej gdy baza danych to magazyn bez logiki biznesowej. Partycjonowanie, replikacje, etc. jak najbardziej, ale nawet zliczanie sum w jakimś dokumencie na podstawie dołączonych elementów z ceną (np. pozycje w fakturze) to błąd. Kiedy np. dołączamy do faktury w jednym requeście 50 pozycji, mając logikę po stronie bazy robimy to 50-razy dla każdej pozycji, mając logikę w aplikacji możemy to zrobić na końcu transakcji po udanym dodaniu wszystkich pozycji do faktury.
@TomRZ: Zupełnie się z tobą nie zgodzę, żeby sumowanie robić po stronie klienta. W jaki sposób robisz sumowanie 50 razy dla pozycji? Możesz rozwinąć temat?
@TomRZ to zależy. Przenoszenie logiki do bazy danych to sposób na to żeby aplikacja działała (przeważnie) szybciej kosztem tego, że nie będzie skalowalna. Czyli z aplikacji działającej dla 10 tysięcy użytkowników zrobimy taką która obsłuży 50 tysięcy... ale już nie będzie sie nigdy nadawała do obsługi 100 tysięcy. Na żadnym sprzęcie. (oczywiście liczby z palca wyssane - ale już trafiłem na takie aplikacje (full of PL/SQL) - jest dramat wydajnościowy i bez przepisania nie da się wiele zrobić).
@TomRZ: zależy jeszcze co rozumiesz przez sumowanie po stronie bazy i po stronie klienta. Bo robienie tego sumowania w kodzie aplikacji (nie w zapytaniach / DSLach) brzmi jak pomysł na robienie sobie piercingu wiertarką udarową. Z drugiej strony sumowanie w zapytaniu / widoku / zmaterializowanym widoku nie brzmi jeszcze tak źle i jest do ogarnięcia, pod warunkiem że to faktycznie proste sumowanie, a nie złożone procedury i triggery wprowadzające efekty uboczne przy zapisie
@UglyMan: masz relację gdzie przechowujesz pozycje dla faktur, gdzie masz kluc zobcy do faktury, nazwę produktu/pozycji, ilość, i cenę. Teraz masz trigger w bazie danych (na tabelę pozycji) który reaguje na dodanie/usunięcie/zmianę pozycji w ten sposób, że w samej fakturze do której jest klucz obcy aktualizuje sumy netto/brutto. I teraz masz sytuację w aplikacji gdzie do faktury dołączasz te 50 pozycji po kolei w jednym requeście. Z triggerem oznacza to 50 razy wykonanie sumowania, bez triggera mogę to zrobić w aplikacji tylko raz na samym końcu tego seryjnego dodawania do faktury. Oczywiście mozna nie trzymać sum w fakturze i za każdym razem kiedy trzeba sumować przez SQL, ale to jest tylko przykład, i to bardzo prosty.
@jarekr000000: no właśnie zależy, ale u mnie statystycznie rzecz biorąc, na bardzo niewielu tabelach mam triggery, to jest około 0.5 - 1% tabel.
@TomRZ: No to jakieś karkołomne rozwiaznie - po co sumować na fakturze te dane jak są na pozycjach? Jak potrzebujesz zrobić jakieś sumy pośrednie, żeby przyspieszyć jakąś analitykę to robisz proces, który przeleci po bazie i policzy co trzeba. Takie coś jak faktura, można rozwiązać widokiem, który policzy sumy dla faktury na podstawie pozycji - 50 wierszy to jest nic - zkałądajć że masz klucze i indeksy.
@vpiotr: Tak to przykład, aczkolwiek są jeszcze np. faktury pro-forma i różne dziwne przypadki kiedy jednak trzeba fakturę zmienić, zanim się ją wyśle do klienta, ale nie będę się wgłębiał bo nie ma sensu a ja nie mam tyle czasu.
@TomRZ: Jak masz tak dużo triggerów to cos jest nie tak z tą twoją bazą. Triggery to zło - im więcej, tym większe zło.
PS. sumowanie (niekoniecznie w fakturach) jednak czasami się przydaje, kiedy chcesz wyszukać coś wg. sumy, albo zrobić raport na podstawie skomplikowanych warunków, to jednak lepiej mieć to wbite w pole, niż operować na widokach, jest to o wiele wydajniejsze, chociaż oczywiście komplikuje logikę. Wszystko zależy od danego przypadku.
@TomRZ: A co jak ci się te sumy rozjadą - co innego w pozycjach co innego w sumie ?
@UglyMan: a dlaczego miałyby się "rozjechać"? Przy prawidłowo działającej aplikacji nic się nie "rozjeżdża", to są prościutkie rzeczy. Stosuję tego typu mechanizmy po stronie aplikacji blisko 20 lat, i jeszcze nic mi się nigdy nie rozjechało - na produkcji oczywiście.
@TomRZ no przy prawidłowo działającej aplikacji się nie rozjeżdża, ale mając na uwadze trudności w utrzymywaniu, wersjonowaniu, zgrywaniu wersji procedur z wersją aplikacji, testowaniu logiki wbitej w bazę itd. itd. nie mówiąc o zwykłych niedopatrzeniach i czynniku ludzkim
- nie zakładałbym, że te błędy się nie pojawią. W przypadku, gdy masz widok możesz wprowadzić poprawkę i potem widoki będą już zwracać właściwe wartości. Jeśli jest problem z wydajnością zapytań masz widoki zmaterializowane (choć z ich przebudowaniem mogą być problemy - np. nie wszystkie DBMS są w stanie sensownie je updatować, więc muszą je zaorać). Natomiast gdy te wartości są powbijane w tabelki to naprawianie może oznaczać dodatkową gimnastykę.
@superdurszlak: u mnie się nigdy nic nie rozjechało, a aktualizacja sum w przypadku jakiegoś błędu to jest jedno polecenie UPDATE w połączeniu z agregatem, czyli mniej problemów niż bawienie się z widokami zmaterializowanymi. Natomiast każdy pracuje / modeluje architekturę tak jak uważa za stosowne. Ja generalnie widoków zmaterializowanych nie stosuję.
A nie można całej takiej faktury zapisać na raz ze wszystkimi pozycjami i sumą? Wtedy nie trzeba nic po stronie bazy liczyć, nic się nie rozjedzie, a sumowanie nawet uda się przetestować jakimiś normalnymi testami jednostkowymi niewymagającymi bazy do działania.
Nie bardzo rozumiem jak zmiana po wystawieniu kłóci się z tym, co napisałem. Zapis, czy nowej, czy zaktualizowanej starej można zrobić na raz.
serializable
w Oracle), jakie są trade-offy w poszczególnych implementacjachómar
, jak wybierany jest lider, co z potencjalną utratą / rozjechaniem się danych gdy padnie węzeł etc.