W dniu 24.04.2019 o 20:18, Wojciech Bancer pisze:
> On 2019-04-24, Kviat <Kviat> wrote:
>
> [...]
>
>>> Podałem swoje argumenty dlaczego tak uważam i dlaczego uważam triggery
>>> za mniej wydajne. Nie mam ochoty się powtarzać. Bazy danych są najbardziej
>>> obciążonym kawałkiem w typowych aplikacjach i nie należy ich dociążać.
>>
>> Triggery i procedury wbudowane nie służą tylko i wyłącznie do celów
>> optymalizacyjnych.
>
> No na pewno nie służą do zapisywania w nich logiki biznesowej.
> Zbyt kiepski to język.
W prawdziwym życiu oprócz logiki biznesowej (w zasadzie to do tego
określenia możesz wrzucić wszystko co chcesz, dopóki nie uściślisz co
masz na myśli), istnieją też inne logiki.
Jeden klient może chcieć moduł sprzedażowy+magazyn w jednym, a inny
osobno fakturowanie, a osobno magazyn. I te dwa różne modele biznesowe
łączy tylko to, że łączą się z tym samym serwerem bazy danych.
Jest jeszcze np. logika ustawodawcy, który wydaje takie, a nie inne
przepisy, że np. nie możesz usunąć jakiegoś dokumentu jak już go
wystawiłeś, albo dokumentu powiązanego logicznie (np. księgowo) z innym.
Masz możliwość implementowania tego w kilku aplikacjach klienckich i
przy każdej drobnej popierdółce zmieniasz i rekompilujesz wszystkie
aplikacje/moduły (nie wspominając o narzędziach firm zewnętrznych) i
wysyłasz klientowi żeby zrobił upgrade na 30 stanowiskach.
Albo robisz jedną zmianę w strukturze bazy, trigger before delete i
wysyłasz jeden upgrade dla serwera bazy. Wszystkie aplikacje, jakkolwiek
by nie były wypasione i choćby się łączyły z serwerem z drugiego końca
kraju, dostają komunikat z serwera, że nie da się usunąć rekordu i już.
(nie czepiaj się proszę przykładu - to tylko przykład)
Pisałem w poprzednim poście, co chyba przeoczyłeś, że jeżeli nie
zapewnisz integralności na poziomie bazy, to wystarczy głupi błąd w
jednej aplikacji klienckiej np.Magazyn w wersji 100.2345.45 SP3 i reszta
aplikacji klienckich leży z błędnymi danymi.
>> Nie widzę przeszkód w wersjonowaniu kodu procedury składowanej..
>
> Aha. I rollback do tego też?
Rollback do czego? Do przepisów księgowych które zmieniły się dwa lata temu?
> Albo taka magiczna sztuczka jak przeskok o 2 wersje, połączone
> ze zmianami na danych.
I w czym problem? Jeżeli wyszła wersja 10.2, a klient pracuje na wersji
10.0 to aktualizacja struktury bazy polega na:
10.0 -> 10.1 -> 10.2
a nie
10.0 -> 10.2
Musi być zachowana ciągłość, bo niektóre zmiany w wersji 10.2 dotyczą
wcześniejszych z wersji 10.1
Nie da się przeskoczyć z wersji 10.0 do 10.2, bo przepisy które są
aktualne dla wersji 10.2 nie istniały w czasie wersji 10.0, a były to
przepisy zmieniające przepisy z wersji 10.1, która wprowadzała zmianę do
przepisów w wersji 10.0.
Logika biznesowa to nie są sztuczki magiczne.
>> Co do pracy w zespole, to przecież osoba pisząca aplikację łączącą się z
>> bazą (korzystająca z danych składowanych w bazie) niekoniecznie musi
>> wiedzieć, co dana procedura/trigger robi "w środku". Interesują go
>> wyniki jakie otrzymuje z bazy.
>
> A potem osoba od DBA odejdzie i jest "aaayyyyeeeeecosiędzieje".
> Widziałem takie podejście wiele razy.
Przecież to nie jest wada triggerów i procedur składowanych.
To wada firmy krzak, w której jedyna "osoba od DBA" robi notatki o
zmianach ołówkiem na karteczkach post-it, a na odchodne ze złości klika
"encrypt stored procedure".
>>> A że trigger jakoś istotnie szybciej przeiteruje po tablicy
>>> w pamięci niż aplikacja, to wybacz nie wierzę. Język interpretowany
>>> nie ma dostępu do pamięci "gorszego sortu" tylko tej samej,
>>> chyba że serwer DB stoi na innej infrastrukturze.
>>
>> I wtedy aby przeiterować trzeba z bazy wypchnąć do klienta wszystkie
>> rekordy, które mają być przeiterowane, łącznie z rekordami zależnymi,
>> żeby otrzymać wynik.
>
> I mam uwierzyć, że jak ktoś nie potrafi optymalnie sobie pobrać
> danych do procesowania w aplikacji, to zrobi to optymalnie w triggerze.
> Tak, jasne.
Zdefiniuj co to znaczy "optymalnie pobrać"?
Tylko połowę WZ, RW i PZ żeby poznać aktualny stan magazynowy towaru,
czy wszystkie 15 tysięcy dokumentów zawierających jeszcze po 20 innych
pozycji towarowych z ostatnich czterech miesięcy, albo tworzyć w
kliencie dynamiczne zapytania do bazy, potworki SQLowe wybierające z
ostatnich 15 tysięcy dokumentów tylko te zawierające dany towar i niech
sobie klient zlicza jaki jest stan?
A w czasie pobierania i zliczania trzy inne stanowiska właśnie
wygenerowały kolejne 3 dokumenty i stan się zmienił.
A nie lepiej zliczyć na bieżąco w bazie AFTER INSERT/DELETE/UPDATE po
każdym dokumencie i zaktualizować pole ze stanem i wysłać tylko do
klienta aktualny stan?
>> Tutaj to kwestia kompromisu, czy do stu klientów wypchnąć po
>> kablach/radiu po np. 5GB żeby sobie przeiterowali lokalnie, czy
>> przeiterować 100 razy w bazie i w sieć puścić tylko wynik.
>
> I jak masz 100 takich klientów, to ten ostatni sobie poczeka na wyniki
> tydzień, bo maszyna nie ogarnie.
Albo nie poczeka, bo serwer już dawno to zrobił i ma gotowy wynik w
buforze i jak trzeci klient zapyta o to samo, to mu wyśle gotowca.
Setnemu też.
Ten setny sto razy dłużej poczeka, gdy serwer będzie musiał wysłać do
100 klientów po 50 tys rekordów żeby sobie sami przeliczyli.
>> A nawet przeiterować w bazie raz, zapisać wynik w tabeli tymczasowej i
>> pchać sto razy wynik po jednej iteracji.
>
> Ciągle widzę brak ogarniania koncepcji skalowalności "wszerz".
> Macie wszyscy nawyki pisania aplikacji z 10 userami dziennie,
> czy może aplikacji desktopowych?
Czasem model biznesowy klienta skalowalności wszerz polega na dołożeniu
30 biurka ze sprzedawcą w mieście dalej niż dołożenie dziesiątego
serwera z bazą danych, bo jeden serwer nie wyrabia z pchaniem 15 tys
dokumentów na sekundę do 30 sprzedawców przez vpn po neostradzie albo
przez sieć komórkową, bo akurat handlowiec laptopa odpalił w samochodzie
stojąc na MOPie i chciał sprawdzić stan magazynowy gwoździa 3".
Zamiast powiedzieć klientowi ile ma gwoździ na stanie to wisi na
telefonie i czeka aż mu się tabelka z dokumentami magazynowymi z
ostatnich 4 miesięcy ściągnie do pamięci laptopa i laptop aktualny stan
przeliczy. Świetny pomysł.
>> Jeżeli z bazą łączą się różne aplikacje (np. Księgowość, Magazyn,
>> Sprzedaż itp.), to łatwiej (i bezpieczniej) jest ogarnąć zależności np.
>> między dokumentami w bazie,
>
> Nie. W API. Które jest jedno i tylko ono ma dostęp do bazy.
Oczywiście zgoda.
W świecie idealnym każda aplikacja ma api.
Ba! A nawet api stoi na osobnej maszynie, a serwer bazy w bunkrze.
Co nie zmienia faktu, że przy Twoim podejściu nadal do api musisz
przesłać 100 razy po 15 tys. dokumentów, gdy 100 klientów poprosi o
aktualny stan magazynowy i to api te 100 razy po 15 tys dokumentów musi
przesłać do klientów. Hmmm... to może niech api raz przeliczy stan i
sobie go zapisze... w bazie danych? I tak api przy każdym jednym
INSERT/UPDATE/DELETE jednego dokumentu będzie pobierał wszystkie
dokumenty z bazy i przeliczał i zapisywał w bazie?
W świecie rzeczywistym zdarza się, że api jest instalowane wraz z
aplikacją kliencką, żeby klient który kupił program miał ułatwienie w
pisaniu (czy używaniu) "autorskich" rozszerzeń, a komp z serwerem
bazodanowym stoi w pokoju obok.
Skoro w/g Ciebie serwer bazodanowy nie jest od logiki biznesowej, to api
tym bardziej.
W świecie rzeczywistym zdarza się, że pomimo istnienia api, zlecenie
napisania rozszerzenia/wtyczki przyjmuje ktoś, kto i tak "wie lepiej" i
łączy się do bazy bezpośrednio, bo szef dał mu hasło.
Dlatego wymyślono opcję "encrypt stored procedure", żeby w razie takiego
zachowania maksymalnie zmniejszyć niepożądane skutki. Jak będzie chciał
coś grzebnąć w bazie bezpośrednio z SQL Management Studio, to nawet nie
usunie rekordu powiązanego logicznie (biznesowo) z innym rekordem.
A nawet jak mu się uda jakimś cudem usunąć np. WZ, to procedura zadba o
to, żeby uaktualnić stan magazynowy.
>> niż w poszczególnych aplikacjach. Im więcej różnych aplikacji/modułów
>> tym większa szansa, że w którejś z nich będzie błąd i spowoduje
>> rozsypanie zależności.
>
> Od logiki biznesowej to jest JEDNA aplikacja, względnie zestaw niezależnych
> aplikacji (mikroserwisów) realizujących swoje indywidualne (niezależne) funkcjonalności.
Przecież napisałem, że może być wiele...
W jaki sposób ma to zagwarantować integralność danych w bazie?
> Wystawia się kontrakt, interfejs, dokumentację, walidację i odpowiada za
> realizację. A nie pół dupy zza krzaka, część w triggerach, część w aplikacji
> (tej której się triggerami nie da), a część bóg wie gdzie.
W świecie idealnym pewnie tak jest.
W prawdziwym świecie niektóre aplikacje żyją, rozwijają się i ewoluują
latami wraz ze zmianami, które były nie do przewidzenia na etapie
projektowania ileś lat wcześniej, nie wspominając o możliwościach
ówczesnych serwerów bazodanowych czy infrastruktury.
Są też takie aplikacje, gdzie zdecydowanie lepiej i bezpieczniej jest
zapewnić integralność danych na poziomie bazy danych niż w aplikacji, bo
z serwerem bazy danych ktoś może połączyć się nie tylko dedykowaną
aplikacją czy przez api.
> Aplikacje o których mówiłeś, łączą się do konkretnych usług które potrzebują
> (jeśli mówimy o architekturze mikroserwisów), albo do jednej aplikacji (jak
> o architekturze monolitycznej) i to one pilnują swojego subsetu reguł.
> A nie jakiś kryptyczny kod w bazie.
Aplikacje o których mówiłem łączą się z serwerem bazy danych.
Zapewne masz na myśli jakieś inne aplikacje.
> Dzięki temu masz i większe bezpieczeństwo i większą możliwość fragmentacji,
> skalowania, wydzielania, zabezpieczania (dawanie wielu aplikacjom dostępu
> do bazy to jakaś masakra, jak chces zprojektować np. aplikacje mobilne w
> takim trybie) i większą skalowalność. Wyobrażasz sobie takie API facebooka
> realizowane z dostępem "na bazie"?
Nie, nie wyobrażam sobie takiego API facebooka.
Nie samym facebukiem świat żyje.
> Takie grzebanie po bazie to mi się wydaje charakterystyczne dla aplikacji
> księgowych na Windowsa,
Świat się nie kończy na wtyczce do internetu.
> które instalowały na desktopie bazę, nie udostępniały
> API, a wszelkie inne programy "wdrażane" wymagały specjalistów od modyfikacji
> tejże bazy. Koszmarek.
Zaskoczę Cię, są też takie, gdzie serwer bazy danych stoi na osobnym
sprzęcie i mają api.
Co nie zmienia faktu, że zapewnianie integralności logicznej
dokumentów/wpisów w bazie z poziomu aplikacji klienckich to pomysł co
najmniej średni.
>> Dodatkowo, jeżeli potrzebna jest jakaś zmiana, to zmianę wykonujesz w
>> jednym miejscu, w bazie, a nie we wszystkich aplikacjach klienckich.
>
> No chyba że zmiana jest niekompatybilna
No chyba, że zmiana jest kompatybilna i nie musisz zmieniać wszystkich
aplikacji klienckich.
>i wtedy trzeba wszysktie aplikacje
> klienckie aktualizować, bo baza nie umożliwia porządnego wersjonowania.
A co przeszkadza w wersjonowaniu skryptów migracyjnych?
Są też pomocne narzędzia:
https://docs.microsoft.com/en-us/sql/ssdt/how-to-use-schema-compare-to-compare-different-database-definitions?view=sql-server-2017
"The results of the comparison appear as a set of actions that must be
taken with the target to make it the same as the source. Once the
comparison is complete you can update the target directly (if the target
is a project or a database) or generate an update script that has the
same effect.
The differences between source and target appear in a grid for easy
review. You can drill into and review each difference in the results
grid or in script form. You can then selectively exclude specific
differences.
You can save comparisons either as part of a SQL Server Database project
or as a standalone file. You can also set options that control the scope
of the comparison and aspects of the update. Then you can save the
comparison so that you can easily repeat the same comparison later or
use it as the starting point for new comparison."
> [...]
>
>> To tak w skrócie i na szybko, że jednak triggery i procedury składowane
>> czasem się przydają.
>
> Błędne założenia (że dostęp do bazy mają jakieś dziwne aplikacje końcowe,
> to i błędne wnioski.
Błędne założenie, że nie istnieją aplikacje końcowe z dostępem do bazy,
prowadzą do błędnych wniosków, że triggery i procedury składowane nie są
w bazie danych potrzebne. A już stwierdzenie, że są złe bo się ich
gdzieśtam nie używa jest co najmniej dziwne.
Pozdrawiam
Piotr