Ich möchte eine schnelle Suche basierend auf, wenn zwei Spalten gleich sind. Ich habe versucht, eine berechnete Spalte mit einem Index zu verwenden, aber SQL Server scheint ihn nicht zu verwenden. Wenn ich nur eine statisch aufgefüllte Bitspalte mit einem Index verwende, erhalte ich die erwartete Indexsuche.
Es scheint, als gäbe es einige andere Fragen wie diese, aber keine konzentrierte sich darauf, warum ein Index nicht verwendet werden würde.
Testtabelle:
CREATE TABLE dbo.Diffs
(
Id int NOT NULL IDENTITY (1, 1),
DataA int NULL,
DataB int NULL,
DiffPersisted AS isnull(convert(bit, case when [DataA] is null and [DataB] is not null then 1 when [DataA] <> [DataB] then 1 else 0 end), 0) PERSISTED ,
DiffComp AS isnull(convert(bit, case when [DataA] is null and [DataB] is not null then 1 when [DataA] <> [DataB] then 1 else 0 end), 0),
DiffStatic bit not null,
Primary Key (Id)
)
create index ix_DiffPersisted on Diffs (DiffPersisted)
create index ix_DiffComp on Diffs (DiffComp)
create index ix_DiffStatic on Diffs (DiffStatic)
Und die Abfrage:
select Id from Diffs where DiffPersisted = 1
select Id from Diffs where DiffComp = 1
select Id from Diffs where DiffStatic = 1
quelle
COALESCE
an dieser Stelle einfach loswerden können . Ich glaube, dieCASE
Anweisung wurde bereits garantiert, um zurückzugeben,0
oder1
, aberISNULL
war nur vorhanden, damit SQL Server ein nicht nullableBIT
für die berechnete Spalte ergeben würde. Es wird jedochCOALESCE
immer noch eine nullfähige Spalte angezeigt. Die einzige Auswirkung dieser Änderung mit oder ohneCOALESCE
ist, dass die berechnete Spalte jetzt nullwertfähig ist, aber die Indexsuche verwendet werden kann.COALESCE
? Warum sollte ich es behalten?COALESCE
. Ich habe versucht, das Erscheinungsbild und die Absicht Ihres ursprünglichen Codes beizubehalten, und habe nicht ohne diesen Code getestet, damit Sie die Tests durchführen können. (Ich kann auch nicht erklären, warum SieISNULL
dort waren.)Dies ist eine spezielle Einschränkung der berechneten SQL Server-Spaltenübereinstimmungslogik, wenn eine äußerste
ISNULL
verwendet wird und der Datentyp der Spalte lautetbit
.Fehlerbericht
Um das Problem zu vermeiden, kann eine der folgenden Problemumgehungen angewendet werden:
ISNULL
Spalte (die einzige Möglichkeit, eine berechnete Spalte zu erstellenNOT NULL
).bit
Datentyp nicht als endgültigen Typ der berechneten Spalte.PERSISTED
und aktivieren Sie das Ablaufverfolgungsflag 174 .Einzelheiten
Der Kern des Problems besteht darin, dass ohne Ablaufverfolgungsflag 174 alle berechneten Spaltenreferenzen in einer Abfrage (auch wenn sie bestehen bleiben) immer sehr früh in der zugrunde liegenden Definition bei der Abfragekompilierung erweitert werden.
Die Idee der Erweiterung besteht darin, Vereinfachungen und Umschreibungen zu ermöglichen, die nur für die Definition gelten, nicht nur für den Spaltennamen. Beispielsweise kann die Abfrage Prädikate enthalten, die auf diese berechnete Spalte verweisen und einen Teil der Berechnung überflüssig oder auf andere Weise eingeschränkt machen.
Sobald frühe Vereinfachungen und Umschreibungen berücksichtigt wurden, versucht die Abfragekompilierung, Ausdrücke in der Abfrage mit berechneten Spalten abzugleichen (alle berechneten Spalten, nicht nur diejenigen, die ursprünglich im Abfragetext enthalten waren).
Unveränderte berechnete Spaltenausdrücke stimmen in den meisten Fällen problemlos mit der ursprünglichen berechneten Spalte überein. Es scheint einen Fehler zu geben, wenn ein Ausdruck vom
bit
Typ mit einem äußersten übereinstimmtISNULL
. Der Abgleich ist in diesem speziellen Fall nicht erfolgreich, auch wenn eine detaillierte Prüfung der Interna ergibt, dass der Abgleich erfolgreich sein sollte.quelle