Czy posiadanie funkcjonalności w DB jest przeszkodą dla skalowalności?

17

Mogę nie być w stanie podać właściwego tytułu pytania. Ale oto jest

Rozwijamy portal finansowy do zarządzania majątkiem. Oczekujemy, że z aplikacji skorzysta ponad 10000 klientów. Portal oblicza różne analizy wydajności na podstawie analizy technicznej rynku akcji.

Wiele funkcji opracowaliśmy za pomocą procedur przechowywanych, funkcji zdefiniowanych przez użytkownika, wyzwalaczy itp. Za pośrednictwem bazy danych. Pomyśleliśmy, że możemy uzyskać ogromny wzrost wydajności, robiąc rzeczy bezpośrednio w bazie danych niż za pomocą kodu C #. I rzeczywiście uzyskaliśmy ogromny wzrost wydajności.

Kiedy próbowałem pochwalić się osiągnięciem naszego CTO, przeciwdziałał mojej decyzji o wdrożeniu funkcjonalności w bazie danych, a nie w kodzie. Według niego takie aplikacje mają problemy ze skalowalnością. Jego słowa „W dzisiejszych czasach rzeczy są przechowywane w pamięci / pamięci podręcznej. Z czasem dane klastrowe są trudne do zarządzania. Facebook, Google nie mają nic w bazie danych. To era cienkich serwerów i grubych klientów. DB służy tylko do przechowywania zwykłych danych a funkcjonalność powinna być całkowicie oddzielona od bazy danych ”.

Czy możecie mi zasugerować, czy to, co mówi, jest słuszne? Jak zająć się architektem takiej aplikacji?

Estefany Velez
źródło
3
„i rzeczywiście uzyskaliśmy ogromny wzrost wydajności” w porównaniu do czego? Skąd wiesz, kiedy nigdy nie wdrożyłeś tej samej funkcjonalności na kliencie?
Doc Brown,
3
Myślę, że będzie to normalne - zależy to od projektu, wdrożenia danych i umiejętności zespołu.
Daniel Iankov,
1
Powinieneś zapytać swojego CTO, co sprawia, że ​​według niego bazy danych nie wykorzystują jego ulubionych technik i dlaczego procedury przechowywane nie kwalifikują się jako „kod”.
Blrfl,
3
Facebook i Google mają problemy w zupełnie innej skali niż większość aplikacji - może występować problem z ilością danych, z którymi musisz sobie poradzić, jeśli chodzi o dane z rynku, ale współczesne bazy danych SQL są zbudowane tak, aby poradzić sobie z olbrzymią ilością danych.
Murph,
1
Prawdopodobnie pomyślałbym tak samo jak twój CTO, chyba że udowodnisz, że jego rozwiązanie było niewystarczające i nie było innych sposobów na zarządzanie nim. Procedury składowane, zwłaszcza gdy ich liczba staje się duża, powodują, że ogromna bariera przenosi się na inne bazy danych, jeśli jest to wymagane ... nie może przewidzieć przyszłości.
Przypon

Odpowiedzi:

23

Krótko mówiąc, zgodziłbym się z twoim CTO. Prawdopodobnie osiągnąłeś pewną wydajność kosztem skalowalności (jeśli te warunki są mylące, wyjaśnię poniżej). Moimi dwoma największymi obawami byłyby łatwość konserwacji i brak opcji skalowania w poziomie (zakładając, że będziesz tego potrzebować).

Odległość od danych: cofnijmy się o krok. Istnieje kilka dobrych powodów, aby wypychać kod do bazy danych. Argumentowałbym, że największym z nich jest bliskość danych - na przykład, jeśli spodziewasz się, że obliczenia zwrócą garść wartości, ale są to agregacje milionów rekordów, wysyłające miliony rekordów (na żądanie) ponad sieć, która ma być agregowana w innym miejscu, jest ogromnie marnotrawstwem i może łatwo zabić twój system. Powiedziawszy to, możesz osiągnąć tę bliskość danych na inne sposoby, zasadniczo używając pamięci podręcznej lub baz danych analizy, w których część agregacji jest wykonywana z góry.

Wydajność kodu w DB:Wtórne efekty wydajności, takie jak „buforowanie planów wykonania” są trudniejsze do argumentowania. Czasami buforowane plany wykonania mogą być bardzo negatywne, jeśli buforowany został niewłaściwy plan wykonania. W zależności od RDBMS możesz uzyskać jak najwięcej z nich, ale w większości przypadków nie uzyskasz dużo więcej niż sparametryzowany SQL (te plany również zwykle są buforowane). Argumentowałbym również, że większość skompilowanych lub JIT'owanych języków zazwyczaj działa lepiej niż ich odpowiedniki SQL (takie jak T-SQL lub PL / SQL) w podstawowych operacjach i programowaniu nierelacyjnym (manipulacja ciągami, pętle itp.), Więc nie nic tam nie stracisz, jeśli użyjesz czegoś takiego jak Java lub C #, aby skrócić liczbę. Drobnoziarnista optymalizacja jest również dość trudna - w DB możesz „ często utknąłem z ogólnym B-drzewem (indeksem) jako jedyną strukturą danych. Szczerze mówiąc, pełna analiza, w tym takie jak dłuższe transakcje, eskalacja blokady itp., Może wypełnić książki.

Konserwowalność: SQL jest wspaniałym językiem do tego, do czego został zaprojektowany. Nie jestem pewien, czy świetnie pasuje do logiki aplikacji. Większość narzędzi i praktyk, które czynią nasze życie znośnym (TDD, refaktoryzacja itp.), Jest trudna do zastosowania w programowaniu baz danych.

Wydajność a skalowalność:Aby wyjaśnić te warunki, mam na myśli to: wydajność to szybkość, z jaką można oczekiwać, że jedno żądanie przejdzie przez system (i wróci do użytkownika), na chwilę przy założeniu niskiego obciążenia. Będzie to często ograniczone przez takie rzeczy, jak liczba warstw fizycznych, przez które przechodzi, jak dobrze zoptymalizowane są te warstwy itp. Skalowalność to zmiana wydajności wraz ze wzrostem liczby użytkowników / obciążenia. Możesz mieć średnią / niską wydajność (powiedzmy 5 sekund + na żądanie), ale niesamowitą skalowalność (w stanie obsłużyć miliony użytkowników). W twoim przypadku prawdopodobnie osiągniesz dobrą wydajność, ale twoja skalowalność będzie ograniczona przez to, jak duży serwer możesz fizycznie zbudować. W pewnym momencie przekroczysz ten limit i będziesz zmuszony przejść do takich rzeczy, jak sharding, co może nie być możliwe w zależności od charakteru aplikacji.

Przedwczesna optymalizacja: myślę, że popełniłeś błąd, optymalizując przedwcześnie. Jak zauważyli inni, tak naprawdę nie ma pomiarów pokazujących, jak działałyby inne podejścia. Cóż, nie zawsze możemy zbudować prototypy w pełnej skali, aby udowodnić lub obalić teorię ... Ale ogólnie zawsze wahałbym się przed wyborem podejścia, które wymienia łatwość utrzymania (prawdopodobnie najważniejszą jakość aplikacji) w zakresie wydajności .

EDYCJA: Z pozytywnego punktu widzenia, pionowe skalowanie może rozciągać się dość daleko w niektórych przypadkach. O ile mi wiadomo, SO działało na jednym serwerze przez dłuższy czas. Nie jestem pewien, jak pasuje do twoich 10 000 użytkowników (wydaje mi się, że będzie to zależeć od charakteru tego, co robią w twoim systemie), ale daje ci wyobrażenie o tym, co można zrobić (w rzeczywistości są daleko bardziej imponujące przykłady, jest to po prostu popularny, który ludzie mogą łatwo zrozumieć).

EDYCJA 2: Aby wyjaśnić i skomentować kilka kwestii poruszonych w innym miejscu:

  • Re: Spójność atomowa - Spójność ACID może być wymogiem systemu. Powyższe tak naprawdę nie przemawia przeciwko temu i powinieneś zdawać sobie sprawę, że spójność ACID nie wymaga od ciebie uruchamiania całej logiki biznesowej w bazie danych. Przesuwając kod, który tego nie robi musi tam być, do bazy danych, ograniczasz go do działania w środowisku fizycznym reszty bazy danych - konkuruje on o te same zasoby sprzętowe, co rzeczywista część bazy danych w zarządzaniu danymi. Jeśli chodzi o skalowanie tylko kodu na inne serwery DB (ale nie rzeczywiste dane) - jasne, może to być możliwe , ale co dokładnie zyskujesz, oprócz dodatkowych kosztów licencji w większości przypadków? Trzymaj rzeczy, które nie muszą znajdować się na DB, poza DB.
  • Re: Wydajność SQL / C # - ponieważ wydaje się to być przedmiotem zainteresowania, dodajmy trochę do dyskusji. Z pewnością możesz uruchomić natywny / Java / C # kod w DB, ale o ile mi wiadomo, nie o to tu dyskutowano - porównujemy implementację typowego kodu aplikacji w coś takiego jak T-SQL w porównaniu do czegoś takiego jak C #. Istnieje szereg problemów, które w przeszłości trudno było rozwiązać za pomocą kodu relacyjnego - np. Weź pod uwagę problem „maksymalnej liczby równoczesnych logowań”, w którym masz rekordy wskazujące na logowanie lub wylogowanie oraz czas i musisz ustalić, jakie maksymalna liczba użytkowników zalogowanych jednocześnie. Najprostszym możliwym rozwiązaniem jest iteracja rekordów i ciągłe zwiększanie / zmniejszanie licznika podczas napotkania logowań / wylogowań oraz śledzenie maksymalnej wartości tej wartości.może, Nie wiem), najlepsze, co możesz zrobić, to KURSOR (rozwiązania czysto relacyjne mają różne stopnie złożoności, a próba ich rozwiązania za pomocą pętli while powoduje gorszą wydajność). W tym przypadku tak, rozwiązanie C # jest faktycznie szybsze niż to, co można osiągnąć w T-SQL, kropka. To może wydawać się zbyt daleko idące, ale ten problem może łatwo objawić się w systemach finansowych, jeśli pracujesz z wierszami reprezentującymi zmiany względne i musisz obliczyć na nich agregacje okienkowe. Przechowywane wywołania proc również wydają się być droższe - wywołuj trywialny SP milion razy i zobacz, jak to się ma do wywołania funkcji C #. Podpowiedziałem kilka innych przykładów powyżej - jeszcze nie spotkałem nikogo, kto zaimplementuje prawidłową tablicę skrótów w T-SQL (która faktycznie daje pewne korzyści), podczas gdy jest to dość łatwe w C #. Znów są rzeczy, w których DB są świetne, i rzeczy, w których nie są tak świetne. Tak jak nie chciałbym wykonywać JOIN, SUM i GROUP BY w C #, nie chcę pisać w języku T-SQL nic szczególnie wymagającego pod względem procesora.
Daniel B.
źródło
Jednym z powodów, dla których staram się wypychać funkcjonalność do bazy danych, jest to, że jest mniej wadliwa niż kod na poziomie aplikacji. SQL jest deklaratywny i nie cierpi na wiele problemów związanych z językami imperatywnymi.
wobbily_col 23.03.16
Jeśli chodzi o łatwość konserwacji, korzystanie z narzędzi do konserwacji SQL Server Data Tools jest bardzo proste. W rzeczywistości dla każdej nietrywialnej bazy danych (jednej z więcej niż 5 tabelami) uznałbym to za wymóg.
Jon49,
4

Skalowalność nie ma nic wspólnego z miejscem, w którym znajdują się dane ani z przebiegiem obliczeń. Skalowalność polega na tym, jak zarządzasz globalną współzależnością stanu i danych. Jeśli twoja architektura jest spleciona z różnego rodzaju wzajemnymi zależnościami danych, nie ma znaczenia, gdzie umieścisz kod do transformacji tych danych. Wzajemne zależności zmuszą twoją rękę i zmniejszą wszelkie możliwości skalowania rzeczy. Jeśli z drugiej strony twoje dane są luźno sprzężone i stan globalny jest bardzo niewielki lub nie ma ich wcale, to ponownie nie ma znaczenia, gdzie nastąpi obliczenie. Skalowanie rzeczy będzie znacznie łatwiejsze.

Nie jestem pewien, skąd Twój CTO otrzymuje jego informacje na temat problemów ze skalowalnością, ale z tego, co powiedziałeś, nie brzmi to tak, jakby miał jakiekolwiek rzeczywiste powody, by kwestionować obecną decyzję architektoniczną inną niż trendy w modzie oprogramowania. Opieranie decyzji architektonicznych na takich trendach jest zwykle złym pomysłem.

davidk01
źródło
1
+1 zaScalability is all about how you manage global state and data inter-dependence.
Estefany Velez
2

I rzeczywiście uzyskaliśmy ogromny wzrost wydajności.

Myślę, że musisz najpierw ustanowić test wydajności i zacząć budować swój prototyp. Utrzymywanie całej logiki w DB to stara szkoła (imho, nie mam nic przeciwko temu) radzenie sobie z architekturą klient-serwer. Chociaż ma to swoje zalety, należy wziąć pod uwagę szereg wad.

Typowe podejście do tego typu aplikacji dostępnych do sprzedaży odbywa się za pośrednictwem SOA . Ponieważ na dłuższą metę jest to najłatwiejszy sposób dodawania nowych aplikacji klienckich do projektu.

Wspomniałeś także o wyzwalaczach. Użycie wyzwalacza może okazać się dużym problemem w późniejszym cyklu życia aplikacji, byłbym z nim podwójnie ostrożny, a nawet spróbowałem pominąć jego użycie.

Jusubow
źródło
2

Twój CTO jest w 100% błędny.

Twoje numery finansowe MUSZĄ być sumowane przez cały czas. Oznacza to, że potrzebujesz ACID, a relacyjna baza danych to najlepsze miejsce, aby to zapewnić. Wzrost wydajności NoSql DB odbywa się zwykle kosztem ACID i jest to OK dla Google i Facebook, ALE NIE dla systemu zawierającego finanse.

Mówienie, że C # działa lepiej niż kod SQL, jest także idiotyzmem…

Kretynowie
źródło
Stwierdzenie, że C # działa lepiej niż kod SQL jest także idiotyzmem… - Ale nie zaprzeczasz, że kod C # jest bardziej skalowalny, prawda?
Jim G.
Nie, nie jest bardziej skalowalny, ponieważ nie tam, gdzie jest szyjka butelki, mogę skalować kod Sql (nie dane) poziomo tak łatwo, jak mogę skalować w poziomie kod C #.
Morons
@JimG. Żeby wyjaśnić: „Mogę skalować kod Sql (nie dane) poziomo tak łatwo, jak mogę skalować w poziomie kod C #”, jeśli został zaprojektowany do tego ... Tak samo jak C #, musi być zaprojektowany do skalowania. Nie można po prostu powiedzieć, że C # skaluje się lepiej, to kwestia planowania, a nie języka.
Morons
@JimG .: Oprogramowanie, które nie jest skalowane, może być napisane w dowolnym języku, w tym w języku C #. Każda baza danych warta swojej soli może mieć procedury składowane napisane w językach innych niż ich natywna implementacja SQL-a, a ludzie, którzy idą z daleka od NoSQL w sytuacjach wymagających ACID, zwykle kończą na nowo wynalezienie większości kół, które zostały ładnie realizowane przez DBMS.
Blrfl 30.09.12
@ Morons: Myślę, że się zgadzamy. I był w rzeczywistości utożsamiając dane z „SQL”. Skalowanie bazy danych jest znacznie droższe.
Jim G.
2

Za każdym razem, gdy ktoś wspomina o skalowalności i Google / Facebook / Twitter / itp., Jest to czerwony śledź. O ile nie zapewniasz zasadniczo tej samej usługi, to, co działa dla nich, może nie być dla Ciebie odpowiednie. Ogólnie rzecz biorąc, jeśli można skalować z jednego komputera do klastra z ośmioma komputerami, prawdopodobnie wszystkie bazy zostały pokryte. Jeśli nie masz trudnych wymagań biznesowych, aby codziennie wyświetlać 20 milionów odsłon, nie przejmuj się hiper-skalowaniem. Rób to, co ma sens dla rzeczywistych wymagań aplikacji , i martw się skalowaniem, gdy stanie się oczywiste, że musisz. I nie zapominaj, że większość serwerów baz danych może być również klastrowanych, więc to, że wszystko jest w jednej bazie danych, nie oznacza, że ​​jest na jednym serwerze.

TMN
źródło