SQL服务器 - 值得索引大字符串键吗?

Ghi*_*ita 10 sql-server

我有一个表有一个大字符串键(varchar(1024)),我想在SQL服务器上编入索引(我希望能够快速搜索它,但插入也很重要).在sql 2008中,我没有收到警告,但是在sql server 2005下它告诉我它超过了900字节,并且插入/更新了超过这个大小的列将被删除(或者该区域中的某些内容)

如果我想在这个大型列上编制索引,我有什么选择?如果我能的话,我不知道它是否值得.

Rem*_*anu 19

具有接近900字节的所有密钥的索引将非常大并且非常深(每页很少的密钥导致非常高的B树).

这取决于您计划如何查询值.索引在以下几种情况下很有用:

  • 当探测一个值时.这是最典型的用途,即在表格中搜索精确值时.典型的例子是WHERE column='ABC'连接条件ON a.column = B.someothercolumn.
  • 扫描范围时.当在表中搜索一系列值时,这也是相当典型的.除了明显的例子之外WHERE column BETWEEN 'ABC' AND 'DEF'还有其他不太明显的例子,比如局部匹配:WHERE column LIKE 'ABC%'.
  • 订购要求.这种用法鲜为人知,但索引可以帮助有明确ORDER BY column要求的查询避免停止排序,也可以帮助某些隐藏的排序要求,如a ROW_NUMBER() OVER (ORDER BY column).

那么,为什么你需要索引?会使用什么样的查询?

对于范围扫描和订购要求,除了索引之外没有其他解决方案,您必须权衡索引的成本与收益.

对于探测,您可以使用散列来避免索引非常大的列.创建一个持久的计算列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
Run Code Online (Sandbox Code Playgroud)

在这种情况下,字典表被组织为values_hash列上的聚簇索引,该列将所有冲突的哈希值组合在一起.id添加该列以使聚簇索引唯一,从而无需隐藏的唯一性列.这种结构使查找@value尽可能高效,没有极低效率的索引value和绕过900字符限制.主键id是非群集的,这意味着查找value来自并id在聚簇索引中产生一个额外探测的开销.

不确定这是否能解决您的问题,您显然比我更了解您的实际情况.此外,代码不处理错误条件,并且实际上可以插入重复的@value条目,这可能是也可能不正确.