Czy dodanie indeksu do kolumny bitowej znacznie spowalnia wstawianie?

11

Mam tabelę z około 1 milionem do 5 milionów rekordów. Niewielka część tych rekordów ma jedną z bitowych kolumn ustawioną na „PRAWDA”. Musisz szybko znaleźć te rekordy. Myślę, że ten indeks może przyspieszyć wyszukiwanie w tej kolumnie, ale obawiam się WSTAWIĆ. Stąd moje pytanie.

Baza danych działa jak rodzaj hurtowni danych, więc istnieje wiele WYBORÓW i małe (do 10-20 dziennie), ale dość duże WSTAWKI (do 200 tysięcy rekordów jednocześnie). Obawiam się dłuższego czasu tego importu do bazy danych.

marioosh
źródło
5
Jaka wersja SQL Server? Jeśli 2008+ brzmi jak przefiltrowany indeks może być tym, czego potrzebujesz.
Martin Smith
SQL Server 2005
marioosh
1
Możesz podzielić tabelę (dodać nową tabelę z tylko jedną kolumną, PK tabeli, która zostanie wypełniona tylko tymi wierszami, że kolumna bitowa jest prawdziwa - w końcu możesz nawet usunąć kolumnę bitową.) Zindeksowana widok działałby również w 2005 r., przy braku częściowych indeksów.
ypercubeᵀᴹ
bądź ostrożny z widokiem indeksowanym, ponieważ jak wspomniałeś, masz 10-20 dużych wkładek dziennie, utrzymanie widoku indeksowanego może przewyższyć korzyści związane ze wzrostem wydajności. nie sądzę, aby jakakolwiek „bezpośrednia funkcja” SQL 2005 mogła służyć do poprawy sytuacji. ale jeśli wymienisz obecną strukturę tabeli i istniejący indeks, możemy znaleźć alternatywny projekt.
Anup Shah

Odpowiedzi:

8

Indeks bitowy dla 1 miliona rekordów jest bezużyteczny. Optymalizator nigdy go nie użyje, zapłacisz tylko za jego utrzymanie. O wiele lepszą alternatywą jest dodanie tego bitu jako lewego klawisza w indeksie klastrowym.

Ale zrobię ślepy strzał w ciemności i odgadnę, że masz wzór kolejek: rekordy są upuszczane w tabeli z bitem ustawionym na „PRAWDA” (tj. „Needsprocessing = true”), a następnie wygląda proces w tle dla tych rekordów wykonuje pewne przetwarzanie i aktualizuje bit do FAŁSZ. Jest to wszechobecny wzorzec, zwany również pieszczotliwie „wzorzecem przepisu na katastrofę wydajności”. Poleciłbym upuścić rekordy do tabeli i upuścić powiadomienie (może być tak proste, jak nowo wstawiony identyfikator rekordu) jednocześnie do kolejki . Zobacz Używanie tabel jako kolejek .

Remus Rusanu
źródło
1
Nie widzę żadnego sensu, aby umieszczać kolumnę bitów po lewej stronie, ponieważ nie znamy innych kolumn z filtrem o wysokim współczynniku kardynałowości. do tej pory widziałem kolumnę BIT jest ostatnim wyborem w indeksie klastrowym. ale tak, +1 za miłe odniesienie do „Używanie tabeli jako kolejki”.
Anup Shah
2
Właściwie przeprowadziłem test i tak, użyje indeksu. Utwórz tabelę (identyfikator tożsamości, bit myBit) dodaj 100 wierszy, w których bit ma wartość 0, i 2000000, gdzie bit ma wartość 1. Upewnij się, że statystyki są aktualizowane (w razie potrzeby) i uruchom zapytanie na myBit = 0, a indeks zostanie użyty.
Kenneth Fisher
@KennethFisher, z wyjątkiem tego, że w typowym modelu dużej prędkości wstawiania PRAWDA / aktualizacja do FAŁSZ natychmiast statystyki zawsze będą nieaktualne. Jeśli wolisz grać w rosyjską ruletkę przy użyciu optymalizatora zamiast przejrzystego projektu, dostaniesz to, na co zasłużyłeś ...
Remus Rusanu
„nigdy go nie użyję” to stwierdzenie dotyczy 99% przypadków, ale nie wiemy, w jakim przypadku znajduje się OP. Z powodzeniem zaindeksowałem bit. Istnieją przypadki użycia.
usr
pytanie - czy odpowiedź jest zła, a konkretnie> „Kiedy indeksujesz pole bitowe (lub jakiś wąski zakres), zmniejszasz zestaw roboczy tylko o liczbę wierszy pasujących do tej wartości. Jeśli masz niewielką liczbę wierszy pasujących do niego znacznie zmniejszyłoby Twój zestaw roboczy . W przypadku dużej liczby wierszy z rozkładem 50/50 może to spowodować bardzo niewielki wzrost wydajności w porównaniu z utrzymaniem aktualności indeksu ”. W takim przypadku indeks na bicie, który odpowiada 1% rekordów, pozwoliłby uniknąć skanowania 99% z 1 miliona w celu znacznego przyspieszenia?
drzaus
2

Jak powiedział @MartinSmith, jeśli kiedykolwiek uaktualnisz do SQL 2008, filtrowany indeks byłby idealnym rozwiązaniem. Jednak w międzyczasie jako ogólny przypadek KAŻDY dodany indeks wydłuży czas ładowania. Małe indeksy mniej niż duże.

Jedną rzeczą, na którą chciałbym spojrzeć, jest posiadanie istniejącego indeksu, który można modyfikować. Zakładając, że twoje istniejące zapytania używają danego indeksu, następnie dodanie kolumny bitów na końcu tego indeksu powinno mieć minimalny wpływ na wstawki i pozytywny efekt, na który patrzysz na swoje zapytania.

Następną rzeczą do obejrzenia jest „Czy mam już wiele indeksów?” Nie ma twardej i szybkiej reguły dotyczącej tego, czym jest „dużo”, ale zwykle stosuję regułę 10 indeksów, która jest limitem, chyba że NAPRAWDĘ potrzebuję nowej.

Ostatnia myśl, przetestuj to na instancji testowej. Skonfiguruj tabelę z kilkoma milionami wierszy, uruchom na niej obciążenie, dodaj indeks, a następnie uruchom ponownie ładunek i sprawdź, czy zauważysz znaczący wzrost czasu ładowania.

Tylko Ty naprawdę możesz zdecydować, co jest „znaczące”. Mam maszyny, w których dodanie 5 minut do czasu ładowania jest „znaczące” i inne, w których mogłem bezpiecznie zaobserwować wzrost o kilka godzin.

EDYTOWAĆ:

Inną opcją jest podzielenie tabeli na partycje. Być może będziesz musiał użyć widoku podzielonego na partycje, jeśli nie korzystasz z wersji Enterprise, ale mimo to powinno to pomóc. Umieszczasz swoje bity 0 w jednej partycji, a bity 1 w innej. Zakładając, że wstawiasz tylko jedną wersję lub drugą, możesz nawet przyspieszyć wstawianie.

Kenneth Fisher
źródło