如何让MS SQL Server透明地使用CHECKSUM /哈希索引?

del*_*eto 8 sql-server indexing hash sql-server-2008 database-performance

看起来SQL Server不会自动使用CHECKSUM /哈希索引,除非CHECKSUM列明确包含在查询的搜索参数中.这是一个问题,因为我不控制查询表的应用程序,我可能不会破坏它们的性能.

有没有办法让SQL Server使用新的CHECKSUM /哈希索引而不修改查询以包含新的CHECKSUM /哈希列?

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)
Run Code Online (Sandbox Code Playgroud)

插入一些测试数据:

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)
Run Code Online (Sandbox Code Playgroud)

遗留查询.导致聚集索引扫描(BAD):

SELECT * FROM big_table 
WHERE wide_col = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
Run Code Online (Sandbox Code Playgroud)

聚集索引扫描(BAD)


更新的查询.导致NonClustered Index Seek(好):

SELECT * FROM big_table 
WHERE wide_col = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
AND wide_col_checksum = CHECKSUM('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
Run Code Online (Sandbox Code Playgroud)

NonClustered Index Seek(好)

背景

我的表非常大(数亿行),有几个索引(~20),所有这些都是必需的.一些索引列有点宽(~50个字节)并且具有很少的重复值.仅在相等性上搜索列.桌子不断插入.

下面是一个表格,比较上面样本表中的"普通"索引和CHECKSUM /哈希索引,包括压缩和非压缩.来自具有100万行的表的新重建索引的数据:

散列索引和压缩

单独的页面压缩对样本数据非常无效(实际数据应该更好地压缩).哈希索引实现了4X索引大小的减少.哈希索引上的页面压缩实现了6X索引大小的减少.

我使用哈希索引的目的是:

  1. 减少内存中这些索引的大小,从而允许SQL Server在RAM中缓存更大的部分,从而避免物理读取.
  2. 减少索引存储大小.
  3. 减少INSERT操作的索引I/O.

And*_*mar 1

如果您的应用程序查询:

SELECT * FROM big_table WHERE wide_col = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
Run Code Online (Sandbox Code Playgroud)

您需要在 上建立索引wide_col,而不是在 上wide_col_checksum

SQL Server 将索引存储为 B 树。正如 @MartinSmith 所建议的,减少索引中列的大小确实会减少内存和磁盘占用空间。