【发布时间】:2012-06-18 13:38:31
【问题描述】:
SQL Server 似乎不会自动使用 CHECKSUM/哈希索引,除非 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/hash 索引的表,包括压缩和非压缩。来自 100 万行表的新重建索引的数据:
单独的页面压缩对样本数据非常无效(实际数据应该压缩得更好一些)。哈希索引实现了 4 倍的索引大小减少。哈希索引上的页面压缩实现了 6 倍的索引大小减小。
我使用哈希索引的目的是:
- 减少这些索引在内存中的大小,从而允许 SQL Server 在 RAM 中缓存更多部分,从而避免物理读取。
- 减少索引存储大小。
- 减少 INSERT 操作的索引 I/O。
【问题讨论】:
-
也许你应该考虑数据压缩。它可以轻松完成所有这些事情。
-
你需要某种
INSTEAD OF SELECT触发器,而且不存在这样的东西,所以很确定答案是“不”。 -
@Aaron 我添加了一个表格,比较了单独 PAGE 压缩的索引大小减少与 CHECKSUM 的大小减少。通过对哈希索引启用 PAGE 压缩,我们可以将原始宽索引的大小减少近 6 倍。
-
@MartinSmith 我想我找到了一种棘手的方法来建立一种
INSTEAD OF SELECT,请参阅我的答案
标签: sql-server sql-server-2008 hash indexing database-performance