Skalowalność polega na przetwarzaniu wstępnym (buforowaniu), rozkładaniu lub ograniczaniu powtarzającej się pracy do podstawowych elementów, aby zminimalizować wykorzystanie zasobów na jednostkę pracy. Aby dobrze skalować, nie robisz niczego, czego nie potrzebujesz, a rzeczy, które faktycznie robisz, robisz tak wydajnie, jak to tylko możliwe.
W tym kontekście, oczywiście, łączenie dwóch oddzielnych źródeł danych jest stosunkowo wolne, przynajmniej w porównaniu z nie dołączaniem do nich, ponieważ jest to praca, którą musisz wykonać na żywo w miejscu, w którym użytkownik o to poprosi.
Pamiętaj jednak, że alternatywą nie jest już posiadanie w ogóle dwóch oddzielnych części danych; musisz umieścić dwa różne punkty danych w tym samym rekordzie. Nie możesz łączyć dwóch różnych danych gdzieś bez konsekwencji, więc upewnij się, że rozumiesz kompromis.
Dobra wiadomość jest taka, że nowoczesne relacyjne bazy danych są dobre w połączeniach. Naprawdę nie powinieneś myśleć o złączeniach jako wolnych, z dobrą bazą danych używaną dobrze. Istnieje szereg skalowalności przyjaznych sposobów, aby surowo łączy i uczynić je znacznie szybciej:
- Łączenie na podstawie klucza zastępczego (kolumny autonumeru / tożsamości) zamiast klucza naturalnego. Oznacza to mniejsze (a zatem szybsze) porównania podczas operacji łączenia
- Indeksy
- Widoki zmaterializowane / zindeksowane (pomyśl o tym jako o wstępnie obliczonym złączeniu lub zarządzanej denormalizacji)
- Obliczone kolumny. Możesz użyć tego do haszowania lub w inny sposób wstępnie obliczać kolumny kluczy złączenia, tak że to, co byłoby skomplikowanym porównaniem dla złączenia, jest teraz znacznie mniejsze i potencjalnie wstępnie zindeksowane.
- Partycje tabelaryczne (pomaga w przypadku dużych zestawów danych, rozkładając obciążenie na wiele dysków lub ograniczając to, co mogło być skanowaniem tabeli do skanowania partycji)
- OLAP (wstępnie oblicza wyniki niektórych rodzajów zapytań / złączeń. To nie do końca prawda, ale można to potraktować jako ogólną denormalizację)
- Replikacja, grupy dostępności, wysyłanie dzienników lub inne mechanizmy umożliwiające wielu serwerom odpowiadanie na zapytania dotyczące odczytu dla tej samej bazy danych, a tym samym skalowanie obciążenia pracą na kilka serwerów.
- Użycie warstwy buforującej, takiej jak Redis, aby uniknąć ponownego uruchamiania zapytań, które wymagają skomplikowanych sprzężeń.
Powiedziałbym nawet, że głównym powodem istnienia relacyjnych baz danych jest umożliwienie wydajnego łączenia się * . Z pewnością nie chodzi tylko o przechowywanie ustrukturyzowanych danych (możesz to zrobić za pomocą płaskich konstrukcji plików, takich jak csv lub xml). Kilka opcji, które wymieniłem, pozwoli ci nawet całkowicie zbudować połączenie z wyprzedzeniem, więc wyniki są już zrobione przed wysłaniem zapytania - tak jakbyś zdenormalizował dane (wprawdzie kosztem wolniejszych operacji zapisu).
Jeśli masz powolne sprzężenie, prawdopodobnie nie używasz poprawnie bazy danych.
De-normalizacja powinna być przeprowadzona tylko wtedy, gdy zawiodły te inne techniki. Jedynym sposobem, w jaki możesz naprawdę ocenić „porażkę”, jest wyznaczenie znaczących celów wydajnościowych i ich porównanie. Jeśli nie mierzyłeś, jest za wcześnie, aby nawet pomyśleć o denormalizacji.
* Oznacza to, że istnieją jako jednostki odrębne od zwykłych zbiorów tabel. Dodatkowym powodem prawdziwego rdbms jest bezpieczny, jednoczesny dostęp.
Łączenia mogą być wolniejsze niż unikanie ich poprzez denormalizację, ale jeśli są używane poprawnie (łączenie na kolumnach z odpowiednimi indeksami i tak dalej), nie są z natury powolne .
De-normalizacja to jedna z wielu technik optymalizacji, które można rozważyć, jeśli dobrze zaprojektowany schemat bazy danych wykazuje problemy z wydajnością.
źródło
artykuł mówi, że są powolne w porównaniu z brakiem połączeń. można to osiągnąć poprzez denormalizację. więc istnieje kompromis między szybkością a normalizacją. nie zapomnij też o przedwczesnej optymalizacji :)
źródło
Po pierwsze, racją bytu (powodem istnienia) relacyjnej bazy danych jest możliwość modelowania relacji między podmiotami. Połączenia to po prostu mechanizmy, dzięki którym przechodzimy przez te relacje. Z pewnością mają one symboliczny koszt, ale bez łączeń naprawdę nie ma powodu, aby mieć relacyjną bazę danych.
W świecie akademickim uczymy się o różnych formach normalnych (1., 2., 3., Boyce-Codd, itp.), Oraz o różnych typach kluczy (podstawowych, obcych, alternatywnych, unikalnych itp.) te rzeczy pasują do siebie, aby zaprojektować bazę danych. Uczymy się podstaw SQL, a także manipulowania strukturą i danymi (DDL i DML).
W świecie korporacji wiele konstruktów akademickich okazuje się być znacznie mniej wykonalnych, niż sądzono. Doskonałym przykładem jest pojęcie klucza podstawowego. Z naukowego punktu widzenia to właśnie ten atrybut (lub zbiór atrybutów) jednoznacznie identyfikuje jeden wiersz w tabeli. Tak więc w wielu dziedzinach problemowych właściwy akademicki klucz główny jest złożeniem 3 lub 4 atrybutów. Jednak prawie wszyscy we współczesnym świecie korporacji używają automatycznie generowanej, sekwencyjnej liczby całkowitej jako klucza podstawowego tabeli. Czemu? Dwa powody. Po pierwsze, sprawia, że model jest znacznie czystszy podczas migracji elementów FK w różne miejsca. Drugim i najbardziej związanym z tym pytaniem jest to, że pobieranie danych przez łączenia jest szybsze i bardziej wydajne na pojedynczej liczbie całkowitej niż na 4 kolumnach varchar (jak już wspomniało kilka osób).
Zagłębmy się teraz nieco głębiej w dwa specyficzne podtypy rzeczywistych baz danych. Pierwszy typ to baza transakcyjna. To podstawa wielu aplikacji do handlu elektronicznego lub zarządzania treścią, napędzających nowoczesne witryny. Z bazą danych transakcji mocno optymalizujesz w kierunku „przepustowości transakcji”. Większość aplikacji handlowych lub związanych z treścią musi równoważyć wydajność zapytań (z niektórych tabel) z wydajnością wstawiania (w innych tabelach), chociaż każda aplikacja będzie miała własne, unikalne problemy biznesowe do rozwiązania.
Drugi typ rzeczywistej bazy danych to baza danych raportowania. Są one wykorzystywane prawie wyłącznie do agregowania danych biznesowych i generowania sensownych raportów biznesowych. Zazwyczaj mają inny kształt niż bazy danych transakcji, w których generowane są dane, i są wysoce zoptymalizowane pod kątem szybkości ładowania danych zbiorczych (ETL) i wydajności zapytań z dużymi lub złożonymi zestawami danych.
W każdym przypadku programista lub administrator danych musi dokładnie zrównoważyć zarówno funkcjonalność, jak i krzywe wydajności, a po obu stronach równania istnieje wiele sztuczek zwiększających wydajność. W Oracle można wykonać tak zwany „plan wyjaśniania”, dzięki czemu można dokładnie zobaczyć, w jaki sposób zapytanie jest analizowane i wykonywane. Chcesz zmaksymalizować prawidłowe wykorzystanie indeksów przez bazę danych. Naprawdę nieprzyjemnym nie-nie jest umieszczenie funkcji w klauzuli where zapytania. Kiedykolwiek to zrobisz, gwarantujesz, że Oracle nie użyje żadnych indeksów w tej konkretnej kolumnie i prawdopodobnie zobaczysz pełne lub częściowe skanowanie tabeli w planie wyjaśniania. To tylko jeden konkretny przykład tego, jak można napisać zapytanie, które kończy się powolnością i nie ma nic wspólnego z łączeniami.
A skoro mówimy o skanach tabel, oczywiście wpływają one na szybkość zapytań proporcjonalnie do rozmiaru tabeli. Pełne skanowanie 100 wierszy tabeli nie jest nawet zauważalne. Uruchom to samo zapytanie na tabeli zawierającej 100 milionów wierszy, a po powrocie musisz wrócić w przyszłym tygodniu.
Porozmawiajmy przez chwilę o normalizacji. To kolejny bardzo pozytywny temat akademicki, który może być nadmiernie zestresowany. W większości przypadków, gdy mówimy o normalizacji, tak naprawdę mamy na myśli eliminację zduplikowanych danych poprzez umieszczenie ich we własnej tabeli i migrację FK. Ludzie zwykle pomijają całą zależność opisaną przez 2NF i 3NF. A jednak w skrajnym przypadku z pewnością możliwe jest posiadanie doskonałej bazy danych BCNF, która jest ogromna i kompletna bestia do pisania kodu, ponieważ jest tak znormalizowana.
Więc gdzie balansujemy? Nie ma jednej najlepszej odpowiedzi. Wszystkie lepsze odpowiedzi są zwykle kompromisem między łatwością utrzymania struktury, łatwością obsługi danych i łatwością tworzenia / konserwacji kodu. Ogólnie rzecz biorąc, im mniej duplikatów danych, tym lepiej.
Dlaczego więc łączenia są czasami powolne? Czasami jest to zły projekt relacji. Czasami jest to nieefektywne indeksowanie. Czasami jest to problem z ilością danych. Czasami jest to okropnie napisane zapytanie.
Przepraszam za tak rozwlekłą odpowiedź, ale czułem się zmuszony do podania bardziej mięsistego kontekstu wokół moich komentarzy, zamiast po prostu wyrzucać 4-punktową odpowiedź.
źródło
Osoby z bazami danych o wielkości terabajtów nadal używają złączeń, jeśli mogą zmusić je do pracy pod względem wydajności, to Ty też możesz.
Istnieje wiele powodów, dla których nie należy denomalizować. Po pierwsze, szybkość wybierania zapytań nie jest jedynym, ani nawet głównym problemem związanym z bazami danych. Integralność danych jest najważniejsza. Jeśli zdenormalizujesz, musisz zastosować techniki, które pozwolą zachować denormalizację danych, gdy zmieniają się dane nadrzędne. Więc przypuśćmy, że zaczynasz przechowywać nazwę klienta we wszystkich tabelach, zamiast łączyć się z tabelą klienta w client_Id. Teraz, gdy zmieni się nazwa klienta (100% szansa, że niektóre nazwy klientów zmienią się w czasie), teraz musisz zaktualizować wszystkie rekordy podrzędne, aby odzwierciedlić tę zmianę. Jeśli zrobisz to za pomocą kaskadowej aktualizacji i masz milion rekordów podrzędnych, jak myślisz, jak szybko to nastąpi i ilu użytkowników będzie cierpieć z powodu problemów z blokowaniem i opóźnień w ich pracy, gdy to nastąpi? Ponadto większość ludzi denormalizuje się, ponieważ „
Denormalizacja to złożony proces, który wymaga dogłębnego zrozumienia wydajności i integralności bazy danych, jeśli ma być wykonany poprawnie. Nie próbuj denormalizować, jeśli nie masz takiej wiedzy na temat personelu.
Połączenia są dość szybkie, jeśli robisz kilka rzeczy. Najpierw użyj klucza suggorgate, złączenie int jest prawie zawsze najszybszym złączeniem. Po drugie zawsze indeksuj klucz obcy. Użyj tabel pochodnych lub warunków łączenia, aby utworzyć mniejszy zestaw danych do filtrowania. Jeśli masz dużą, bardzo złożoną bazę danych, zatrudnij profesjonalną osobę z doświadczeniem w dzieleniu na partycje i zarządzaniu dużymi bazami danych. Istnieje wiele technik poprawiających wydajność bez usuwania połączeń.
Jeśli potrzebujesz tylko możliwości zapytań, to tak, możesz zaprojektować magazyn danych, który można zdenormalizować i który jest wypełniany za pomocą narzędzia ETL (zoptymalizowanego pod kątem szybkości), a nie wprowadzania danych użytkownika.
źródło
Połączenia są powolne, jeśli
Tak więc, to prawda, im większe są twoje dane, tym więcej przetwarzania potrzebujesz do zapytania, ale sprawdzenie i praca nad pierwszymi trzema opcjami powyżej często daje świetne wyniki.
Twoje źródło daje możliwość denormalizacji. Jest to w porządku tylko wtedy, gdy wyczerpałeś lepsze alternatywy.
źródło
Łączenia mogą być powolne, jeśli trzeba przeskanować duże porcje rekordów z każdej strony.
Lubię to:
SELECT SUM(transaction) FROM customers JOIN accounts ON account_customer = customer_id
Nawet jeśli indeks jest zdefiniowany
account_customer
, wszystkie rekordy z tego ostatniego nadal wymagają przeskanowania.W przypadku listy zapytań przyzwoite optymalizatory prawdopodobnie nawet nie rozważą ścieżki dostępu do indeksu, wykonując zamiast tego a
HASH JOIN
lubMERGE JOIN
a.Zauważ, że w przypadku takiego zapytania:
SELECT SUM(transaction) FROM customers JOIN accounts ON account_customer = customer_id WHERE customer_last_name = 'Stellphlug'
łączenie najprawdopodobniej będzie szybkie: najpierw indeks włączony
customer_last_name
zostanie użyty do odfiltrowania wszystkich Stellphlugów (których oczywiście nie ma zbyt wielu), a następnie skan indeksuaccount_customer
zostanie wykonany dla każdego Stellphluga w celu znalezienia jego transakcji.Pomimo faktu, że mogą to być miliardy rekordów
accounts
icustomers
, tylko nieliczne będą wymagały zeskanowania.źródło
accounts(account_customer)
większości systemów RDBMS, będzie on używał tego indeksu do ustalenia, które dokładnie wierszecustomers
bazy danych wymagają przeskanowania.HASH JOIN
byłby znacznie szybszy, więc będzie to, co będzie używane z wyjątkiem wszystkich głównych baz danych, z wyjątkiem tychMySQL
, które będą po prostu powodowaćcustomers
wprowadzanie w zagnieżdżonej pętli (ponieważ jest mniejszy)Joins are fast.
Łączenia należy traktować jako standardową praktykę z odpowiednio znormalizowanym schematem bazy danych. Połączenia umożliwiają łączenie różnych grup danych w znaczący sposób. Nie bój się połączenia.Zastrzeżenie polega na tym, że musisz zrozumieć normalizację, łączenie i prawidłowe użycie indeksów.
Uważaj na przedwczesną optymalizację, ponieważ najważniejszym niepowodzeniem wszystkich projektów deweloperskich jest dotrzymanie terminu. Po ukończeniu projektu i zrozumieniu kompromisów możesz złamać zasady, jeśli możesz to uzasadnić.
Prawdą jest, że wydajność łączenia spada nieliniowo wraz ze wzrostem rozmiaru zbioru danych. Dlatego nie skaluje się tak dobrze, jak zapytania w pojedynczej tabeli, ale nadal skaluje.
Prawdą jest również, że ptak leci szybciej bez skrzydeł, ale tylko prosto w dół.
źródło
Łączenia wymagają dodatkowego przetwarzania, ponieważ muszą przeszukiwać więcej plików i więcej indeksów, aby „połączyć” dane. Jednak „bardzo duże zbiory danych” są względne. Jaka jest definicja dużego? W przypadku JOIN, myślę, że jest to odniesienie do dużego zbioru wyników, a nie do ogólnego zbioru danych.
Większość baz danych może bardzo szybko przetworzyć zapytanie, które wybiera 5 rekordów z tabeli podstawowej i łączy 5 rekordów z powiązanej tabeli dla każdego rekordu (zakładając, że istnieją prawidłowe indeksy). Każda z tych tabel może mieć setki milionów rekordów, a nawet miliardy.
Gdy zestaw wyników zacznie się powiększać, sytuacja ulegnie spowolnieniu. Posługując się tym samym przykładem, jeśli wynik z tabeli podstawowej wynosi 100 tys. Rekordów, trzeba będzie znaleźć 500 tys. „Połączonych” rekordów. Po prostu wyciągam tyle danych z bazy danych z dodatkowymi opóźnieniami.
Nie unikaj POŁĄCZEŃ, po prostu wiedz, że może zajść potrzeba optymalizacji / denormalizacji, gdy zbiory danych staną się „bardzo duże”.
źródło
Również z cytowanego artykułu:
i
i
Artykuł omawia mega-strony, takie jak Ebay. Na tym poziomie użytkowania prawdopodobnie będziesz musiał rozważyć coś innego niż zwykłe zarządzanie relacyjnymi bazami danych. Jednak w „normalnym” toku działalności (aplikacje z tysiącami użytkowników i milionami rekordów) te droższe, bardziej podatne na błędy podejścia są przesadą.
źródło
Połączenia są uważane za siłę przeciwstawną do skalowalności, ponieważ zwykle stanowią wąskie gardło i nie można ich łatwo dystrybuować ani równolegle.
źródło
Prawidłowo zaprojektowane tabele zawierające odpowiednie wskazania i poprawnie napisane zapytania nie zawsze są powolne. Gdziekolwiek to słyszałeś:
nie ma pojęcia, o czym mówią !!! Większość połączeń będzie bardzo szybkich. Jeśli musisz połączyć wiele wierszy jednocześnie, możesz przyjąć trafienie w porównaniu ze zdenormalizowaną tabelą, ale to wraca do Prawidłowo zaprojektowanych tabel, wiedz, kiedy denormalizować, a kiedy nie. w ciężkim systemie raportowania podziel dane w zdenormalizowanych tabelach na potrzeby raportów, a nawet utwórz hurtownię danych. W ciężkim systemie transakcyjnym normalizuj tabele.
źródło
Ilość generowanych danych tymczasowych może być ogromna w przypadku łączenia.
Na przykład jedna baza danych tutaj w pracy miała ogólną funkcję wyszukiwania, w której wszystkie pola były opcjonalne. Procedura wyszukiwania połączyła się na każdym stole przed rozpoczęciem wyszukiwania. Na początku działało to dobrze. Ale teraz, gdy główna tabela ma ponad 10 milionów wierszy ... nie tak bardzo. Wyszukiwanie trwa teraz co najmniej 30 minut.
Otrzymałem zadanie optymalizacji procedury składowanej wyszukiwania.
Pierwszą rzeczą, jaką zrobiłem, było to, że jeśli którekolwiek z pól tabeli głównej były przeszukiwane, wybrałem tabelę tymczasową tylko na tych polach. WTEDY dołączyłem do wszystkich stołów z tym stołem tymczasowym przed wykonaniem pozostałej części wyszukiwania. Wyszukiwanie miejsc, w których jedno z głównych pól tabeli zajmuje teraz mniej niż 10 sekund.
Jeśli żadne z pól głównej tabeli nie jest rozpoczęte, wykonuję podobne optymalizacje dla innych tabel. Kiedy skończyłem, żadne wyszukiwanie nie trwa dłużej niż 30 sekund, a większość ma mniej niż 10 lat.
Wykorzystanie procesora przez serwer SQL również spadło.
źródło
Podczas gdy sprzężenia (prawdopodobnie ze względu na znormalizowany projekt) mogą oczywiście być wolniejsze w przypadku pobierania danych niż odczyt z pojedynczej tabeli, zdenormalizowana baza danych może być wolna w przypadku operacji tworzenia / aktualizacji danych, ponieważ ślad całej transakcji nie będzie minimalny.
W znormalizowanej bazie danych część danych będzie znajdować się tylko w jednym miejscu, więc ślad dla aktualizacji będzie jak najmniejszy. W zdenormalizowanej bazie danych możliwe jest, że ta sama kolumna w wielu wierszach lub między tabelami będzie musiała zostać zaktualizowana, co oznacza, że ślad byłby większy, a ryzyko blokad i zakleszczeń może wzrosnąć.
źródło
Cóż, tak, wybieranie wierszy z jednej zdenormalizowanej tabeli (zakładając przyzwoite indeksy dla zapytania) może być szybsze niż wybieranie wierszy utworzonych z łączenia kilku tabel, szczególnie jeśli łączenia nie mają dostępnych wydajnych indeksów.
Przykłady przytoczone w artykule - Flickr i eBay - to wyjątkowe przypadki IMO, więc miej (i zasługują) na wyjątkowe odpowiedzi. Autor szczególnie zwraca uwagę na brak RI i zakres powielania danych w artykule.
Większość aplikacji - znowu IMO - korzysta z walidacji i ograniczonego powielania zapewnianego przez RDBMS.
źródło
Mogą być powolne, jeśli są wykonywane niechlujnie. Na przykład, jeśli wykonasz 'select *' na złączeniu, prawdopodobnie zajmie trochę czasu, aby odzyskać rzeczy. Jeśli jednak uważnie wybierzesz, które kolumny mają zostać zwrócone z każdej tabeli, i przy odpowiednich indeksach, nie powinno być problemu.
źródło