2009-12-28 23 views
20

Próbuję poprawić wydajność kwerendy, która działa bardzo wolno. Po przejściu przez rzeczywisty plan wykonania; Zauważyłem, że indeks klastrowany osiąga 82%. Czy jest jakiś sposób, aby poprawić wydajność na Index Seek? Poniżej znajduje się obraz problemu z planu wykonania, a także indeks i tabela, z których korzysta.Jak poprawić wydajność w indeksie klastrowym wyszukaj

alt text http://img340.imageshack.us/img340/1346/seek.png

Index:

/****** Object: Index [IX_Stu] Script Date: 12/28/2009 11:11:43 ******/ 
CREATE CLUSTERED INDEX [IX_Stu] ON [dbo].[stu] 
(
[StuKey] ASC 
)WITH (PAD_INDEX = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY] 

stołowe (niektóre kolumny pominięty dla zwięzłość):

CREATE TABLE [dbo].[stu](
[StuCertKey] [int] IDENTITY(1,1) NOT NULL, 
[StuKey] [int] NULL 
CONSTRAINT [PK_Stu] PRIMARY KEY NONCLUSTERED 
(
[StuCertKey] ASC 
)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF, FILLFACTOR = 80) ON [PRIMARY] 
) ON [PRIMARY] 
+2

"To zależy." ... – RBarryYoung

+0

Czy jest to zły pomysł, aby indeks klastrowany był ustawiony na coś innego niż klucz podstawowy? Kwerenda nigdy nie używa klucza podstawowego, więc uznałem, że lepiej byłoby utworzyć indeks klastrowany w kolumnie, która jest połączona najbardziej (StuKey) –

+1

Czy możesz opublikować zapytanie. Ponadto wiele wierszy znajduje się w tabeli, a w przybliżeniu ile jest zwracanych przez zapytanie? – dan

Odpowiedz

14

Jestem tutaj generalizować, ale ...

klastrowym indeks poszukiwania jest w przeważającej części, w najlepszym wypadku. Jedynymi sposobami, które mogę poprawić w celu zwiększenia wydajności, są:

  • Zaktualizuj zapytanie, aby zwrócić mniej wierszy/kolumn, jeśli to możliwe;
  • Defragmentuj lub odbuduj indeks;
  • Podział indeksu na wiele dysków/serwerów.

Jeśli zwraca tylko 138 wierszy, i jest to powolne ... może jest blokowane przez inny proces? Czy testujesz to w odosobnieniu, czy też inni użytkownicy/procesy są online w tym samym czasie? A może to nawet problem sprzętowy, taki jak awaria dysku.

+0

Może być kilku innych użytkowników, ale niewielu. Również jest to zapytanie DW. Jeśli w bazie danych nie ma aktualizacji, nie powinno być żadnych blokad, które uniemożliwiałyby czytanie, prawda? –

+0

Niektóre inne procesy mogą wykonywać 'SELECT * FROM stu' bez filtra, odzyskując wszystkie 8 milionów wierszy; to zdecydowanie spowolniłoby inne zapytania z powodu wąskiego gardła wejścia/wyjścia. Jest mało prawdopodobne, ale możliwe. – Aaronaught

1

Czy próbowałeś pewne utrzymanie tego wskaźnika? Jak to defragmentować? Wydaje się naprawdę dziwne, że kosztuje to tyle (120.381). Wyszukiwanie indeksu jest najszybszą operacją indeksu, nie powinno zająć tyle czasu. Czy możesz wysłać zapytanie?

+0

Wolę nie publikować zapytania. Pozwól mi rzucić okiem na to, co robi defragmentacja ... –

+0

Jakieś sugestie na temat tego, jak dużo defragmentacji jest zbyt daleko odkreślania? –

0

Przebudować indeks i obliczyć statystyki?

Jedyny inny sposób, w jaki mogę go przyspieszyć to podział na partycje, co może, ale nie musi być możliwe.

+0

Próbowano przebudowywać indeksy i statystyki. bez powodzenia. Być może zastanawiam się nad podzieleniem tabel na następne. Czy to dobre rozwiązanie dla powolnych poszukiwań? –

3

Myśli ...

  • Dlaczego IX_Stu skupione? Wewnętrznie SQL Server dodaje 4-bajtowy "unikatnik" do nieunikalnych indeksów klastrowych. Jakie jest uzasadnienie? Spowoduje to również naderwanie twojego PK również

  • Jakie jest aktualne zapytanie?

  • Wreszcie, dlaczego FILLFACTOR 80%?

Edit:

  • A "normalne" FILLFACTOR byłoby 90%, ale jest to regułą tylko

  • An 11 zapytań przyłączyć? To najprawdopodobniej twój problem.Jakie są twoje postanowienia JOIN, WHERE itd.? Jaki jest plan pełnego tekstu?

+2

Jeśli chodzi o pierwsze pytanie, zrobiłem IX_Stu w klastrze, ponieważ będzie on używany w przypadku większości złączeń. Myślałem, że to poprawi wydajność, czy jestem tutaj pomieszany? Drugie pytanie, wolałbym nie publikować zapytania w Internecie, jeśli mogę tego uniknąć. Jest bardzo duży z jedenaście złączeń, jeśli to ci pomoże ... Ostatnie pytanie: Stworzyłem indeks przez studio zarządzania, a nie przez zapytanie. Najwyraźniej studio zarządzania dodało FILLFACTOR 80%. Czy to może powodować problemy? –

1

Co się dzieje, jeśli ciężko kodzie GDZIE kryteria, na przykład:

SELECT StuCertKey, StuKey FROM stu 
WHERE stuKey in (/* list 50 values of StuKey here */) 

Jeśli to wciąż bardzo powolny, masz problem wewnętrzny pewnego rodzaju. Jeśli jest szybszy, to indeks nie jest wąskim gardłem, to robisz, by stworzyć filtr WHERE.

Należy pamiętać, że SELECT * może być bardzo powolny, jeśli istnieje wiele dużych kolumn, a zwłaszcza jeśli istnieją BLOBy.

6

Klastrowany zakres indeksów wyszukiwania, który zwraca 138 wierszy, nie jest problemem.

Technicznie można zwiększyć wydajność poszukiwania poprzez indeks klastrowany węższy:

Oba mogą mieć bardzo dramatyczny wpływ na czas wyszukiwania, ponieważ zmniejszają IO i potrzebę trafienia w fizyczne odczyty. Oczywiście, jak zwykle, wynik będzie się różnić w zależności od dużej liczby innych czynników, takich jak to, jakie kolumny projektujesz (eksmisja wyświetlanej kolumny na jednostkę alokacji BLOB może w rzeczywistości mieć negatywny wpływ na niektóre zapytania). Na marginesie, zazwyczaj fragmentacja będzie miała tylko marginalny wpływ na taki krótki zasięg. Znowu to zależy.

Ale jak mówię, bardzo wątpię, że to jest twój prawdziwy problem. Wysłałeś tylko wybrane części planu i wyniki własnej analizy. Prawdziwa pierwotna przyczyna może leżeć zupełnie gdzie indziej.

1

Kilka ogólnych porad: kiedy muszę przeprowadzić optymalizację zapytań, zaczynam od napisania tego, co myślę, że powinien być plan wykonania.

Po podjęciu decyzji o tym, jaki powinien być plan wykonania, staram się, aby aktualne zapytanie pasowało do tego planu. Techniki do tego są różne dla każdego DBMS i niekoniecznie przechodzą z jednego do drugiego, a nawet czasami między różnymi wersjami DBMS.

Należy pamiętać, że DBMS może realizować tylko jedno przyłączenie naraz: zaczyna się od dwóch początkowych tabel, łączy je, a następnie przyjmuje wynik tej operacji i dołącza ją do następnej tabeli. Celem każdego kroku jest zminimalizowanie liczby wierszy w pośrednim zestawie wyników (bardziej poprawnie, w celu zminimalizowania liczby bloków, które należy odczytać w celu uzyskania wyników pośrednich, ale zazwyczaj oznacza to mniej wierszy).

+1

Interesujące. Załóżmy, że wiem, że pewne sprzężenie zmniejsza mój zestaw z 6 milionów wierszy do około 500 000. Czy poprawi to wydajność, aby ten Join pojawił się przed innymi połączeniami, czy może utworzył CTE, który zawiera zawartość tego łączenia, a następnie używał tego w przyszłości? –

10

Wyszukiwanie indeksów pojawia się, gdy używane są indeksy nieklastrowe i niekoniecznie są złe.

Rozważmy następujące zapytanie:

SELECT s.StuKey, s.Name, s.Address, s.City, s.State FROM stu s WHERE State='TX' 

Jeśli istnieje tylko skupione indeks StuKey, następnie SQL Server ma tylko 1 opcja, musi zeskanować całą tabelę szuka wierszy gdzie State = "TX” i zwróć te wiersze.

Jeśli dodasz nieklastrowanym indeksu państwa

CREATE INDEX IX_Stu_State on Stu (State) 

serwera SQL teraz ma nową opcję. Może wybrać wyszukiwanie przy użyciu indeksu nieklastrowego, który wygeneruje wiersze, w których State = "TX". Jednakże, aby uzyskać pozostałe kolumny do zwrócenia w SELECT, musi wyszukać te kolumny, wykonując indeks klastrowy w poszukiwaniu każdego wiersza.

Jeśli chcesz zmniejszyć indeks klastrowany, możesz ustawić indeks jako "obejmujący", dodając do niego dodatkowe kolumny.

CREATE INDEX IX_Stu_State2 on Stu (State) INCLUDE (name, address, city) 

Indeks ten zawiera teraz wszystkie kolumny potrzebne, aby odpowiedzieć na zapytanie powyżej. Zapytanie wykona indeks wyszukiwania, aby zwrócić tylko te wiersze, w których State = "TX", a dodatkowe kolumny mogą być wyciągnięte z indeksu nieklastrowego, więc indeks klastrowany szuka go.

1

Sprawdź statystyki indeksowe.

reCalculating statystyki indeks klastrowy rozwiąże problem.

w moim przypadku, szukałem 30 rekordów w 40M zregenerowanych. Plan wykonania mówi, że przechodzi przez indeks klastrowy, ale zajęło to około 200ms. a indeks nie został zdefragmentowany. po ponownym obliczeniu statystyk robi się to poniżej 10 ms!