sql-server - SQL Server - 值得为大字符串键建立索引吗?

标签 sql-server

我有一个表,它有一个大字符串键 (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/

相关文章:

sql-server - T-SQL 不等于运算符与 Case 语句

sql-server - SQL Server Linux 公共(public)预览版上的 xp_cmdshell

sql-server - 如何在SQL Server中进行上层递归自连接?

sql - LAG 函数和 NULL

asp.net - 有没有任何工具可以查看针对数据库运行的查询?

sql-server - t-SQL 授予表删除和创建权限

sql - 在SQL Server 2008中统计每个国家的人数

sql - 主键与聚簇索引的关系

sql - 获取具有多个值且至少其中一个为零的记录

SQL Server - 获取作业历史记录详细信息