Как заставить MS SQL Server прозрачно использовать индекс CHECKSUM / хеш?
Похоже, что SQL Server автоматически не использует индекс CHECKSUM / hash, если столбец CHECKSUM явно не включен в аргументы поиска для запроса. Это проблема, потому что я не контролирую приложения, которые запрашивают таблицу, и я не могу нарушить их производительность.
Есть ли способ заставить SQL Server использовать новый индекс CHECKSUM / hash без изменения запросов, чтобы включить новый столбец CHECKSUM / hash?
Скрипт Repro
CREATE TABLE big_table ( id BIGINT IDENTITY CONSTRAINT pk_big_table PRIMARY KEY, wide_col VARCHAR(50), wide_col_checksum AS CHECKSUM(wide_col), other_col INT ) CREATE INDEX ix_checksum ON big_table (wide_col_checksum)
Вставьте несколько тестовых данных:
- Как воспроизвести хэш-код пароля ASP.NET MVC 4
- Вычисление хэшей для строк в базе данных SQL Server - стоит усилий?
- Сравнение большого количества текста большой строки в SQL Server. Лучше ли производительность, если вместо сравнения используется хеш
- Сравнение созданной C # контрольной суммы с SQL Server
- Создание числовых клавиш на основе уникальных имен объектов в базе данных по всем системам?
SET NOCOUNT ON DECLARE @count INT = 0 BEGIN TRANSACTION WHILE @count < 10000 BEGIN SET @count = @count + 1 INSERT INTO big_table (wide_col, other_col) VALUES (SUBSTRING(master.dbo.fn_varbintohexstr(CRYPT_GEN_RANDOM(25)), 3, 50), @count) IF @count % 1000 = 0 BEGIN COMMIT TRANSACTION BEGIN TRANSACTION END END COMMIT TRANSACTION INSERT INTO big_table (wide_col, other_col) VALUES ('ABCDEFGHIJKLMNOPQRSTUVWXYZ', 9999999)
Устаревший запрос. Вызывает сканирование индексов (BAD):
SELECT * FROM big_table WHERE wide_col = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
Обновленный запрос. Причины поиска некластеризованного индекса (хорошо):
SELECT * FROM big_table WHERE wide_col = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' AND wide_col_checksum = CHECKSUM('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
Задний план
Моя таблица очень большая (много сотен миллионов строк), имеет несколько индексов (~ 20), все из которых требуются. Некоторые индексированные столбцы немного шире (~ 50 байт) и имеют несколько повторяющихся значений. Столбцы просматриваются только по принципу равенства. Стол вставляется постоянно.
Вот таблица, сравнивающая «нормальные» индексы и индексы CHECKSUM / hash в приведенной выше таблице примеров, как сжатых, так и не сжимаемых. Данные недавно восстановленных индексов на таблицах с 1 миллионом строк:
Сжатие страницы само по себе довольно неэффективно в данных выборки (реальные данные должны сжиматься немного лучше). Индекс хэша достигает уменьшения размера индекса 4X. Сжатие страницы по индексу хеширования позволяет уменьшить размер индекса 6X.
Мои цели с использованием хэш-индексов:
- Уменьшите размер этих индексов в памяти, тем самым позволяя SQL Server кэшировать большую долю в ОЗУ, тем самым избегая физических чтений.
- Уменьшите размер хранилища.
- Уменьшите ввод-вывод индекса для операций INSERT.
- Требуется эквивалент C # для функции SQL HashBytes
- Ограничение фрагментации на двоичном индексе хэш-типа
- C # хэш и функция hashbytel сервера sql, такая же реализация?
- Эквивалент Hashset в SQL Server
- Индексы хеш-серверов SQL Server
- Хеширование пароля для SqlServer
- Вычислить хэш или контрольную сумму для таблицы в SQL Server
- Хранение хэша паролей SHA512 в базе данных
Если ваше приложение запрашивает:
SELECT * FROM big_table WHERE wide_col = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
Вам нужен указатель на wide_col
, а не на wide_col_checksum
.
SQL Server хранит индексы как B-дерево. Как предполагает @MartinSmith, уменьшение размера столбцов в индексе действительно уменьшает объем памяти и диска.
SQL Server автоматически не использует индекс контрольной суммы / хэша. Запрос должен использовать хеш-столбец для SQL-сервера, чтобы рассмотреть возможность использования индекса. Поэтому я не вижу, как вы можете достичь своей цели, которая вносит изменения в запросы. Это интересный вопрос, однако, это может быть хороший запрос функции SQL Server.