Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Verbessern Sie die SQL Server-Abfrageleistung bei großen Tabellen

Einfache Antwort:NEIN. Ad-hoc-Abfragen in einer 238-Spalten-Tabelle mit einem Füllfaktor von 50 % im Clustered-Index können nicht unterstützt werden.

Ausführliche Antwort:

Wie ich in anderen Antworten zu diesem Thema gesagt habe, ist Indexdesign sowohl Kunst als auch Wissenschaft, und es gibt so viele Faktoren zu berücksichtigen, dass es nur wenige, wenn überhaupt, feste Regeln gibt. Sie müssen Folgendes berücksichtigen:das Volumen der DML-Operationen im Vergleich zu SELECTs, das Festplattensubsystem, andere Indizes / Trigger in der Tabelle, die Verteilung der Daten innerhalb der Tabelle, Abfragen mit SARGable WHERE-Bedingungen und einige andere Dinge, an die ich mich nicht einmal richtig erinnern kann jetzt.

Ich kann sagen, dass bei Fragen zu diesem Thema keine Hilfe geleistet werden kann, ohne die Tabelle selbst, ihre Indizes, Trigger usw. zu verstehen. Jetzt, da Sie die Tabellendefinition gepostet haben (warten immer noch auf die Indizes, aber die Tabellendefinition allein weist darauf hin). 99 % der Ausgabe) kann ich einige Vorschläge machen.

Erstens, wenn die Tabellendefinition korrekt ist (238 Spalten, 50% Füllfaktor), können Sie den Rest der Antworten / Ratschläge hier so gut wie ignorieren;-). Tut mir leid, hier weniger als politisch zu sein, aber im Ernst, es ist eine wilde Gänsejagd, ohne die Einzelheiten zu kennen. Und jetzt, wo wir die Tabellendefinition sehen, wird deutlicher, warum eine einfache Abfrage so lange dauern würde, selbst wenn die Testabfragen (Update Nr. 1) so schnell liefen.

Das Hauptproblem hier (und in vielen Situationen mit schlechter Leistung) ist eine schlechte Datenmodellierung. 238 Spalten sind nicht verboten, genauso wie 999 Indizes nicht verboten sind, aber es ist im Allgemeinen auch nicht sehr klug.

Empfehlungen:

  1. Zunächst muss dieser Tisch wirklich umgebaut werden. Wenn dies eine Data Warehouse-Tabelle ist, dann vielleicht, aber wenn nicht, müssen diese Felder wirklich in mehrere Tabellen aufgeteilt werden, die alle denselben PK haben können. Sie hätten eine Master-Datensatztabelle und die untergeordneten Tabellen sind nur abhängige Informationen, die auf gemeinsam zugeordneten Attributen basieren, und der PK dieser Tabellen ist derselbe wie der PK der Master-Tabelle und daher auch FK für die Master-Tabelle. Zwischen Master- und allen untergeordneten Tabellen besteht eine 1-zu-1-Beziehung.
  2. Die Verwendung von ANSI_PADDING OFF ist störend, ganz zu schweigen von der Inkonsistenz innerhalb der Tabelle aufgrund der verschiedenen Spaltenzusätze im Laufe der Zeit. Nicht sicher, ob Sie das jetzt beheben können, aber idealerweise hätten Sie immer ANSI_PADDING ON , oder haben zumindest die gleiche Einstellung für alle ALTER TABLE Aussagen.
  3. Erwägen Sie, zwei zusätzliche Dateigruppen zu erstellen:Tabellen und Indizes. Es ist am besten, Ihre Sachen nicht in PRIMARY zu legen denn dort speichert SQL SERVER alle seine Daten und Metadaten zu Ihren Objekten. Sie erstellen Ihre Tabelle und Ihren Clustered Index (da dies die Daten für die Tabelle sind) auf [Tables] und alle Non-Clustered-Indizes auf [Indexes]
  4. Erhöhen Sie den Füllfaktor von 50 %. Diese niedrige Zahl ist wahrscheinlich der Grund dafür, dass Ihr Indexbereich größer ist als Ihr Datenbereich. Wenn Sie einen Index-Neuaufbau durchführen, werden die Datenseiten mit maximal 4 KB (von der gesamten Seitengröße von 8 KB) neu erstellt, die für Ihre Daten verwendet werden, sodass Ihre Tabelle über einen großen Bereich verteilt ist.
  5. Wenn die meisten oder alle Abfragen "ER101_ORG_CODE" im WHERE haben Bedingung, ziehen Sie dann in Betracht, diese in die führende Spalte des Clustered-Index zu verschieben. Vorausgesetzt, es wird häufiger verwendet als "ER101_ORD_NBR". Wenn "ER101_ORD_NBR" häufiger verwendet wird, dann behalte es. Unter der Annahme, dass die Feldnamen "OrganizationCode" und "OrderNumber" bedeuten, scheint es, dass "OrgCode" eine bessere Gruppierung ist, die möglicherweise mehrere "OrderNumbers" enthält.
  6. Kleiner Punkt, aber wenn "ER101_ORG_CODE" immer 2 Zeichen lang ist, dann verwenden Sie CHAR(2) statt VARCHAR(2) da es ein Byte im Zeilenheader spart, das variable Breiten verfolgt und sich über Millionen von Zeilen summiert.
  7. Wie andere hier bereits erwähnt haben, verwenden Sie SELECT * wird die Leistung beeinträchtigen. Nicht nur, weil SQL Server alle Spalten zurückgeben muss und daher unabhängig von Ihren anderen Indizes mit größerer Wahrscheinlichkeit einen Clustered Index Scan durchführt, sondern es dauert auch, bis SQL Server zur Tabellendefinition wechselt und * in alle Spaltennamen. Es sollte leicht sein schneller, alle 238 Spaltennamen im SELECT anzugeben Liste, aber das hilft nicht beim Scan-Problem. Aber braucht man wirklich jemals alle 238 Spalten gleichzeitig?

Viel Glück!

AKTUALISIEREN
Der Vollständigkeit halber zur Frage "wie man die Leistung einer großen Tabelle für Ad-hoc-Abfragen verbessert", sei angemerkt, dass dies zwar in diesem speziellen Fall nicht hilfreich ist, WENN jemand SQL Server 2012 verwendet (oder neuer, wenn dieser Zeitpunkt kommt) und wenn die Tabelle nicht aktualisiert wird, ist die Verwendung von Columnstore-Indizes eine Option. Weitere Einzelheiten zu dieser neuen Funktion finden Sie hier:http://msdn.microsoft.com/en-us/library/gg492088.aspx (Ich glaube, diese wurden so gestaltet, dass sie ab SQL Server 2014 aktualisierbar sind).

AKTUALISIERUNG 2
Zusätzliche Überlegungen sind:

  • Aktivieren Sie die Komprimierung für den Clustered Index. Diese Option wurde in SQL Server 2008 verfügbar, jedoch nur als Feature der Enterprise Edition. Allerdings ab SQL Server 2016 SP1 , Datenkomprimierung wurde in allen Editionen verfügbar gemacht! Einzelheiten zur Zeilen- und Seitenkomprimierung finden Sie auf der MSDN-Seite für Datenkomprimierung.
  • Wenn Sie die Datenkomprimierung nicht verwenden können oder wenn sie für eine bestimmte Tabelle keinen großen Nutzen bringt, dann WENN Sie eine Spalte mit fester Länge haben (INT , BIGINT , TINYINT , SMALLINT , CHAR , NCHAR , BINARY , DATETIME , SMALLDATETIME , MONEY usw.) und weit über 50 % der Zeilen sind NULL , ziehen Sie dann die Aktivierung von SPARSE in Betracht Option, die in SQL Server 2008 verfügbar wurde. Weitere Informationen finden Sie auf der MSDN-Seite für Use Sparse Columns.