{"id":1059,"date":"2008-05-07T18:58:11","date_gmt":"2008-05-07T16:58:11","guid":{"rendered":"http:\/\/www.glorf.it\/blog\/2008\/05\/07\/sql-talk\/performance\/sql-server-2005-pivot-und-performance"},"modified":"2008-05-11T11:07:21","modified_gmt":"2008-05-11T09:07:21","slug":"sql-server-2005-pivot-und-performance","status":"publish","type":"post","link":"http:\/\/www.glorf.it\/blog\/2008\/05\/07\/sql-talk\/performance\/sql-server-2005-pivot-und-performance","title":{"rendered":"SQL-Server-2005: PIVOT und Performance"},"content":{"rendered":"<p>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 &quot;SQL-Server-2005: schnelles Pivot?&quot;. Diese Serie soll meine Erfahrungen weitergeben und bei Verstehen der Zusammenh&#228;nge helfen. Mit ein paar Kniffen kann man dann die Ausf&#252;hrung erheblich beschleunigen. Der Quellcode zu diesem vorletzten Artikel steht &#252;brigens <a href=\"http:\/\/www.glorf.it\/files\/200710_pivot\/05_pivot_performance.sql\">hier<\/a>. <\/p>\n<ul>\n<li><a href=\"http:\/\/www.glorf.it\/blog\/2008\/05\/03\/sql-talk\/performance\/sql-server-2005-schnelles-pivot\">Artikel 1: Wie wird Pivot abgearbeitet?<\/a><\/li>\n<li><a href=\"http:\/\/www.glorf.it\/blog\/2008\/05\/05\/sql-talk\/performance\/sql-server-2005-stoerer-beim-pivot-eliminieren\">Artikel 2: St&#246;rer beim PIVOT eliminieren<\/a><\/li>\n<li><a href=\"http:\/\/www.glorf.it\/blog\/2008\/05\/07\/sql-talk\/performance\/sql-server-2005-pivot-und-performance\">Artikel 3: Pivot-Performance<\/a><\/li>\n<li><a href=\"http:\/\/www.glorf.it\/blog\/2008\/05\/09\/sql-talk\/performance\/sql-server-2005-pivot-auf-joins\">Artikel 4: Pivot-Performance mit Joins<\/a><\/li>\n<\/ul>\n<p><strong>Performance<\/strong><\/p>\n<p>Um ein Gef&#252;hl daf&#252;r zu bekommen, wird die im <a href=\"http:\/\/www.glorf.it\/blog\/2008\/05\/03\/sql-talk\/performance\/sql-server-2005-schnelles-pivot\">ersten Artikel<\/a> beschriebene Tabelle &quot;OpenSchema&quot; mit 1,9 Mio Datens&#228;tzen gef&#252;llt und ausgelesen. Interessant ist, wie viel &quot;Overhead&quot; ein PIVOT ausmacht. Wenn man ein SELECT auf die ganze Tabelle mit einem PIVOT im gleichen Batch ausf&#252;hrt und dazu mit &quot;Strg+M&quot; den tats&#228;chlichen Zugriffsplan anzeigen l&#228;sst, dann bekommt man neben den Zugriffspl&#228;nen auch den gesch&#228;tzten, prozentualen Anteil der Statements im Batch.<\/p>\n<p><code lang=\"sql\">SELECT ID, Attribute, \"Value\"<br \/>\n\tFROM OpenSchema<\/p>\n<p>SELECT ID, attr1 as Typ, attr2 as Datum, attr3 as Anzahl, attr4 as Dings, attr5 as Bums<br \/>\nFROM \tOpenSchema<br \/>\n\tPIVOT<br \/>\n\t(<br \/>\n\t\tMax(&quot;Value&quot;)<br \/>\n\t\tFOR Attribute IN (&quot;attr1&quot;, &quot;attr2&quot;, &quot;attr3&quot;, &quot;attr4&quot;, &quot;attr5&quot;)<br \/>\n\t) AS pvt<br \/>\nORDER BY ID<\/code><\/p>\n<p>Liegt ein Clustered-Index auf der Spalte ID, dann ist das Verh&#228;ltnis 44% zu 56%. Das bedeutet, der Optimizer sch&#228;tzt etwa 22% Aufschlag f&#252;r den PIVOT gegen&#252;ber dem einfachen Auslesen. Das deckt sich mit dem Zugriffsplan des PIVOT: Hier ben&#246;tigt das einfache Lesen auch 78%:<\/p>\n<p>Das &#228;ndert sich allerdings dramatisch, wenn kein geeigneter Index vorhanden ist. Dann ist das Verh&#228;ltnis im Batch 1% zu 99%.<\/p>\n<p>Da f&#252;r die Gruppierung bereits anhand der ID sortiert werden muss, hat das nachfolgende \u201eORDER BY ID\u201c tats&#228;chlich keinerlei Auswirkungen auf den Zugriffsplan. Das sieht allerdings anders aus, falls man nach anderen Kriterien sortieren l&#228;sst. Das wird aber nur ben&#246;tigt, wenn man Joins im PIVOT verwendet. dazu komme ich im letzten Artikel.<\/p>\n<p>Zusammenfassend kann man sagen, dass ein PIVOT immer dann &quot;schnell&quot; ist, wenn ein Clustered Index auf den Gruppierungsfeldern liegt. Ein normaler Index hilft hier nicht weiter. Wie schnell er tats&#228;chlich ist, h&#228;ngt &#8211; wie immer &#8211; von der darunter liegenden Hardware ab&#8230;<\/p>\n<div class=\"small\">Diese Reihe schrieb ich letzten Oktober als Reaktion auf den Aufruf im SQL-PASS-Newsletter. M&#246;glicherweise erscheint der Artikel noch dort. Ich ver&#246;ffentliche ihn jetzt aber lieber mal bevor er mit dem bald erscheinenden SQL-Server-2008 m&#246;glicherweise veraltet&#8230; \ud83d\ude09<\/div>\n","protected":false},"excerpt":{"rendered":"<p>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 &quot;SQL-Server-2005: schnelles Pivot?&quot;. Diese Serie soll meine Erfahrungen weitergeben und bei Verstehen der Zusammenh&#228;nge helfen. Mit ein paar Kniffen kann man dann die Ausf&#252;hrung erheblich beschleunigen. Der Quellcode zu diesem vorletzten [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[18],"tags":[930,51,929],"_links":{"self":[{"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/posts\/1059"}],"collection":[{"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/comments?post=1059"}],"version-history":[{"count":0,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/posts\/1059\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/media?parent=1059"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/categories?post=1059"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/tags?post=1059"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}