2009-06-22 5 views
7

Hipotetycznie, w bazie danych SQL Server, jeśli mam tabelę z dwoma polami int (np. Relacja wiele do wielu), która uczestniczy w łączeniach między dwiema innymi tabelami, przy jakim przybliżonym rozmiarze tabela staje się wystarczająco duża, gdy wydajność korzyści z indeksów na dwóch polach int pokonuje koszty narzucone przez te indeksy?Kiedy tabela bazy danych jest wystarczająco duża, aby indeks był korzystny?

Czy istnieją różnice w architekturze między różnymi wersjami SQL Server, które zasadniczo zmieniłyby tę odpowiedź?

Odpowiedz

10

W przypadku zapytań obejmujących małe fragmenty wierszy tabeli, indeksy są zawsze korzystne, bądź tam 100 wierszy lub .

Zobacz ten wpis w moim blogu na przykładach z planów i szczegółów Osiągi:

zapytań tak:

SELECT * 
FROM table1 t1 
JOIN table2 t2 
ON  t2.col = t1.col 

najprawdopodobniej korzystania HASH JOIN. Zostanie zbudowana tablica mieszająca dla mniejszej tabeli, a wiersze z większej tabeli będą używane do sprawdzania tabeli mieszania.

Aby to zrobić, indeks nie jest potrzebny.

jednak to zapytanie:

SELECT * 
FROM table1 t1 
JOIN table2 t2 
ON  t2.col = t1.col 
WHERE t1.othercol = @value 

użyje NESTED LOOPS: wiersze z tabeli zewnętrznej (table1) będą wyszukiwane za pomocą indeksu table1.othercol i wiersze z tabeli wewnętrznej (table2) będzie wyszukiwane przy użyciu indeksu na table2.col.

Jeśli nie masz indeksu na col1, A HASH JOIN zostaną wykorzystane który wymaga skanując wszystkie wiersze z obu tabel, a niektóre więcej środków na wbudowanym tabeli mieszania.

Indeksy są również użyteczne dla zapytań takich jak ten:

SELECT t2.col 
FROM table1 t1 
JOIN table2 t2 
ON  t2.col = t1.col 

, w takim przypadku silnik nie trzeba czytać table2 sama w ogóle: eveything trzeba dla tego zapytania można znaleźć w indeksie , która może być znacznie mniejsza niż sama tabela i bardziej wydajna do czytania.

I, oczywiście, jeśli potrzebujesz dane sortowane i mają indeksy zarówno table1.col i table2.col, to następujące zapytanie:

SELECT * 
FROM table1 t1 
JOIN table2 t2 
ON  t2.col = t1.col 
ORDER BY 
     t2.col 

będzie prawdopodobnie używać MERGE JOIN metodę, która jest super szybki, gdy oba zestaw wierszy wejściowych są sortowane, a ich dane wyjściowe są również sortowane, co oznacza, że ​​ORDER BY jest bezpłatne.

Należy pamiętać, że nawet jeśli nie masz indeksu, optymalizator może wybrać dla swojej małej tabeli wartość Eager Spool, co oznacza utworzenie indeksu tymczasowego na czas trwania zapytania i usunięcie indeksu po zakończeniu zapytania.

Jeśli zapytanie jest małe, będzie bardzo szybkie, ale ponownie indeks nie zaszkodzi (mam na myśli zapytania o numerach SELECT). Jeśli optymalizator nie będzie tego potrzebować, po prostu nie będzie używany.

Należy jednak pamiętać, że tworzenie indeksu może mieć wpływ na wydajność DML, ale jest to inna historia.

+0

W rzeczywistości baza danych nie sortuje kluczy w obrębie jednej strony. Więc dopóki nie przekroczy tego punktu, nie ma żadnej korzyści. I prawdopodobnie na kilka stron dalej. – dkretz

+0

@Robert: przynoszą również korzyści, gdy używasz tylko indeksowanych kolumn w zapytaniu lub gdy potrzebujesz posortować dane. I nie, nie zawsze są one korzystne dla klauzuli WHERE, tylko w przypadku bardzo selektywnych. – Quassnoi

+0

Quassnoi, widziałem twój blog. Tak, więc wiesz, ostateczna decyzja o indeksowaniu naszej bazy danych (na podstawie dodatkowych informacji pod tym postem: stackoverflow.com/questions/1033796/...) polegała na indeksowaniu wszystkich kluczy obcych, Z WYJĄTKIEM tych, którzy uczestniczą w połączeniach z tabelami wyszukiwania zawierającymi MNIEJ NIŻ 10 DOKUMENTACJA. –

0

Wierzę, że zaraz po rozpoczęciu łączenia z polami int, Twój stół jest wystarczająco duży. Jeśli tabela jest na tyle mała, że ​​nie odniesie ona korzyści z indeksu, wówczas narzut nie będzie na tyle znaczący, że zechcesz zrezygnować.

Kiedy myślę o obciążeniu wynikającym z indeksu, zazwyczaj zastanawiam się, jak często zmienia się indeks tabeli - poprzez wstawianie, usuwanie i aktualizację do indeksowanych kolumn.

+0

Indeksy dodają narzutów również w instrukcjach SELECT, a nie tylko INSERT i UPDATE. –

1

Indeks prawie zawsze zwiększy wydajność kwerendy, kosztem dodatkowej pamięci i kosztu wydajności wstawiania/usuwania (ponieważ musi w tym momencie utrzymać indeks). Profilowanie będzie jedynym określonym sposobem określenia, czy indeks, w twoim konkretnym przypadku, jest korzystny.

Ogólnie rzecz biorąc, handlujesz pamięcią, aby uzyskać szybkość, gdy tworzysz indeks (inny niż dodatkowy koszt wstawienia). Jeśli wykonujesz wiele zapytań (wyborów lub aktualizacji) w stosunku do liczby wstawionych/usuniętych wierszy, indeksy prawie zawsze zwiększą Twoją wydajność.

+0

Jeśli przypadek jest względnie standardowy (jak w przykładzie dwóch intów w tabeli), to punkt końcowy jest względnie wyrównany lub będzie się zmieniać w zależności od liczby dodatkowych kolumn w tabelach zewnętrznych i innych nieznanych czynniki? –

+0

Optymalizator wie, gdzie znajduje się punkt krytyczny, więc nie musisz się tym martwić. Jeśli kara za ładowanie jest znacząca, ponieważ ładujesz wiersze wystarczająco szybko, by zauważyć, dotrzesz do tego punktu w żadnym momencie. – dkretz

+0

Indeksowanie przyspieszy zapytania, prawie na całej tablicy. Liczba kolumn będzie miała niewielką różnicę, ponieważ chodzi o zlokalizowanie odpowiednich wierszy do zwrotu (co jest nieco oddzielone od liczby kolumn). Jeśli masz bardzo mało danych, indeks może niewiele pomóc, ale jest też prawie darmowy - ja osobiście zawsze indeksuję kolumny, z których będę często korzystał dla zapytań o lokalizację (w tym aktualizowanie wierszy [o ile nie zmienisz indeksowana kolumna), ponieważ będzie to znacznie szybsze z indeksem, nawet w stosunkowo niewielkich przypadkach. –

1

zależy to od selektywności danych, jeśli dane nie są wystarczająco selektywne, indeks może nie zostać użyty, ponieważ koszt będzie zbyt wysoki. Jeśli w tabeli są tylko 2 wartości, a te wartości są równomiernie rozłożone, otrzymasz skanowanie, którego nie potrzebujesz. Wciąż uważam, że każda tabela powinna mieć klucz podstawowy, jeśli to masz, to masz już indeks

+0

To prawda, że ​​w moim hipotetycznym (łączeniu wielu do wielu) zewnętrzne tabele miałyby już indeksy. –

+0

Dwukolumnowa tablica połączeń? Byłoby bardzo nietypowe mieć niską selektywność na podstawowych kluczach z dwóch innych tabel. – dkretz

+0

@Robert: A co z twoją tabelą linków? Powinien również posiadać klucz podstawowy - jeśli nic więcej, złożony klucz podstawowy na dwóch kolumnach klucza obcego. W jaki sposób obecny schemat chroni przed duplikowaniem rekordów? – GalacticCowboy

1

Kara za wstawienie będzie nieznaczna do momentu pojawienia się korzyści z indeksów. Optymalizator jest wystarczająco inteligentny, aby zignorować indeksy, dopóki ten punkt nie zostanie kliknięty. Wystarczy więc od razu zaindeksować tabelę.

+0

Czy twierdzisz, że SQL Server utworzy plan wykonania za pomocą indeksów tylko wtedy, gdy ustali, że indeks zapewni korzyści? –

+1

Dobrze. W SO było kilka pytań o to, dlaczego indeksy nie są używane w małych tabelach, a odpowiedzią było "nie masz jeszcze wystarczającej ilości danych". – dkretz

+0

Moje pytanie zmienia się na: "Przy jakiej liczbie rekordów program SQL Server Optimizer kopie indeks?" A odpowiedź brzmi: "Nie przejmuj się?" –

1

Inną rzeczą, o której należy pomyśleć, jest koncepcja kodowania wydajności - czasami posiadanie indeksu może usprawnić umysłowe obciążenie myślenia o tym, jak zarządzać relacją między różnymi częściami danych. czasami może to skomplikować ...

+0

Jedna rzecz, o której nie wspomniałem to to, że używam Linq do SQL, który wydaje się przyjmować nazwy pól i indeksy jako wskazówki dla tego, co jest zawarte w modelu; w szczególności, połączenia klucza obcego mają specjalne preferencje. –

1

Bez względu na rozmiar, zawsze przynosi korzyści podczas indeksowania przy użyciu indeksu.

Odnośnie do narzutu, pojawia się pytanie: co narzut ma na myśli i jak odnosi się to do wartości wyszukiwania? W końcu są to osobne wartości.

Istnieją dwie formy narzutu dla indeksu: spacja (która jest zazwyczaj znikoma, w zależności od struktury indeksu) i ponowne indeksowanie na insert (serwer musi ponownie obliczyć indeks po każdej wstawce).

Jak już wspomniałem, kwestia przestrzeni kosmicznej prawdopodobnie nie jest tak wielka. Ale ponowne indeksowanie to. Na szczęście trzeba wykonać wiele bliskiego ciągłego wstawiania, zanim ta forma narzutu stanie się problemem.

Najważniejsze: prawie zawsze lepiej mieć indeks. Zacznij od tej pozycji i poczekaj, aż ponowne indeksowanie stanie się wąskim gardłem. Następnie możesz zajrzeć do alternatyw.

+0

Niepoprawnie. Utwórz tabelę z tylko jednym wierszem, dodaj indeks i przekonaj się sam. –

+0

OK, przez "niezależnie od wielkości" mam na myśli "dla tabel z liczbą rzędów większą niż 3". Lepszy? – Randolpho

+0

Czy punkt przechylania to naprawdę trzy zapisy? To nie wydaje się prawdopodobne. –

1

Najlepszą rzeczą jest to, aby sam serwer zrozumieć. Indeks tworzy się w kolumnach, w których ma on sens (jestem pewien, że istnieją całe rozdziały, jeśli nie książki, jak to zrobić w najlepszy sposób), i niech serwer SQL wykombinuje, kiedy/jak korzystać z indeksu.

W wielu przypadkach, podczas optymalizacji, musisz przeczytać dokumenty danego systemu DBMS, aby dowiedzieć się więcej o tym, jak używa indeksów, i powiązać je z zapytaniami aplikacji, z której korzystasz. Następnie możesz dostroić użycie indeksu.