Projektuję tabelę pozycji, która (potencjalnie) będzie zawierać dziesiątki milionów rekordów. Niektóre elementy nie będą dostępne, dopóki nie zostaną „zatwierdzone” przez administratora. Przez „use” rozumiem, że do takich pozycji nie będzie odwoływać się żadna inna tabela, dopóki nie zostaną „zatwierdzone”. Do 50% produktów może być „niezatwierdzonych” w dowolnym momencie. Zapisy mogą zostać „zatwierdzone”, ale nie odwrotnie.
Rozważam dwie opcje projektowania:
- trochę flaga
- osobna tabela „niezatwierdzonych” przedmiotów - po zatwierdzeniu element jest przenoszony do „zwykłej” tabeli (odnowienie ID przedmiotu nie stanowi problemu)
Myślę, że druga opcja jest znacznie lepsza. Flaga bitowa zajmuje tylko bajt na wiersz, więc nie stanowi to problemu. Ale jeśli mamy milion zatwierdzonych i milion niezatwierdzonych rekordów w tej samej tabeli - czas skanowania wydłuża się dla operacji z zatwierdzonymi rekordami.
Pytanie brzmi: czy powinienem rozważyć pierwszą opcję (flaga bitowa)? Czy ma jakieś zalety w opisywanej sytuacji?
WHERE status='A'
a zapytanie maWHERE status = 'A' AND (... other columns and parameters here...)
, to indeks może być nadal używany.Odpowiedzi:
Możesz to zrobić na dwa sposoby z widokami podzielonymi na partycje .
Tworzysz tabelę bazową dla każdego statusu, wymuszoną przez ograniczenia, z wzajemnie wykluczającymi się wartościami. Następnie zobacz, które UNIE razem tworzą podstawowe tabele. Do widoku lub każdej tabeli bazowej można bezpośrednio odwoływać się. Jeśli status wiersza jest aktualizowany przez widok, DBMS usunie go z jednej tabeli podstawowej i wstawi do tego odpowiadającego nowemu statusowi. Każda tabela podstawowa może być indeksowana niezależnie zgodnie z jej wzorcem użytkowania. Optymalizator rozpozna odniesienia do pojedynczej odpowiedniej tabeli podstawowej, jeśli to możliwe.
Korzyści to
a) płytsze indeksy. Wykonaj matematykę na temat rozwijania indeksu. Przy tej skali i podziale między wartościami statusu możliwe jest, że indeksy będą miały taką samą głębokość w tabelach podziału, jak w tabeli łączonej.
b) kod aplikacji nie musi się zmieniać. Dane nadal pojawiają się jako ciągła całość.
c) przyszłe nowe wartości statusu można uwzględnić, dodając nową tabelę podstawową z ograniczeniami i ponownie tworząc widok.
Kosztem jest cały ten ruch danych; dwie strony i powiązane indeksy są zapisywane dla każdej aktualizacji statusu. Dużo IO do załatwienia. Taki ruch spowoduje również fragmentację.
źródło
To właściwie nie tyle, biorąc pod uwagę to, co SQL Server może skutecznie obsługiwać. Oczywiście pamiętam jedno z moich wcześniejszych zadań, w którym jedna z największych tabel (system z pojedynczą instancją) miała 2 miliony wierszy i była to największa ilość, z jaką kiedykolwiek miałem do czynienia. Następnie następne zadanie obejmowało 17 instancji produkcyjnych z niektórymi tabelami zawierającymi setki milionów wierszy, a wszystkie zostały zagregowane w hurtownię danych z wieloma tabelami faktów mającymi ponad 1 miliard wierszy. Nie zrozum mnie źle, nie szydzę z dziesiątek milionów wierszy, po prostu podkreślam, że przy dobrym modelu danych i właściwym indeksowaniu (i konserwacji indeksów) SQL Server może wiele poradzić .
Hmm To nie brzmi dobrze. Wskaźnik „zatwierdzania” wpisów będzie o połowę mniejszy niż liczba nowych wpisów? Na każde 2 nowe wpisy tylko 1 zostanie „zatwierdzony”? W twoim przykładzie 2 milionów wierszy i 1 miliona dla „zatwierdzonych” i „niezatwierdzonych”, kilka lat później z kolejnymi 10 milionami wpisów, oczekujesz 6 milionów dla „zatwierdzonych” i „niezatwierdzonych”? Czy może 1 milion „niezatwierdzonych” pozostanie nieco stały, tak że przy 10 milionach nowych wpisów będzie 11 milionów „zatwierdzonych”, a 1 milion „niezatwierdzonych”?
To prawda dzisiaj , ale z czasem wszystko się zmienia, dlatego zawsze istnieje możliwość, że firma zdecyduje się na „niezatwierdzenie”, a może jakiś inny status, np. „Zarchiwizowany” itp.
Spójrzmy więc na opcje:
Flaga (a może nawet
TINYINT
„status”)TINYINT
kolumnyDwie oddzielne tabele (jedna dla „zatwierdzonych”, jedna dla „niezatwierdzonych”)
IDENTITY
kolumną, a tabela zatwierdzona ma kolumnę identyfikatora, która nie jestIDENTITY
(ponieważ nie jest tam potrzebna). W związku z tym wartości ID pozostają spójne, gdy rekord przemieszcza się między tabelami.Osobiście pochyliłbym się w kierunku pojedynczego stołu z
StatusID
kolumną na początek. Korzystanie z dwóch tabel wydaje się nadmiernie skomplikowaną, przedwczesną optymalizacją. Tego rodzaju optymalizację można omówić, jeśli / kiedy liczba rekordów wynosi kilkaset milionów, a indeksowanie nie zapewnia żadnego wzrostu wydajności.źródło