我有一个表,它有一个大字符串键 (varchar(1024)),我想在 SQL Server 上对其进行索引(我希望能够快速搜索它,但插入也很重要)。在 sql 2008 中,我没有收到此警告,但在 sql server 2005 下,它告诉我它超过了 900 字节,并且超过此大小的列的插入/更新将被删除(或该区域中的某些内容)
如果我想在这个大列上建立索引,我有什么选择?如果可以的话,我不知道是否值得。
最佳答案
所有键都接近 900 字节的索引将非常大且非常深(每页很少的键会导致非常高的 B 树)。
这取决于您计划如何查询这些值。索引在多种情况下很有用:
- 当探测某个值时。这是最典型的用途,即在表中搜索精确值时。典型例子有
WHERE column='ABC'
或连接条件ON a.column = B.someothercolumn
. - 扫描范围时。当在表中搜索<em>范围的值时,这也是相当典型的。除了
WHERE column BETWEEN 'ABC' AND 'DEF'
的明显例子之外还有其他不太明显的示例,例如部分匹配:WHERE column LIKE 'ABC%'
. - 订购要求。这种用法鲜为人知,但索引可以帮助具有显式
ORDER BY column
的查询。避免走走停停排序的要求,并且还可以帮助某些隐藏的排序要求,例如ROW_NUMBER() OVER (ORDER BY column)
.
那么,为什么需要索引呢?什么样的查询会使用它?
对于范围扫描和排序要求,除了索引之外没有其他解决方案,您必须权衡索引的成本与 yield 。
对于探针,您可以使用散列来避免对非常大的列进行索引。创建一个持久计算列 column_checksum = CHECKSUM(column)
然后对该列建立索引。必须重写查询才能使用 WHERE column_checksum = CHECKSUM('ABC') AND column='ABC'
。必须仔细考虑权衡窄索引(32 位校验和)的优点与冲突双重检查以及缺乏范围扫描和排序功能的缺点。
评论后
我曾经遇到过类似的问题,我使用了哈希列。该值太大,无法索引(>1K),我还需要将该值转换为 ID 来存储(基本上是一个字典)。大致思路是这样的:
create table values_dictionary (
id int not null identity(1,1),
value varchar(8000) not null,
value_hash = checksum(value) persisted,
constraint pk_values_dictionary_id
primary key nonclustered (id));
create unique clustered index cdx_values_dictionary_checksum on (value_hash, id);
go
create procedure usp_get_or_create_value_id (
@value varchar(8000),
@id int output)
begin
declare @hash = CHECKSUM(@value);
set @id = NULL;
select @id = id
from table
where value_hash = @hash
and value = @value;
if @id is null
begin
insert into values_dictionary (value)
values (@value);
set @id = scope_identity();
end
end
在本例中,字典表被组织为 values_hash
上的聚集索引。将所有冲突的哈希值分组在一起的列。 id
添加列以使聚集索引唯一,从而避免需要 hidden uniqueifier column 。此结构可查找 @value
尽可能高效,没有 value
上效率极低的索引并绕过 900 个字符的限制。 id
上的主键是非聚集的,这意味着查找 value
来自和 id
会在聚集索引中产生一个额外探测的开销。
不确定这是否能解决您的问题,您显然比我更了解您的实际场景。此外,该代码不处理错误情况,实际上可以插入重复的 @value 条目,这可能正确,也可能不正确。
关于sql-server - SQL Server - 值得为大字符串键建立索引吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8001905/