Frage

Ich versuche zu verstehen, warum die Verwendung einer Tabellenvariablen verhindert, dass der Optimierer mit einem Indexsuche mit einem Indexsuche mit einem Index-Scan verwendet wird.

Bevölkerung der Tabelle:

generasacodicetagpre.

Füllen Sie eine Tabellenvariable mit einem einzelnen Datensatz und versuchen Sie, den Primärschlüssel und die zweite Spalte zu suchen, indem Sie auf der Spalte Fremdschlüssel suchen:

generasacodicetagpre.

ist der Ausführungsplan:

 Geben Sie hier eingeben Beschreibung hier eingeben

jetzt die gleiche Abfrage mit einer Temp-Tabelle stattdessen:

generasacodicetagpre.

Dieser Abfrageplan verwendet ein Such- und Bookmark-Lookup:

 Geben Sie hier eingeben Beschreibung hier eingeben

Warum ist der Optimierer bereit, der Bookmark-Lookup mit der Temp-Tabelle, aber nicht die Tabellenvariable?

Die Tabellenvariable wird in diesem Beispiel verwendet, um Daten darzustellen, die durch einen benutzerdefinierten Tabellentyp in einer gespeicherten Prozedur kommen.

Ich realisiere, dass der Indexsuche möglicherweise nicht angemessen ist, wenn der Fremdschlüsselwert Hunderttausende Male auftrat. In diesem Fall wäre ein Scan wahrscheinlich eine bessere Wahl. Für das Szenario, das ich geschaffen habe, gab es keine Zeile mit einem Wert von 10. Ich denke immer noch, dass das Verhalten interessant ist und möchte wissen, ob es einen Grund dafür gibt.

sql feige

Hinzufügen von generationspflichtigem Maschinensatz änderte das Verhalten nicht. Das UDDT hat einen primären Schlüssel.

OPTION (RECOMPILE) ist SQL Server 2008 R2 (SP2) - 10.50.4042.0 (X64) (Build 7601: Service Pack 1) (Hypervisor)

War es hilfreich?

Lösung

Der Grund für das Verhalten ist, dass SQL Server nicht bestimmen kann, wie viele Zeilen dem Auslössamkeit übereinstimmen, da es keinen Index mit RowKey als führende Spalte gibt (sie kann dies von Statistiken auf der #TEMP-Tabelle ableiten, aber diese Es gibt nicht für Tabellenvariablen / UDTTS), daher ist es eine Schätzung von 100.000 Zeilen, die besser mit einem Scan als einer Suche + Lookup gehandhabt wird. Durch den Zeitpunkt der Zeit, dessen SQL Server erkennt, gibt es nur eine Zeile, es ist zu spät.

Sie können Ihre UDTT möglicherweise anders erstellen. In moderneren Versionen von SQL Server können Sie sekundäre Indizes auf Tabellenvariablen erstellen, diese Syntax ist jedoch im Jahr 2008 nicht verfügbar R2.

BTW Sie können das Suchverhalten (zumindest in meinen limitierten Studien) abrufen, wenn Sie versuchen, die Bitmap / Sonde zu vermeiden, indem Sie einen verschachtelten Loops anheften, teilnehmen:

generasacodicetagpre.

i diesen Trick von Paul White vor einigen Jahren gelernt. Natürlich sollten Sie vorsichtig sein, um jegliche Art von Join-Hinweisen in Produktionscode anzugeben. Dies kann fehlschlagen, wenn die Personen Änderungen an den zugrunde liegenden Objekten vornehmen, und dass ein bestimmter Typ der Join nicht mehr möglich ist oder nicht mehr optimal ist.

für komplexere Abfragen, und wenn Sie nach SQL Server 2012 oder höher wechseln, ist dies möglich, dass Trace-Flagge 2453 könnte helfen. Diese Flagge hat jedoch nicht bei diesem einfachen Join geholfen. Und die gleichen Haftungsausschlüsse würden sich anwenden - dies ist nur eine Alternative, die Sie im Allgemeinen nicht ohne eine Tonne Dokumentation und strenge Regressionsprüfverfahren tun sollten.

auch Service Pack 1 ist lange außerhalb des Supports, Sie sollten Service Pack 3 + MS15-058 .

Andere Tipps

Tabellenvariablen und Temp-Tabellen werden auf verschiedene Arten unterschiedlich behandelt.Es gibt eine TollAntworten Sie hier mit vielen Besonderheiten, wo sie anders sind.

Insbesondere in Ihrem Fall würde ich vermuten, dass die Tatsache, dass Temp-Tabellen zusätzliche Statistiken generierte und parallele Pläne haben können, während Tabellenvariablen mehr begrenzte Statistiken (keine Spaltenebene-Statistiken) aufweisen, und keine parallelen Pläne sind Ihr Täter.

Sie können sehr gut sein, wenn Sie die Tabellenvariable für die Dauer der gespeicherten Prozedur in eine Temp-Tabelle in eine Temp-Tabelle dezentrieren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit dba.stackexchange
scroll top