Wir haben einen SQL-Generator, der generische SQL-Bedingungsanweisungen für bestimmte Felder ausgibt (was zur Diskussion: Wir werden als kennzeichnen myField
).
Wenn myField
es sich um einen Typ handelt NVARCHAR
, können wir dieses Feld mit einer Zeichenfolge wie folgt vergleichen : myField = 'foo'
.
Dies funktioniert jedoch nicht für Felder vom Typ NTEXT
. Wir müssen also den Vergleich mit einer Besetzung anstellen : CAST(myField as NVARCHAR(MAX)) = 'foo'
. Dies funktioniert in der Tat, wenn myField
es sich um einen Typ handelt NVARCHAR
oder NTEXT
.
Was ist der Leistungshit, wenn die oben genannte Besetzung auf einem Feld ausgeführt wird, das bereits vom Typ ist NVARCHAR
? Ich hoffe, dass SQL Server intelligent genug ist, um dynamisch zu erkennen, dass myField
es sich bereits um einen Typ handelt NVARCHAR
(der effektiv CAST
zu einem No-Op wird).
quelle
Antworten:
Wenn die Besetzung der Spalte genau den gleichen Datentyp und die gleiche Länge hat und das Suchprädikat ein Literal ist, scheint es dies tatsächlich zu ignorieren oder als No-Op zu behandeln, und es sucht ein Index nach Gleichheit.
Wenn die Umwandlung der Spalte denselben Datentyp hat, aber länger ist und das Suchprädikat ein Zeichenfolgenliteral ist, wird ein Index-Scan durchgeführt. Dies ist natürlich zu vermeiden.
Wenn die Umwandlung der Spalte denselben Datentyp und dieselbe oder eine größere Länge hat und das Suchprädikat eine lokale Variable ist, wird dem Ausführungsplan ein Berechnungsskalaroperator hinzugefügt. Dies ruft
GetRangeThroughConvert
einen Bereich auf und gibt ihn aus.Dieser Bereich wird für eine Indexsuche verwendet und scheint ziemlich effizient zu sein
Code testen
quelle
Im Allgemeinen
CAST
wird die Leistung beeinträchtigt, da die Verwendung von Indexsuchen ungültig wird, wie das letzte Beispiel von Martin Smith zeigt. Das Casting aufnvarchar(max)
oder auf eine andere Länge bedeutet einen anderen Datentyp: Die Tatsache, dass allesnvarchar
ist, ist irrelevant.Darüber hinaus spielt auch der Datentyp auf der rechten Seite des Vergleichs eine Rolle. Wenn es sich um eine lokale Variable oder einen Parameter mit einer anderen Länge handelt, ist eine Seite implizit
CAST
der breiteste der beiden Datentypen (siehe Priorität des Datentyps ).Grundsätzlich, wenn Sie einen General
CAST
dazunvarchar(max)
haben, wird die Dinge durcheinander bringen. Ich würde in Betracht ziehen, die Verwendung von zu korrigieren,ntext
bevor ichCAST
alles hinzufügte .Die Konvertierung wird möglicherweise nicht im Abfrageplan angezeigt. Siehe Paul Whites Blog-Artikel
quelle
Nur eine Anmerkung: Casting wie dieses, bei dem Datecreated datetime ist
Beeinträchtigt nicht die Fähigkeit von SQL, Indizes zu verwenden, wenn Indizes vorhanden sind, und wenn sie nicht vorhanden sind, kann dies dazu führen, dass ein fehlender Index protokolliert wird.
In ähnlicher Weise hindert die Cast-Funktion SQL beim Casting von
int
nachtinyint
oderbigint
nachint
usw. nicht daran, Indizes zu verwenden , wenn der Optimierer weiß, dass die Cast-Operation die Sortierreihenfolge der beiden vergleichbaren Datentypen nicht ändert.Hier finden Sie eine Reihe von Tests, die Sie mit Adventureworks2008R2 ausführen und den aktuellen Plan anzeigen können
quelle