Als ich mit dem PIVOT-Konstrukt arbeitete und performante Ergebnisse haben wollte, muss ich erst verstehen, wie es intern arbeitet. Das beschrieb ich im Artikel "SQL-Server-2005: schnelles Pivot?". Diese Serie soll meine Erfahrungen weitergeben und bei Verstehen der Zusammenhänge helfen. Mit ein paar Kniffen kann man dann die Ausführung erheblich beschleunigen. Der Quellcode zu diesem vorletzten Artikel steht übrigens hier.
Performance
Um ein Gefühl dafür zu bekommen, wird die im ersten Artikel beschriebene Tabelle "OpenSchema" mit 1,9 Mio Datensätzen gefüllt und ausgelesen. Interessant ist, wie viel "Overhead" ein PIVOT ausmacht. Wenn man ein SELECT auf die ganze Tabelle mit einem PIVOT im gleichen Batch ausführt und dazu mit "Strg+M" den tatsächlichen Zugriffsplan anzeigen lässt, dann bekommt man neben den Zugriffsplänen auch den geschätzten, prozentualen Anteil der Statements im Batch.
SELECT ID, Attribute, "Value"
FROM OpenSchema
SELECT ID, attr1 as Typ, attr2 as Datum, attr3 as Anzahl, attr4 as Dings, attr5 as Bums
FROM OpenSchema
PIVOT
(
Max("Value")
FOR Attribute IN ("attr1", "attr2", "attr3", "attr4", "attr5")
) AS pvt
ORDER BY ID
Liegt ein Clustered-Index auf der Spalte ID, dann ist das Verhältnis 44% zu 56%. Das bedeutet, der Optimizer schätzt etwa 22% Aufschlag für den PIVOT gegenüber dem einfachen Auslesen. Das deckt sich mit dem Zugriffsplan des PIVOT: Hier benötigt das einfache Lesen auch 78%:
Das ändert sich allerdings dramatisch, wenn kein geeigneter Index vorhanden ist. Dann ist das Verhältnis im Batch 1% zu 99%.
Da für die Gruppierung bereits anhand der ID sortiert werden muss, hat das nachfolgende „ORDER BY ID“ tatsächlich keinerlei Auswirkungen auf den Zugriffsplan. Das sieht allerdings anders aus, falls man nach anderen Kriterien sortieren lässt. Das wird aber nur benötigt, wenn man Joins im PIVOT verwendet. dazu komme ich im letzten Artikel.
Zusammenfassend kann man sagen, dass ein PIVOT immer dann "schnell" ist, wenn ein Clustered Index auf den Gruppierungsfeldern liegt. Ein normaler Index hilft hier nicht weiter. Wie schnell er tatsächlich ist, hängt – wie immer – von der darunter liegenden Hardware ab…
Diese Reihe schrieb ich letzten Oktober als Reaktion auf den Aufruf im SQL-PASS-Newsletter. Möglicherweise erscheint der Artikel noch dort. Ich veröffentliche ihn jetzt aber lieber mal bevor er mit dem bald erscheinenden SQL-Server-2008 möglicherweise veraltet… 😉