Я хочу иметь быстрый поиск на основе, если два столбца равны. Я пытался использовать вычисляемый столбец с индексом, но SQL Server, похоже, не использует его. Если я просто использую статически заполненный битовый столбец с индексом, я получаю ожидаемый поиск индекса.
Кажется, есть и другие подобные вопросы, но ни один из них не сфокусирован на том, почему индекс не будет использоваться.
Тестовая таблица:
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)
И запрос:
select Id from Diffs where DiffPersisted = 1
select Id from Diffs where DiffComp = 1
select Id from Diffs where DiffStatic = 1
источник
COALESCE
на этом этапе вы можете просто избавиться от ; Я полагаю, чтоCASE
оператор уже гарантированно возвращал0
или1
, ноISNULL
присутствовал только для того, чтобы SQL Server мог дать необнуляемое значениеBIT
для вычисляемого столбца. Тем не менее, по-COALESCE
прежнему будет обнуляться столбец Таким образом, единственное влияние этого изменения, с или безCOALESCE
, состоит в том, что вычисляемый столбец теперь обнуляем, но можно использовать поиск по индексу.COALESCE
? Зачем мне это держать?COALESCE
. Я пытался сохранить внешний вид и намерения вашего исходного кода и не тестировал без него, поэтому тестирование будет на вас. (Я также не могу объяснить, почему выISNULL
там были .)Это конкретное ограничение логики сопоставления вычисляемых столбцов SQL Server, когда используется самый внешний
ISNULL
и тип данных столбцаbit
.Отчет об ошибке
Чтобы избежать этой проблемы, можно использовать любой из следующих обходных путей:
ISNULL
(единственный способ сделать вычисляемый столбецNOT NULL
).bit
тип данных в качестве окончательного типа вычисляемого столбца.PERSISTED
и включите флаг трассировки 174 .Детали
Суть проблемы заключается в том, что без флага трассировки 174 все вычисленные ссылки на столбцы в запросе (даже сохраненные) всегда расширяются до базового определения очень рано при компиляции запроса.
Идея расширения заключается в том, что оно может позволить упрощения и переписывания, которые могут работать только с определением, а не только с именем столбца. Например, в запросе могут быть предикаты, ссылающиеся на этот вычисляемый столбец, которые могут сделать часть вычисления избыточной или иным образом более ограниченной.
После раннего упрощения и переписывания компиляция запроса пытается сопоставить выражения в запросе с вычисляемыми столбцами (все вычисляемые столбцы, а не только те, которые изначально были найдены в тексте запроса).
Неизмененные выражения вычисляемого столбца в большинстве случаев соответствуют исходному вычисляемому столбцу без проблем. Кажется, что есть ошибка, когда она специфична для сопоставления выражения
bit
типа с самым внешнимISNULL
. Совпадение неуспешно в этом конкретном случае, даже если детальное изучение внутренних органов показывает, что оно должно быть успешным.источник