Jakie są prawidłowe scenariusze użycia dla tabel HEAP?

31

Obecnie wykonuję import niektórych danych do starszego systemu i odkryłem, że ten system nie używa pojedynczego indeksu klastrowego. Szybkie wyszukiwanie w Google zapoznało mnie z koncepcją tabel HEAP, a teraz jestem ciekawy, jakie scenariusze użytkowania powinny być preferowane w stosunku do tabeli klastrowej?

O ile rozumiem, tabela HEAP byłaby przydatna tylko dla tabel audytu i / lub tam, gdzie wstawianie zdarza się znacznie częściej niż selekcje. Zaoszczędziłoby to miejsce na dysku i dyskowe operacje wejścia / wyjścia, ponieważ nie ma żadnego indeksu klastrowego do utrzymania, a dodatkowa fragmentacja nie stanowiłaby problemu z powodu bardzo rzadkich odczytów.

marc.d
źródło
1
Mówisz o SQL Server?
a_horse_w_no_name
@ a_horse_with_no_name tak, zapomniałem wspomnieć, że sry
marc.d
Tabele stert są dobre dla tabel z milionami wierszy, które są mocno uderzane przez użytkowników. Minusem jest to, że mogą zajmować dużo miejsca, ponieważ dane są fizycznie przechowywane nieposortowane. Ponadto możesz polegać na swoich indeksach, aby dostosować je do swoich zapytań. Pracowałem w miejscach, które w ogóle nie używały indeksów klastrowych z powodu problemów z wydajnością. Prawdopodobnie z powodu złych wyborów indeksu klastrowego, ale jeśli używasz tylko tabel sterty, nie musisz się o to martwić. Lepszym rozwiązaniem byłoby użycie korporacyjnej wersji serwera SQL i partycjonowanie dużego stołu w poziomie. Ale jeśli nie masz ent
Zobacz także stackoverflow.com/questions/1341393/... .
Jon of All Trades

Odpowiedzi:

22

Jedyne prawidłowe zastosowania dotyczą

  • tabele pomostowe używane w procesach importu / eksportu / ETL.
  • ad-hoc, tymczasowe i krótkoterminowe tworzenie kopii zapasowych tabel przy użyciu SELECT * INTO..

Tabele pomostowe są zazwyczaj dość płaskie i obcięte przed / po użyciu.

Zauważ, że indeks klastrowy jest zwykle niewielki w porównaniu do wielkości danych: dane najniższym poziomem struktury indeksu.

Stoły stert również mają problemy. Przynajmniej te:

Zobacz także

gbn
źródło
2
Zwykle używa hałd do dwóch osobnych rzeczy. Tabele przemieszczania i pracy ETL, których używam do tymczasowego przechowywania danych, gdy zestaw jest zbyt duży, aby tabela tymczasowa działała skutecznie. Wszystkie są obcinane przy następnym ładowaniu.
Zane,
Przy okazji, dobre pytanie.
Zane,
1
Jedna drobna poprawka - jeśli wykonasz WYBIERZ W celu utworzenia szybkiej kopii zapasowej małej tabeli przed dokonaniem zmiany, domyślnie tworzona jest sterty. Powiedziałbym, że jest to poprawne zastosowanie - ale to tylko wybieranie nitów. Chciałbym się pozbyć tej hałdy, jak tylko będę wiedział, że moja praca została wykonana.
Brent Ozar,
@BrentOzar: Zgadzam się, robię to cały czas sam. Duch mojej odpowiedzi brzmi: „tabele długoterminowe i trwałe”, ale zaktualizuję
2015 r
9

Główne uwagi

Widzę jedną ważną zaletę dla stosów i jedną dla tabel klastrowych, a także trzecią uwagę, która może iść w obie strony.

  • Kupa oszczędza warstwę pośrednią. Indeksy zawierają identyfikatory wierszy wskazujące bezpośrednio (dobrze, nie tak naprawdę, ale tak bezpośrednio, jak to możliwe) na lokalizację dysku. Dlatego szukanie indeksu względem sterty powinno kosztować około połowy poszukiwania indeksu nieklastrowego względem tabeli klastrowanej.

  • Indeks klastrowany jest sortowany per se, dzięki (prawie) wolnemu indeksowi. Ponieważ indeks klastrowania jest odzwierciedlony w fizycznej kolejności danych, zajmuje on stosunkowo niewiele miejsca na samych danych, które oczywiście trzeba przechowywać. Ponieważ jest ono uporządkowane fizycznie, skanowanie zasięgu w stosunku do tego indeksu może wyszukiwać do punktu początkowego, a następnie bardzo skutecznie przesuwać się do punktu końcowego.

  • Wskaźniki na hałdach odnoszą się do RID, które są 64-bitowe. Jak wspomniano, nieklastrowe indeksy w tabeli klastrowej odnoszą się do klucza klastrowania, który może być mniejszy (32-bitowy INT), taki sam (64-bitowy BIGINT) lub większy (48-bitowy DATETIME2()plus 32-bitowy INT, lub 128-bitowy identyfikator GUID). Oczywiście szersze odniesienie powoduje, że indeksy są większe i droższe.

Wymagania dotyczące miejsca

Dzięki tym dwóm tabelom:

CREATE TABLE TmpClustered
(
ID1 INT NOT NULL,
ID2 INT NOT NULL
)
ALTER TABLE TmpClustered ADD CONSTRAINT PK_Tmp1 PRIMARY KEY CLUSTERED (ID1)
CREATE UNIQUE INDEX UQ_Tmp1 ON TmpClustered (ID2)

CREATE TABLE TmpNonClustered
(
ID1 INT NOT NULL,
ID2 INT NOT NULL
)
ALTER TABLE TmpNonClustered ADD CONSTRAINT PK_Tmp2 PRIMARY KEY NONCLUSTERED (ID1)
CREATE UNIQUE INDEX UQ_Tmp2 ON TmpNonClustered (ID2)

... każdy zawiera 8,7 mln rekordów, wymagane miejsce to 150 MB na dane dla obu; 120 MB dla indeksów tabeli klastrowej, 310 MB dla indeksów tabeli nieklastrowanej. Odzwierciedla to, że indeks klastrowy jest węższy niż RID i że indeks klastrowy jest przeważnie „darmowy”. Bez włączonych unikatowych indeksów ID2wymagana przestrzeń indeksu spada do 155 MB dla nieklastrowanej tabeli (połowa, jak można się spodziewać), ale tylko 150 KB dla klastrowanego PK - prawie nic.

Tak więc indeks nieklastrowy 32-bitowego pola w tabeli klastrowej z indeksem 32-bitowym (łącznie 64 bity, nominalnie) zajął 120 MB, podczas gdy indeks 32-bitowego pola w stercie z 64-bitowym RID (łącznie 96 bitów, nominalnie) zajął 155 MB, czyli nieco mniej niż 50% wzrost, na który naiwnie można się spodziewać przejścia z 64-bitowych na 96-bitowe klucze, ale oczywiście jest narzut, który zmniejsza efektywną różnicę wielkości.

Zapełnienie dwóch tabel i utworzenie ich indeksów zajęło tyle samo czasu dla każdej tabeli. Przeprowadzając proste testy obejmujące skanowanie lub wyszukiwanie, nie znalazłem istotnych różnic w wydajności między tabelami, które pasują do białej księgi Microsoft, którą gbn jest pomocne. Wspomniany artykuł wykazuje znaczącą różnicę w przypadku wysoce współbieżnego dostępu; Nie jestem pewien, dlaczego tak się dzieje, mam nadzieję, że ktoś z większym doświadczeniem niż ja z dużymi systemami OLTP może nam powiedzieć.

Dodanie ~ 40 bajtów losowych danych o zmiennej długości nie zmieniło znacząco tej równoważności. Zastąpienie INTs szerokimi identyfikatorami UUID również nie spowodowało (każda tabela została spowolniona w mniej więcej tym samym stopniu). Może się wahać, ale w większości przypadków , czy indeks jest dostępny jest ważniejsze niż to, co rodzaj.

Kawałki

Wykonywanie skanowania zakresu w stosunku do indeksu nieklastrowego - ponieważ tabela jest stertą lub indeks nie jest indeksem klastrowanym - obejmuje skanowanie indeksu, a następnie wyszukiwanie tabeli w odniesieniu do każdego działania. Może to być bardzo kosztowne, więc czasami taniej jest po prostu zeskanować stół. Możesz jednak obejść ten problem za pomocą indeksu obejmującego. Dotyczy to niezależnie od tego, czy masz klaster tabeli, czy nie.

Jak zauważył @gbn, nie ma prostego sposobu na zagęszczenie sterty. Jeśli jednak twoja tabela stopniowo się powiększa - co jest bardzo częstym przypadkiem - niewiele będzie marnotrawstwa, ponieważ przestrzeń zwolniona przez usuwanie zostanie wypełniona nowymi danymi.

Kilka dyskusji na temat sterty w porównaniu do tabeli klastrowej, które widziałem, stanowi ciekawy argument, że sterta bez indeksów jest gorsza od tabeli klastrowanej, ponieważ zawsze wymaga skanowania tabeli. Jest to z pewnością prawda, ale bardziej miarodajne porównanie to „duża dobrze indeksowana tabela klastrowa” w porównaniu z „dużą dobrze indeksowaną stertą”. Jeśli twój stół jest bardzo mały lub zawsze będziesz przeprowadzał skanowanie tabeli, to nie ma większego znaczenia, czy go zgrupujesz, czy nie.

Ponieważ każdy indeks w tabeli klastrowej odwołuje się do indeksu klastrowania, w rzeczywistości wszystkie indeksy pokrywają się. Kwerenda, która odwołuje się do kolumny indeksowanej i kolumn klastrowych, może wykonać skanowanie indeksu bez wyszukiwania tabel. Zasadniczo nie jest to cenne, jeśli indeks klastrowania jest kluczem syntetycznym, ale jeśli jest to klucz biznesowy, który i tak należy pobrać, jest to miła funkcja.

TL; DR

Jestem facetem od hurtowni danych, a nie ekspertem od OLTP. W przypadku tabel faktów prawie zawsze używam indeksu klastrowania w polu, który najprawdopodobniej wymaga skanowania zakresu, zazwyczaj pola daty. W przypadku tabel wymiarów klastruję na PK, więc jest on przewidziany dla połączeń scalania z tabelami faktów.

Istnieje kilka powodów, dla których warto stosować indeksy klastrowe, ale jeśli żaden z tych powodów nie ma zastosowania, koszty ogólne mogą nie być opłacalne. Podejrzewam, że wiele osób „zawsze tak robiliśmy” i „to po prostu najlepsza praktyka” za ludźmi używającymi indeksów klastrowych uniwersalnie. Spróbuj zarówno ze swoimi danymi i swoim obciążeniem i zobaczyć, co działa najlepiej.

Jon of All Trades
źródło
5

Myślę, że powiedzenie „Jedynym prawidłowym zastosowaniem są tabele pomostowe używane w procesach importu / eksportu / ETL” jest co najmniej nieco restrykcyjne. Musisz wziąć przewidywany przypadek użycia danego systemu, a następnie wybrać na podstawie zalet stosów lub indeksowanych tabel zorganizowanych (wiem, termin Oracle, ale ładnie go opisuje).

Nasz magazyn ładuje ~ 1,5 miliarda wierszy dziennie i musi obsługiwać wysoce równoczesne zapisy i przetwarzanie, a także odczyty. Sklep relacyjny obsługuje bazę danych OLAP, a zatem odczyty są zwykle skanami tabel. Generowane raporty i kanały końcowe nie są na ogół wystarczająco selektywne, aby przydałby się jakikolwiek indeks. System obsługuje przesuwane okno danych, dlatego po załadowaniu tabeli rzadko do niego piszemy ponownie, biorąc pod uwagę raczej słabą implementację partycjonowania tabel wymagającego blokad Sch-M dla podziałów, przełączników i scaleń w porównaniu do blokad Sch-S dla odczytów itp. , system musiał korzystać z wielu tabel, chociaż mamy też tabele podzielone na partycje. Zastosowanie wielu tabel ułatwia segmentację danych i cykle czyszczenia, jednocześnie zmniejszając rywalizację.

Jako taki, dodatkowy narzut indeksu tabeli zorganizowanej (tabeli klastrowanej) w niektórych dowolnych kolumnach w porównaniu do możliwości bcp w stercie, przetwarzania partycji OLAP, wykonywania niektórych zapytań skanowania tabeli, a następnie 3 dni później upuszczenia oznacza to, że po prostu nie jest tego warte. Zauważ, że w naszym przypadku dane wracają z dużego klastra siatki, więc nie ma również kolejności danych, więc wstawienie do tabeli z indeksem klastrowym może wprowadzić inne problemy, takie jak „punkty aktywne” i podziały stron i tym podobne.

Ponadto uważam, że argument o rozproszeniu stron jest nieco nieuczciwy. Indeksy klastrowe mogą również mieć swoje strony rozproszone w całym pliku. Po ponownym zaindeksowaniu (przy założeniu ponad 1000 stron) może to być lepsze niż kupa, ale potem trzeba było również ponownie zaindeksować.

Możliwe jest również zaoszczędzenie miejsca przy użyciu rzadkich kolumn i kompresji, jeśli jest to problem. Prawdą jest, że w niektórych przypadkach wybory w tabeli z indeksem klastrowym mogą być szybsze, ale trzeba to wyważyć z zasobami wymaganymi do załadowania go i utrzymania.

[Edytuj] Powinienem chyba wyjaśnić, że tylko nasze niepodzielone na partycje tabele faktów to stosy. Wszystkie podzielone na partycje tabele i tabele wymiarów mają indeksy klastrowe, które wspierają wydajne wyszukiwanie itp. [Edytuj2] Poprawiono 2,5 miliarda do 1,5 miliarda. Tut, te dwie liczby są obok siebie. Co się dzieje, gdy wpisuję odpowiedzi na telefonie, myślę ...

Phil Stephenson
źródło