Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Popraw wydajność zapytań SQL Server na dużych tabelach

Prosta odpowiedź:NIE. Nie można pomóc kwerendom ad hoc w tabeli 238 kolumn z 50% współczynnikiem wypełnienia indeksu klastrowego.

Szczegółowa odpowiedź:

Jak już wspomniałem w innych odpowiedziach na ten temat, projektowanie indeksów jest zarówno sztuką, jak i nauką i jest tak wiele czynników, które należy wziąć pod uwagę, że istnieje niewiele, jeśli w ogóle, twardych i szybkich zasad. Trzeba wziąć pod uwagę:wielkość operacji DML vs SELECTy, podsystem dyskowy, inne indeksy/triggery w tabeli, dystrybucja danych w tabeli, to zapytania używające warunków SARGable WHERE i kilka innych rzeczy, których nawet nie pamiętam dobrze teraz.

Mogę powiedzieć, że nie można udzielić pomocy w przypadku pytań na ten temat bez zrozumienia samej tabeli, jej indeksów, wyzwalaczy itp. Teraz, gdy opublikowałeś definicję tabeli (wciąż czekasz na indeksy, ale sama definicja tabeli wskazuje na 99% problemu) Mogę zaoferować kilka sugestii.

Po pierwsze, jeśli definicja tabeli jest dokładna (238 kolumn, 50% współczynnik wypełnienia), możesz zignorować resztę odpowiedzi / porad tutaj;-). Przepraszam, że jestem mniej niż polityczny tutaj, ale poważnie, to szalona pogoń za dzikimi gęsiami bez znajomości szczegółów. A teraz, gdy widzimy definicję tabeli, staje się nieco jaśniejsze, dlaczego proste zapytanie zajęłoby tak długo, nawet jeśli zapytania testowe (aktualizacja nr 1) przebiegały tak szybko.

Głównym problemem tutaj (i w wielu sytuacjach o niskiej wydajności) jest złe modelowanie danych. 238 kolumn nie jest zabronione, podobnie jak posiadanie 999 indeksów nie jest zabronione, ale generalnie nie jest to zbyt mądre.

Zalecenia:

  1. Po pierwsze, ten stół naprawdę wymaga przebudowy. Jeśli jest to tabela hurtowni danych, to może, ale jeśli nie, to te pola naprawdę muszą zostać podzielone na kilka tabel, z których każda może mieć tę samą PK. Miałbyś główną tabelę rekordów, a tabele podrzędne są tylko informacjami zależnymi opartymi na powszechnie powiązanych atrybutach, a PK tych tabel jest takie samo jak PK tabeli głównej, a zatem również FK do tabeli głównej. Będzie relacja 1 do 1 między tabelami głównymi i wszystkimi tabelami podrzędnymi.
  2. Korzystanie z ANSI_PADDING OFF jest niepokojące, nie wspominając o niespójności w tabeli ze względu na różne dodawanie kolumn w czasie. Nie jestem pewien, czy możesz to teraz naprawić, ale najlepiej zawsze mieć ANSI_PADDING ON , lub przynajmniej mieć to samo ustawienie we wszystkich ALTER TABLE oświadczenia.
  3. Rozważ utworzenie 2 dodatkowych grup plików:tabel i indeksów. Najlepiej nie umieszczać swoich rzeczy w PRIMARY ponieważ to tam SQL SERVER przechowuje wszystkie swoje dane i metadane dotyczące twoich obiektów. Tworzysz tabelę i indeks klastrowy (jako że są to dane dla tabeli) na [Tables] i wszystkie indeksy nieklastrowe na [Indeksy]
  4. Zwiększ współczynnik wypełnienia z 50%. Ta niska liczba jest prawdopodobnie powodem, dla którego przestrzeń indeksu jest większa niż przestrzeń danych. Wykonanie przebudowy indeksu spowoduje odtworzenie stron danych z maksymalnym rozmiarem 4k (z całkowitego rozmiaru strony 8k) używanych dla danych, dzięki czemu tabela jest rozłożona na dużym obszarze.
  5. Jeśli większość lub wszystkie zapytania mają „ER101_ORG_CODE” w WHERE warunek, a następnie rozważ przeniesienie go do wiodącej kolumny indeksu klastrowego. Zakładając, że jest używany częściej niż „ER101_ORD_NBR”. Jeśli „ER101_ORD_NBR” jest używane częściej, zachowaj je. Po prostu wydaje się, zakładając, że nazwy pól oznaczają „OrganizationCode” i „OrderNumber”, że „OrgCode” jest lepszą grupą, która może zawierać wiele „OrderNumbers”.
  6. Mniejszy punkt, ale jeśli „ER101_ORG_CODE” ma zawsze 2 znaki, użyj CHAR(2) zamiast VARCHAR(2) ponieważ zapisze bajt w nagłówku wiersza, który śledzi rozmiary o zmiennej szerokości i dodaje ponad miliony wierszy.
  7. Jak wspomnieli inni, używając SELECT * zaszkodzi wydajności. Nie tylko ze względu na to, że SQL Server wymaga zwrócenia wszystkich kolumn, a tym samym zwiększa prawdopodobieństwo wykonania klastrowego skanowania indeksu niezależnie od innych indeksów, ale także przejście do definicji tabeli i przetłumaczenie * do wszystkich nazw kolumn. Powinno być nieco szybciej określić wszystkie 238 nazw kolumn w SELECT Lista jednak nie pomoże w problemie ze skanowaniem. Ale czy naprawdę potrzebujesz wszystkich 238 kolumn jednocześnie?

Powodzenia!

AKTUALIZUJ
Dla kompletności pytania "jak poprawić wydajność na dużej tabeli dla zapytań ad-hoc", należy zauważyć, że chociaż nie pomoże w tym konkretnym przypadku, JEŚLI ktoś używa SQL Server 2012 (lub nowsze, gdy nadejdzie ten czas) i JEŚLI tabela nie jest aktualizowana, to użycie indeksów magazynu kolumn jest opcją. Aby uzyskać więcej informacji na temat tej nowej funkcji, zajrzyj tutaj:http://msdn.microsoft.com/en-us/library/gg492088.aspx (wierzę, że zostały one stworzone, aby można je było aktualizować od SQL Server 2014).

AKTUALIZACJA 2
Dodatkowe uwagi to:

  • Włącz kompresję w indeksie klastrowym. Ta opcja stała się dostępna w programie SQL Server 2008, ale jako funkcja dostępna tylko w wersji Enterprise Edition. Jednak od SQL Server 2016 SP1 , Kompresja danych została udostępniona we wszystkich edycjach! Zobacz stronę MSDN dotyczącą kompresji danych, aby uzyskać szczegółowe informacje na temat kompresji wierszy i stron.
  • Jeśli nie możesz użyć kompresji danych lub jeśli nie przyniesie to większych korzyści dla określonej tabeli, to JEŚLI masz kolumnę typu o stałej długości (INT , BIGINT , TINYINT , MAŁE , ZNAK , NCHAR , BINARNY , DATETIME , SMALLDATETIME , PIENIĄDZE , itp) i znacznie ponad 50% wierszy ma wartość NULL , a następnie rozważ włączenie opcji SPARSE opcja, która stała się dostępna w SQL Server 2008. Aby uzyskać szczegółowe informacje, zobacz stronę MSDN, aby uzyskać informacje na temat używania rzadkich kolumn.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL Query wolno w aplikacji .NET, ale natychmiastowo w SQL Server Management Studio

  2. Ograniczanie jednoczesnych sesji użytkowników dla określonego logowania w SQL Server

  3. Instrukcja usuwania SQL Server:jak usunąć jeden lub wiele wierszy z tabeli

  4. Zarządzaj plikami MDF w SQL Server 2019

  5. Konwertuj obiekt SQL Server DateTime na BIGINT (takty .Net)