Kiedy i dlaczego połączenia z bazami danych są drogie?

Robię badania nad bazami danych i patrzę na pewne ograniczenia relacyjnego DBs.

Dostaję, że łączenie dużych stołów jest bardzo drogie, ale nie jestem do końca pewien, dlaczego. Co musi zrobić DBMS, aby wykonać operację łączenia, gdzie jest wąskie gardło?
W jaki sposób denormalizacja może pomóc przezwyciężyć ten wydatek? Jak pomagają inne techniki optymalizacji (np. indeksowanie)?

Osobiste doświadczenia są mile widziane! Jeśli zamierzasz zamieszczać linki do zasoby, proszę unikać Wikipedii. Już wiem, gdzie to znaleźć.

W związku z tym zastanawiam się nad denormalizowanymi podejściami stosowanymi przez bazy danych usług w chmurze, takie jak BigTable i SimpleDB. Zobacz to pytanie .

Author: Community, 2008-10-06

7 answers

Denormalizacja w celu poprawy wydajności? Brzmi przekonująco, ale nie trzyma wody.

Chris Date, który w towarzystwie Dr Teda Codda był pierwotnym zwolennikiem relacyjnego modelu danych, zabrakło cierpliwości do błędnych argumentów przeciwko normalizacji i systematycznie niszczył je przy użyciu metody naukowej: zdobył duże bazy danych i przetestował te twierdzenia.

Myślę, że napisał to w Relational Database Writings 1988-1991 ale ta książka został później włączony do szóstej edycji Introduction to Database Systems , która jest ostatecznym tekstem na temat teorii i projektowania baz danych, w ósmej edycji, jak piszę i prawdopodobnie pozostanie w druku przez dziesięciolecia nadchodzących. Chris Date był ekspertem w tej dziedzinie, gdy większość z nas wciąż biegała boso.

Stwierdził, że:

  • niektóre z nich posiadają specjalne przypadki
  • Wszystkie nie opłaca się do użytku ogólnego
  • wszystkie z nich są znacznie gorzej dla innych szczególnych przypadków

Wszystko sprowadza się do zmniejszenia rozmiaru zestawu roboczego. Połączenia z odpowiednio dobranymi kluczami z prawidłowo ustawionymi indeksami są tanie, nie drogie, ponieważ pozwalają na znaczne przycinanie wyniku przed wiersze są zmaterializowane.

Zmaterializowanie wyniku wymaga masowych odczytów dysków, które są najdroższym aspektem ćwiczenia o rząd wielkości. Wykonanie połączenia, natomiast logicznie wymaga pobrania tylko kluczy . W praktyce nawet wartości klucza nie są pobierane: wartości skrótu klucza są używane do porównywania połączeń, zmniejszając koszt połączeń wielokolumnowych i radykalnie zmniejszając koszt połączeń obejmujących porównania łańcuchów. Nie tylko znacznie lepiej zmieści się w pamięci podręcznej, ale jest o wiele mniej odczytu dysku.

Co więcej, dobry optymalizator wybierze najbardziej restrykcyjny warunek i zastosuje go przed wykonaniem połączenia, bardzo skutecznie wykorzystując wysoki selektywność połączeń na indeksach o wysokiej kardynalności.

Co prawda ten rodzaj optymalizacji może być również stosowany do denormalizowanych baz danych, ale ludzie, którzy chcą denormalizować schemat, zazwyczaj nie myślą o kardynalności, gdy (jeśli) ustawiają indeksy.

Ważne jest, aby zrozumieć, że skanowanie tabeli (badanie każdego wiersza w tabeli w trakcie tworzenia połączenia) jest rzadkie w praktyce. Optymalizator zapytań wybierze skanowanie tabeli tylko wtedy, gdy jeden lub więcej z następujących chwytów.

  • w relacji jest mniej niż 200 wierszy (w tym przypadku skan będzie tańszy)
  • Nie ma odpowiednich indeksów na kolumnach join (jeśli jest sens join na tych kolumnach, to dlaczego nie są one indeksowane? fix it)
  • przed porównaniem kolumn wymagany jest typ (WTF?! fix it or go home) Zobacz notatki końcowe dla ADO.NET wydanie
  • jednym z argumentów porównania jest wyrażenie (nie indeks)
Wykonanie operacji jest droższe niż jej nie wykonanie. Jednak wykonanie nieprawidłowej operacji , zmuszenie do bezsensownego wejścia/Wyjścia dysku, a następnie odrzucenie żużla przed wykonaniem połączenia, którego naprawdę potrzebujesz, jest znacznie droższe. Nawet jeśli" niewłaściwa " operacja jest wstępnie obliczona, a indeksy zostały rozsądnie zastosowane, pozostaje znacząca kara. Denormalizowanie do precomputera a join-niezależnie od anomalii związanych z aktualizacją-jest zobowiązanie do konkretnego połączenia. Jeśli potrzebujesz innego dołączyć, to zobowiązanie będzie cię kosztowaćduże .

Jeśli ktoś chce mi przypomnieć, że to zmieniający się świat, myślę, że odkryjesz, że większe zbiory danych na sprzęcie gruntier tylko wyolbrzymiają rozprzestrzenianie się ustaleń daty.

Dla wszystkich, którzy pracują na systemach rozliczeniowych lub generatorach śmieci (wstyd wam) i oburzająco ustawiają rękę na klawiaturze, aby mi powiedzieć, że wiecie na pewno, że denormalizacja jest szybsza, przykro mi, ale żyjesz w jednym ze szczególnych przypadków-w szczególności w przypadku, w którym przetwarzasz Wszystkie danych, w kolejności. To nie jest ogólny przypadek, a Ty jesteś uzasadniony w swojej strategii.

Jesteś nie usprawiedliwiony fałszywym uogólnieniem tego. Więcej informacji na temat właściwego wykorzystania denormalizacji w scenariuszach hurtowni danych można znaleźć na końcu sekcji Uwagi.

Chciałbym również odpowiedzieć na

Joins are po prostu produkty kartezjańskie z pewnym błyszczykiem

Co za stek bzdur. Ograniczenia są stosowane tak wcześnie, jak to możliwe, najpierw najbardziej restrykcyjne. Przeczytałeś teorię, ale jej nie zrozumiałeś. Łączniki są traktowane jako "produkty kartezjańskie, do których mają zastosowanie predykaty" tylko przez optymalizator zapytań. Jest to reprezentacja symboliczna (w rzeczywistości normalizacja) w celu ułatwienia rozkładu symbolicznego, aby optymalizator mógł wytworzyć wszystkie równoważne przekształcenia i uszereguj je według kosztów i selektywności, aby mógł wybrać najlepszy plan zapytań.

Jedynym sposobem uzyskania optymalizatora do wytworzenia iloczynu kartezjańskiego jest nie podanie predykatu: SELECT * FROM A,B


Uwagi


David Aldridge podaje kilka ważnych dodatkowych informacji.

Istnieje wiele innych strategii oprócz indeksów i skanowania tabel, a nowoczesny optymalizator będzie kosztował je wszystkie przed opracowaniem planu wykonania.

A praktyczna rada: jeśli może być użyty jako klucz obcy, zindeksuj go tak, aby strategia indeksu była dostępna dla optymalizatora.

Kiedyś byłem mądrzejszy niż MSSQL optimiser. To zmieniło się dwie wersje temu. Teraz ogólnie uczy mnie . Jest to, w bardzo realnym sensie, system ekspercki, kodyfikujący całą mądrość wielu bardzo mądrych ludzi w dziedzinie wystarczająco zamkniętej, aby system oparty na regułach był skuteczny.


"Jaja" mogły być nietaktowne. I jestem proszony o bycie mniej wyniosłym i przypominam, że matematyka nie kłamie. To prawda, ale nie wszystkie implikacje modeli matematycznych powinny być traktowane dosłownie. Pierwiastki kwadratowe liczb ujemnych są bardzo przydatne, jeśli dokładnie unikniesz badania ich absurdu (gra słów) i upewnij się, że je wszystkie anulujesz, zanim spróbujesz zinterpretować swoje równanie.

Powodem, dla którego zareagowałem tak brutalnie, było to, że oświadczenie w sformułowaniu mówi, że

Dołącza produktami kartezjańskimi...

To może nie to, co miało być, ale to to, co zostało napisane i jest kategorycznie nieprawdziwe. Iloczyn kartezjański jest relacją. Połączenie jest funkcją. Mówiąc dokładniej, join jest funkcją o wartości relacyjnej. Z pustym predykatem wytworzy iloczyn kartezjański, a sprawdzanie, czy to robi, jest jednym z sprawdzeń poprawności dla silnika zapytań bazy danych, ale w praktyce nikt nie pisze niezakłóconych łączy, ponieważ nie mają one praktycznej wartości przed klasą.

Nazwałem to, ponieważ nie chcę, aby czytelnicy wpadli w starożytną pułapkę mylenia modelu z rzeczą modelowaną. Model jest przybliżeniem, celowo uproszczonym dla wygodnej manipulacji.


Ograniczenie wyboru strategii łączenia skanowania tabeli może się różnić w zależności od silników bazy danych. Ma to wpływ na szereg decyzji implementacyjnych, takich jak współczynnik wypełnienia drzewa-węzła, rozmiar klucza-wartości i subtelności algorytmu, ale ogólnie speaking high-performance indexing ma czas wykonania k log n + c . Termin C jest ustalonym narzut głównie z czasu konfiguracji, a kształt krzywej oznacza, że nie otrzymasz wypłaty (w porównaniu do wyszukiwania liniowego), dopóki N nie będzie w setkach.


Czasami denormalizacja jest dobrym pomysłem

Denormalizacja jest zobowiązaniem do konkretnej strategii join. Jak wspomniano wcześniej, zakłóca to Inne strategie przyłączenia. Ale jeśli masz wiadra miejsca na dysku, przewidywalne wzorce dostępu i tendencję do przetwarzania wielu lub wszystkich tych danych, wstępne obliczanie połączenia może być bardzo opłacalne.

Możesz również określić ścieżki dostępu, których zazwyczaj używa Twoja operacja, i wstępnie obliczyć wszystkie połączenia dla tych ścieżek dostępu. To jest przesłanka stojąca za hurtowniami danych, a przynajmniej wtedy, gdy są budowane przez ludzi, którzy wiedzą, dlaczego robią to, co robią, a nie tylko ze względu na buzzword zgodność.

Odpowiednio zaprojektowana hurtownia danych jest okresowo wytwarzana przez masową transformację ze znormalizowanego systemu przetwarzania transakcji. Takie rozdzielenie baz danych operacji i raportów ma bardzo pożądany efekt wyeliminowania kolizji między OLTP i OLAP (przetwarzanie transakcji online czyli wprowadzanie danych, a przetwarzanie analityczne online czyli raportowanie).

Ważnym punktem jest to, że oprócz okresowych aktualizacji, hurtownia danych jest Czytaj tylko . To sprawia, że dyskutować kwestię anomalii aktualizacji.

Nie popełniaj błędu denormalizacji swojej bazy danych OLTP (bazy danych, w której dokonuje się wprowadzanie danych). Może to być szybsze w przypadku rozliczeń, ale jeśli to zrobisz, otrzymasz anomalie aktualizacji. Próbowałeś kiedyś przekonać Reader ' s Digest, żeby przestał ci wysyłać rzeczy?

Miejsce na dysku jest tanie w dzisiejszych czasach, więc nie krępuj się. Ale denormalizacja to tylko część historii hurtowni danych. Znacznie większe zyski osiągane są z wstępnie obliczonych wartości zwiniętych: sumy Miesięczne, tego typu rzeczy. To jest zawsze o zmniejszeniu zestawu roboczego.

ADO.NET problem z niedopasowaniem typu

Załóżmy, że masz tabelę SQL Server zawierającą indeksowaną kolumnę typu varchar i używasz AddWithValue do przekazywania parametru ograniczającego zapytanie w tej kolumnie. Ciągi C# są Unicode, więc domyślnym typem parametru będzie NVARCHAR, który nie pasuje do VARCHAR.

VARCHAR do NVARCHAR jest poszerzenie konwersji tak się dzieje bezwarunkowo - ale pożegnaj się z indeksowaniem i powodzenia w ustaleniu dlaczego.


"Count the disk hits" (Rick James)

Jeśli wszystko jest buforowane w pamięci RAM, JOINs są raczej tanie. Oznacza to, że normalizacja nie ma wiele kary wydajności .

Jeśli "znormalizowany" schemat powoduje, że JOINs często uderza w dysk, ale równoważny "znormalizowany" schemat nie musiałby uderzyć w dysk, wtedy denormalizacja wygrywa wydajność konkurencja.

Komentarz od autora oryginału: nowoczesne silniki baz danych są bardzo dobre w organizowaniu sekwencjonowania dostępu w celu zminimalizowania braków pamięci podręcznej podczas operacji łączenia. Powyższe, choć prawdziwe, może być błędnie interpretowane jako sugerujące, że połączenia są koniecznie problematycznie drogie na dużych danych. Prowadziłoby to do słabego podejmowania decyzji przez niedoświadczonych deweloperów.

 428
Author: Peter Wone,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-28 03:17:14

To, co większość komentatorów nie zauważa, to szeroki zakres metod łączenia dostępnych w złożonych RDBMS, a denormalizatory niezmiennie przewyższają wyższe koszty utrzymania denormalizowanych danych. Nie każde połączenie opiera się na indeksach, A bazy danych mają wiele zoptymalizowanych metod i metod łączenia, które mają na celu obniżenie kosztów połączenia.

W każdym przypadku koszt połączenia zależy od jego rodzaju i kilku innych czynników. Wcale nie musi być droga-niektóre przykłady.

  • połączenie hash, w którym dane zbiorcze są równe, jest bardzo tanie, a koszt staje się znaczący tylko wtedy, gdy tabela hash nie może być buforowana w pamięci. Indeks nie jest wymagany. Equi-partycjonowanie między połączonymi zestawami danych może być bardzo pomocne.
  • Koszt połączenia sort-merge zależy od kosztu sortowania, a nie połączenia-metoda dostępu oparta na indeksach może praktycznie wyeliminować koszt sortowania.
  • koszt połączenia zagnieżdżonej pętli na indeksie wynosi napędzany przez wysokość indeksu drzewa b i dostęp do samego bloku tabeli. Jest szybki, ale nie nadaje się do łączenia luzem.
  • zagnieżdżona pętla join oparta na klastrze jest znacznie tańsza, z mniejszą liczbą logicznych IO wymaganych na jeden wiersz join -- jeśli połączone tabele znajdują się w tym samym klastrze, to join staje się bardzo tani poprzez kolokację połączonych wierszy.

Bazy danych są zaprojektowane do łączenia, są bardzo elastyczne w tym, jak to robią i ogólnie bardzo wydajne, chyba że błąd w mechanizmie łączenia.

 42
Author: David Aldridge,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-06 13:00:19

Myślę, że całe pytanie opiera się na fałszywej przesłance. Połączenia na dużych stołach są nie koniecznie drogie. W rzeczywistości, wydajne łączenie jest jednym z głównych powodów, dla których istnieją relacyjne bazy danych. Łączenie dużych zbiorów często jest kosztowne, ale bardzo rzadko chcesz połączyć całą zawartość dużej tabeli a z całą zawartością dużej tabeli B. zamiast tego piszesz zapytanie w taki sposób, że używane są tylko ważne wiersze każdej tabeli a rzeczywisty zestaw utrzymywany przez połączenie pozostaje mniejszy.

DODATKOWO masz wydajność wspomnianą przez Petera Wone ' a, taką, że tylko ważne części każdego rekordu muszą być w pamięci, dopóki ostateczny zestaw wyników nie zostanie zmaterializowany. Ponadto, w przypadku dużych zapytań z wieloma połączeniami zazwyczaj chcesz zacząć od mniejszych zestawów tabel i przejść do dużych, tak aby zestaw przechowywany w pamięci pozostał tak mały, jak to możliwe, jak najdłużej.

Po poprawnym wykonaniu, dołącza są zazwyczaj najlepszym sposobem porównywania, łączenia lub filtrowania dużych ilości danych.

 25
Author: Joel Coehoorn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-06 16:45:06

Wąskim gardłem jest prawie Zawsze We/Wy dysku, a dokładniej-losowe We/Wy dysku (dla porównania, odczyty sekwencyjne są dość szybkie i mogą być buforowane za pomocą strategii read ahead).

Joins can increase random seeks-if you ' re jumping around reading small parts of a large table. Ale optymalizatory zapytań szukają tego i zamienią go w sekwencyjne skanowanie tabeli (odrzucanie niepotrzebnych wierszy), jeśli uzna, że byłoby lepiej.

A single denormalizowana tabela ma podobny problem - wiersze są duże, a więc mniej pasują do jednej strony danych. Jeśli potrzebujesz wierszy, które znajdują się daleko od innych (a duży rozmiar wierszy sprawia, że są dalej od siebie), będziesz mieć więcej losowych We/Wy.ponownie, skanowanie tabeli może być zmuszone tego uniknąć. Ale tym razem skanowanie tabeli musi odczytać więcej danych ze względu na duży rozmiar wiersza. Dodaj do tego fakt, że kopiujesz DANE z jednej lokalizacji do wielu lokalizacji, a RDBMS ma to dużo więcej do przeczytania (i pamięci podręcznej).

Z 2 tabel, można również uzyskać 2 indeksy klastrowe - i ogólnie można indeksować Więcej (z powodu mniej wstawiania / aktualizacji narzutu), co może uzyskać drastycznie zwiększoną wydajność (głównie, ponownie, ponieważ indeksy są (stosunkowo) małe, szybkie do odczytu z dysku (lub Tanie do pamięci podręcznej), i zmniejszyć ilość wierszy tabeli trzeba czytać z dysku).

O tylko narzut z łącznikiem pochodzi z wymyślania pasujących wierszy. SQL Server używa 3 różnych typy złączeń, głównie na podstawie rozmiarów zbiorów danych, w celu znalezienia pasujących wierszy. Jeśli optymalizator wybierze niewłaściwy typ połączenia (z powodu niedokładnych statystyk, nieodpowiednich indeksów lub po prostu błędu optymalizatora lub przypadku krawędzi), może drastycznie wpłynąć na czasy zapytań.

  • połączenie pętli jest zdecydowanie Tanie dla (przynajmniej 1) małego zbioru danych.
  • połączenie merge wymaga najpierw obu zestawów danych. Jeśli jednak dołączysz do zindeksowanej kolumny, wtedy indeks jest już posortowany i nie musisz już pracować załatwione. W przeciwnym razie w sortowaniu jest trochę narzutu procesora i pamięci.
  • połączenie hashowe wymaga zarówno pamięci (do przechowywania hashtable), jak i procesora (do budowania hash). Ponownie, jest to dość szybkie w odniesieniu do We/Wy dysku. jednakże, jeśli nie ma wystarczającej ilości pamięci RAM do przechowywania hashtable, Sql Server użyje tempdb do przechowywania części hashtable i znalezionych wierszy, a następnie przetworzy tylko części hashtable na raz. Podobnie jak w przypadku wszystkich dysków, jest to dość powolne.

In optymalny przypadek, powodują one brak We/Wy dysku - a więc są znikome z punktu widzenia wydajności.

W sumie, w najgorszym przypadku-powinno być szybciej odczytać taką samą ilość danych logicznych z połączonych tabel x, ponieważ jest to z jednej denormalizowanej tabeli ze względu na mniejszy odczyt dysku. Aby odczytać taką samą ilość danych fizycznych, mogą wystąpić niewielkie koszty ogólne.

Ponieważ czas zapytań jest zwykle zdominowany przez koszty We/Wy, a Rozmiar danych nie zmiana (minus kilka bardzo drobnych rzędów na górze) z denormalizacją, nie ma ogromnej korzyści, aby mieć po prostu łączenie tabel razem. Typ denormalizacji, który ma tendencję do zwiększania wydajności, IME, jest buforowanie obliczonych wartości zamiast odczytu 10 000 wierszy wymaganych do ich obliczenia.

 10
Author: Mark Brackett,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-03 23:33:32

Kolejność łączenia tabel jest niezwykle ważna. Jeśli masz dwa zestawy danych, spróbuj zbudować zapytanie w taki sposób, aby najmniejszy został użyty jako pierwszy, aby zmniejszyć ilość danych, na których zapytanie ma pracować.

W przypadku niektórych baz danych nie ma to znaczenia, na przykład MS SQL przez większość czasu zna właściwą kolejność łączenia. Dla niektórych (jak IBM Informix) kolejność robi różnicę.

 4
Author: Ilya Kochetov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-06 09:58:51

Podjęcie decyzji o denormalizacji lub normalizacji jest dość prostym procesem, jeśli weźmiemy pod uwagę klasę złożoności połączenia. Na przykład, mam tendencję do projektowania moich baz danych z normalizacji, gdy zapytania są O (k log n), gdzie k jest w stosunku do żądanej wielkości wyjściowej.

Łatwym sposobem na denormalizację i optymalizację wydajności jest zastanowienie się, jak zmiany w strukturze normalizacyjnej wpływają na denormalizowaną strukturę. Może być jednak problematyczne, ponieważ może wymagać logika transakcyjna do pracy na denormalizowanej strukturze.

Debata na temat normalizacji i denormalizacji nie zakończy się, ponieważ problemy są ogromne. Istnieje wiele problemów, w których naturalne rozwiązanie wymaga obu podejść.

Ogólnie rzecz biorąc, zawsze przechowywałem znormalizowaną strukturę i denormalizowaną pamięć podręczną, które można zrekonstruować. W końcu te Cache ratują mój tyłek, aby rozwiązać przyszłe problemy normalizacji.

 0
Author: MathGladiator,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-20 12:25:28

Opracowanie tego, co powiedzieli inni,

Łączniki są tylko produktami kartezjańskimi z pewną liposukcją. {1,2,3,4} x{1,2,3} dałoby nam 12 kombinacji (nXn=N^2). Ten zbiór obliczeniowy działa jako punkt odniesienia, w odniesieniu do których stosowane są warunki. DBMS stosuje warunki (takie jak gdzie zarówno lewa, jak i prawa są 2 lub 3), aby dać nam pasujące warunki. W rzeczywistości jest bardziej zoptymalizowany, ale problem jest ten sam. Zmiany rozmiaru zestawów zwiększyłyby wykładniczo rozmiar wyniku. Kwota zużyte cykle pamięci i procesora są wykonywane w ujęciu wykładniczym.

Kiedy denormalizujemy, unikamy tego obliczenia całkowicie, pomyśl o tym, aby mieć kolorowy lepki, dołączony do każdej strony książki. Można wywnioskować informacje z zewnątrz za pomocą odniesienia. Kara, którą płacimy, polega na tym, że narażamy istotę DBMS (optimal organization of data)

 -6
Author: questzen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-06 11:09:55