除非 CHECKSUM 列显式包含在查询的搜索参数中,否则 SQL Server 似乎不会自动使用 CHECKSUM/哈希索引。这是一个问题,因为我不控制查询表的应用程序,并且我可能不会破坏它们的性能。
有没有办法让 SQL Server 使用新的 CHECKSUM/hash 索引而不修改查询以包含新的 CHECKSUM/hash 列?
复制脚本
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)
插入一些测试数据:
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/哈希索引的表,包括压缩和非压缩。来自 100 万行表的新重建索引的数据:
单独的页面压缩对样本数据非常无效(实际数据应该压缩得更好)。哈希索引实现了 4 倍的索引大小减少。哈希索引上的页面压缩实现了 6 倍的索引大小减少。
我使用哈希索引的目的是:
- 减少这些索引在内存中的大小,从而允许 SQL Server 在 RAM 中缓存更多部分,从而避免物理读取。
- 减少索引存储大小。
- 减少 INSERT 操作的索引 I/O。