SQL Server и сохраняемое вычисляемое поле с хешбайтами - PullRequest
1 голос
/ 02 ноября 2011

До изменений у меня было постоянное вычисляемое поле, в котором использовалась функция Checksum и индекс для его использования.

alter table Softs add TitleHash AS (CHECKSUM([Title])) PERSISTED;

Все было хорошо, пока мы не обнаружили, что Checksum производит плохой хэш, и могут возникнуть дубликаты. Поэтому мы решили использовать Hashbytes. Я пробовал как с двоичным результатом, так и с результатом char

alter table Softs add TitleHashCBin AS (CONVERT(BINARY(16),hashbytes('MD4',[Title]))) PERSISTED;

или

alter table Softs add TitleHashCChar AS (CONVERT(CHAR(32),hashbytes('MD4',[Title]),2)) PERSISTED;

К сожалению, мы обнаружили, что простой запрос SELECT не использует индекс для нового поля.

SELECT id FROM Softs WHERE TitleHashCBin = 0xC29939F6149FD65100A66AF5FD958D8B

Сканирует первичный индекс, построенный на столбце Id.

После этого мы создали двоичный столбец, скопировали данные из TitleHashCBin, а также создали индекс для нового столбца.

alter table Softs add TitleHashBin AS Binary(16)

И использовал аналогичный оператор выбора.

SELECT id FROM Softs WHERE TitleHashBin = 0xC29939F6149FD65100A66AF5FD958D8B

И этот использует индекс по полю TitleHashBin. Что, черт возьми, происходит с вычисленными полями. Может кто-нибудь объяснить, что я делаю не так или это ошибка? Постскриптум Sql Server 2008 10.0.3798

Редактировать Я просто удалил столбец char из таблицы, чтобы выяснить, что генерирует SSMS. Он сгенерирован на самом деле так же, как вы описали.

BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
GO
--DROP INDEXes here
--GO
ALTER TABLE dbo.Softs DROP COLUMN TitleHashCChar, TitleHashChar
GO
ALTER TABLE dbo.Softs SET (LOCK_ESCALATION = TABLE)
GO
COMMIT

Так что я думаю, мы можем предположить, что параметры таблицы верны. После этого я повторил операторы select, но с тем же планом выполнения, что и раньше ...

Редактировать Я решил задачу, используя простые двоичные поля и триггеры вставки / обновления для их обновления. Работает как шарм. Но до сих пор неясно, почему у него такое странное поведение? ..

1 Ответ

0 голосов
/ 02 ноября 2011

Убедитесь, что заданы правильные параметры, начиная с BOL Link

Требования к параметру SET Параметр уровня соединения ANSI_NULLS должен быть установлен на ON, когда оператор CREATE TABLE или ALTER TABLE, который определяетвычисляемый столбец выполняется.Функция OBJECTPROPERTY сообщает, включена ли опция через свойство IsAnsiNullsOn.Соединение, для которого создается индекс, и все соединения, пытающиеся использовать операторы INSERT, UPDATE или DELETE, которые будут изменять значения в индексе, должны иметь шесть опций SET, установленных на ON, и одну опцию на OFF.Оптимизатор игнорирует индекс в вычисляемом столбце для любого оператора SELECT, выполняемого соединением, которое не имеет этих же параметров настройки.Параметр NUMERIC_ROUNDABORT должен быть установлен на OFF, а следующие параметры должны быть установлены на ON:

ANSI_NULLS

ANSI_PADDING

ANSI_WARNINGS

ARITHABORT

CONCAT_NULL_YIELDS_NULL

QUOTED_IDENTIFIER

Установка ANSI_WARNINGS в значение ON неявно устанавливает значение ARITHABORT в значение ON, если уровень совместимости базы данных равен 90. Если уровень совместимости базы данных установлен равным 80 или более ранним, ARITHABORTопция должна быть явно установлена ​​на ON.Для получения дополнительной информации см. Параметры SET, влияющие на результаты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...