В моем предыдущем вопросе, это хорошая идея, чтобы отключить эскалацию блокировки при добавлении новых вычисляемых столбцов в таблицу? Я создаю вычисляемый столбец:
ALTER TABLE dbo.tblBGiftVoucherItem
ADD isUsGift AS CAST
(
ISNULL(
CASE WHEN sintMarketID = 2
AND strType = 'CARD'
AND strTier1 LIKE 'GG%'
THEN 1
ELSE 0
END
, 0)
AS BIT
) PERSISTED;
Вычисляем столбец PERSISTED
, и в соответствии с computed_column_definition (Transact-SQL) :
PERSISTED
Указывает, что компонент Database Engine будет физически хранить вычисленные значения в таблице и обновлять значения при обновлении любых других столбцов, от которых зависит вычисляемый столбец. Пометка вычисляемого столбца как PERSISTED позволяет создать индекс для вычисляемого столбца, который является детерминированным, но не точным. Для получения дополнительной информации см. Индексы для вычисляемых столбцов. Любые вычисляемые столбцы, используемые в качестве разделительных столбцов разделенной таблицы, должны быть явно помечены как PERSISTED. computed_column_expression должно быть детерминированным, если указано PERSISTED.
Но когда я пытаюсь создать индекс для моего столбца, я получаю следующую ошибку:
CREATE INDEX FIX_tblBGiftVoucherItem_incl
ON dbo.tblBGiftVoucherItem (strItemNo)
INCLUDE (strTier3)
WHERE isUsGift = 1;
Отфильтрованный индекс 'FIX_tblBGiftVoucherItem_incl' не может быть создан для таблицы 'dbo.tblBGiftVoucherItem', поскольку столбец 'isUsGift' в выражении фильтра является вычисляемым столбцом. Перепишите выражение фильтра, чтобы оно не включало этот столбец.
Как я могу создать отфильтрованный индекс по вычисляемому столбцу?
или
Есть ли альтернативное решение?
источник
WHERE (sintMarketID = 2 AND strType = 'CARD' AND strTier1 LIKE 'GG%')
хотя.Ответы:
К сожалению, начиная с SQL Server 2014, нет возможности создать
Filtered Index
местоположение фильтра в вычисляемом столбце (независимо от того, сохранен он или нет).С 2009 года открыт пункт « Подключить» , поэтому, пожалуйста, проголосуйте за него. Возможно, Microsoft исправит это однажды.
Аарон Бертран имеет статью, которая охватывает ряд других вопросов с фильтрованными индексами .
источник
Хотя вы не можете создать отфильтрованный индекс для постоянного столбца, есть довольно простой обходной путь, который вы можете использовать.
В качестве теста я создал простую таблицу со
IDENTITY
столбцом и постоянным вычисляемым столбцом на основе столбца идентификаторов:Затем я создал привязанное к схеме представление на основе таблицы с фильтром для вычисляемого столбца:
Затем я создал кластеризованный индекс в представлении, связанном со схемой, в результате чего сохраняются значения, хранящиеся в представлении, включая значение вычисляемого столбца:
Вставьте некоторые тестовые данные в таблицу:
Создайте элемент статистики и индекс для представления:
Выполнение
SELECT
операторов для таблицы с постоянным столбцом теперь может автоматически использовать постоянное представление, если оптимизатор запросов решит, что имеет смысл сделать это:Фактический план выполнения для вышеуказанного запроса показывает, что оптимизатор запросов выбрал использование постоянного представления для возврата результатов:
Вы, возможно, заметили явное преобразование в
WHERE
пункте выше. Это явноCONVERT(INT, 26)
позволяет оптимизатору запросов правильно использовать объект статистики для оценки количества строк, которые будут возвращены запросом. Если мы напишем запрос с помощьюWHERE pv.TestComputedColumn = 26
, оптимизатор запросов может неправильно оценить количество строк, так как 26 фактически считаетсяTINY INT
; это может привести к тому, что SQL Server не будет использовать постоянное представление. Неявные преобразования могут быть очень болезненными, и стоит постоянно использовать правильные типы данных для сравнений и объединений.Конечно, все стандартные «ошибки», возникающие в результате использования привязки схемы, применимы к вышеописанному сценарию; Это может помешать использовать этот обходной путь во всех сценариях. Например, больше невозможно будет изменить базовую таблицу, не удалив сначала привязку схемы из представления. Для этого вам необходимо удалить кластерный индекс из представления.
Если у вас нет SQL Server Enterprise Edition, оптимизатор запросов не будет автоматически использовать постоянное представление для запросов, которые не ссылаются непосредственно на представление, используя
WITH (NOEXPAND)
подсказку. Чтобы реализовать преимущество использования постоянного представления в версиях, отличных от Enterprise Edition, вам нужно переписать запрос выше примерно так:Спасибо Иану Рингрозу за указание на ограничение Enterprise Edition, приведенное выше, и Полу Уайту за
(NOEXPAND)
подсказку.В этом ответе Пола есть некоторые интересные детали об оптимизаторе запросов относительно постоянных представлений.
источник
TestComputedColumn
вместо. Однако, поскольку кластеризованный индекс содержит все данные для таблицы / представления, я решил, что было бы лучше использовать монотонно увеличивающееся число в качестве ключа кластеризации. Обратите внимание, что я не проверял это предположение, и на самом деле оно может быть неверным для некоторых вариантов воспроизведения.От
Create Index
и егоwhere
пункт, это невозможно:Источник: MSDN
источник
Прежде чем мы вычислили столбцы, мы использовали триггеры для вычисления значения столбцов всякий раз, когда строка была изменена или вставлена.
(Триггер также можно использовать для вставки / удаления PK элемента из второй таблицы, которая затем использовалась в запросах.)
источник
Это попытка улучшить работу Макса Вернона . В своем решении он предлагает использовать 2 индекса для представления и объект статистики.
1-й индекс является кластеризованным, что на самом деле требуется, поскольку в отличие от некластеризованного индекса в таблице будет сгенерирована ошибка, если будет предпринята попытка создания некластеризованного индекса в представлении без предварительного наличия кластерного индекса.
Второй индекс - это некластеризованный индекс, который используется в качестве индекса за запросом. В разделе комментариев его ответа я спросил, что произойдет, если вместо некластеризованного индекса будет использован кластерный индекс.
Следующий анализ пытается ответить на этот вопрос.
Я использую его точно такой же код, за исключением того, что я не создаю некластеризованный индекс для представления.
Я также не создаю объект статистики. Если вы следите за этим и используете SQL Server Management Studio (SSMS) для ввода приведенного ниже кода, вы должны знать, что вы можете увидеть некоторые красные волнистые линии, которые выглядят как ошибки. Это (вероятно) не ошибки, но они связаны с проблемой intellisense.
Вы можете отключить intellisense или просто игнорировать ошибки и запускать команды. Они должны завершиться без ошибок.
Следующий план выполнения (без представления представления / индекса) создается после выполнения следующего запроса к таблице:
Это дает основу для сравнения. Обратите внимание, что после завершения запроса был создан объект статистики (_WA_Sys_00000003_1FCDBCEB). Объект статистики PK_PersistedViewTest был создан при создании индекса кластерной таблицы.
Затем создается отфильтрованное представление и кластеризованный индекс в этом представлении:
Теперь давайте попробуем запустить запрос еще раз, но на этот раз с представлением:
Новый план выполнения теперь:
Если верить новому плану, то после добавления представления и кластеризованного индекса в этом представлении появляется статистика, показывающая, что время, необходимое для выполнения запроса, теперь удвоилось. Также обратите внимание, что не был создан новый объект статистики для поддержки нового индекса после выполнения запроса, который отличается от запроса в таблице.
План запроса по-прежнему предполагает, что создание некластеризованного индекса было бы весьма полезным для повышения производительности запроса. Итак, означает ли это, что некластерный индекс должен быть добавлен в представление до того, как может быть достигнуто желаемое улучшение производительности? Есть еще одна вещь, которую нужно попробовать. Измените запрос, чтобы использовать параметр «WITH NOEXPAND»:
Это приводит к следующему плану запроса:
Этот план выполнения выглядит очень похоже на тот, который был создан с некластеризованным индексом, данным в ответе Макса Вернона. Но это делается с одним меньшим (некластеризованным) индексом и одним меньшим объектом статистики.
Оказывается, что для правильного использования индексированного представления необходимо использовать опцию NOEXPAND с экспресс-версиями и стандартными версиями SQL Server. У Пола Уайта есть отличная статья, в которой рассказывается о преимуществах использования опции NOEXPAND. Он также рекомендует использовать эту опцию с корпоративной версией, чтобы оптимизатор использовал гарантию уникальности, предоставляемую индексами представлений.
Приведенный выше анализ был выполнен в экспресс-выпуске SQL Sever 2014. Я также попробовал его в редакции SQL Server 2016 для разработчиков. Похоже, что опция NOEXPAND не требуется в выпуске для разработчиков для достижения прироста производительности, но все же рекомендуется ,
Менее 5 месяцев назад Microsoft выпустила бесплатные версии для разработчиков . Лицензия ограничивает использование только разработкой, что означает, что базу данных нельзя использовать в производственной среде. Итак, если вы пытались проверить оптимизированные для памяти таблицы, шифрование, R и т. Д., То у вас больше нет оправдания отсутствия лицензии. Я успешно установил его на своем компьютере несколько дней назад вместе с SQL Server 2014 Express без проблем.
источник