Im Blogg von dieser Woche habe ich ja bereits ein paar Tipps zu Performance Steigerung mittels Index Statistiken gegeben – heute gehe ich noch einen Schritt weiter. Statistiken zu erstellen kann eine ganz aufwendige Sache sein, insbesondere wenn die Tabelle Millionen und mehr von Zeilen hat. Dies ist auch der Grund, warum der SQL Server per Default das Histogramm lediglich auf einem Subset aller Zeilen (Sample) bildet. Die Grösse des Samples bestimmt der SQL Server selbständig. Wenn du denkst, dass du smarter als der SQL Server bist, kannst du aber auch hier wiederum von Hand eingreifen:
UPDATE STATISTICS Person.Address IX_Address_AddressLine1_AddressLine2_City_StateProvinceID_PostalCode WITH SAMPLE 1 PERCENT
UPDATE STATISTICS Person.Address IX_Address_AddressLine1_AddressLine2_City_StateProvinceID_PostalCode WITH SAMPLE 1000 ROWS
UPDATE STATISTICS Person.Address IX_Address_AddressLine1_AddressLine2_City_StateProvinceID_PostalCode WITH FULLSCAN
FULLSCAN entspricht dabei einem SAMPLE 100 PERCENT.
Wie gesagt, ein Update der Statistik kann ganz schön lange dauern. Ein Query, das auf eine out-of-date Statistik stösst, muss warten bis diese Statistik aktualisiert wurde; erst dann kann das Query compiliert und ein Resultset zurückgegeben werden. Das kann zu unvorhersehbar langen Antwortzeiten führen, welchen auf Clientseite schon mal zu einem Timeout führen können. Um dem zu entgehen, kennt der SQL Server die DB Option, die Statistik asynchron zu aktualisieren:
ALTER DATABASE AdventureWorks
SET AUTO_UPDATE_STATISTICS_ASYNC ON
In diesem Falle wir die Statistik im Hintergrund aktualisiert. Queries welche in der Zwischenzeit diese Statistik benötigen werden nicht blockiert sondern verwenden die veraltete Statistik.
Wäre es nicht toll, wenn dir der SQL Server erzählen würde, welche Indizes er gerne hätte um noch effizienter arbeiten zu können? Genau hierfür gibt es eine Dynamic Management View:
SELECT object_name(object_id, database_id) as ‘Object’
,equality_columns
,inequality_columns
,included_columns
FROM sys.dm_db_missing_index_details
Das Resultat kann etwa wie folgt aussehen:
| Object | equality_columns | inequality_columns | included_columns |
| Address | [ModifiedDate] | NULL | NULL |
Mit dieser Information kannst du deinen fehlenden Index leicht bilden:
CREATE INDEX NewIndex
ON <Object>(<equality_columns>,<inequality_columns>)
INCLUDE (<included_columns>)
WITH DROP_EXISTING
Oder konkret:
CREATE INDEX Adress_ModDate_Index
ON Address(ModifiedDate)
WITH DROP_EXISTING
Aber Achtung: Diese Daten sind nur solange durch die Dynamic Management View verfügbar, bis du den SQL Server neu startest oder aber an der zugrunde liegenden Tabelle eine Schema Änderung vornimmst.




