我有一种情况,SQL Server 给出索引大小超过 900 字节的错误。它的发生是因为索引定义中的列之一是 varchar(2000),并且只要它的长度超过 800,它就会给出错误。
所以,我的问题是,有没有办法在索引定义中说只包含列中的前 800 个字符?
博客上的一些人建议在表中添加一个附加列,该列将包含其他列的前 800 个字符,并在这个新的附加列而不是原始列上添加索引。但我认为这会影响整体性能,因为读取查询仍在查询原始列。
请建议是否有其他方法可以解决此问题。
我有一种情况,SQL Server 给出索引大小超过 900 字节的错误。它的发生是因为索引定义中的列之一是 varchar(2000),并且只要它的长度超过 800,它就会给出错误。
所以,我的问题是,有没有办法在索引定义中说只包含列中的前 800 个字符?
博客上的一些人建议在表中添加一个附加列,该列将包含其他列的前 800 个字符,并在这个新的附加列而不是原始列上添加索引。但我认为这会影响整体性能,因为读取查询仍在查询原始列。
请建议是否有其他方法可以解决此问题。
我在这里写了一篇关于这种情况的帖子,比这个答案更深入。
这可以通过将计算列创建为
LEFT(MyColumn, 800)
,然后索引该列来完成。请注意,不必使用PERSISTED
子句在表中具体化列——在列上创建索引只会将值具体化到索引中。但是,请谨慎使用计算列方法,因为在某些情况下它的行为可能不像您预期的那样(一般是计算列的问题,并非特定于这种情况)。LIKE 'xyz%'
只要搜索词短于索引长度,这种方法就允许您进行精确匹配和直接匹配。函数的结果
CHECKSUM
可能很小,但它不是一个很好的散列函数。请改用HASHBYTES
或 CLR 函数。关于计算列,同样适用于上述内容。或者,该值足够小(16 字节),可以使用触发器或应用程序代码在表中具体化并从那里建立索引。
缺点是这种方法只允许精确匹配,因为无法匹配部分输入,当然还有向现有表添加新的非 NULL 列所需的更改管理。
您需要更改查询访问表的方式以使这些解决方案之一起作用,所以如果这不可能,那您就不走运了。
因为我们谈论的是有损压缩(散列或截断),所以查询总是必须将原始值与搜索词进行比较,除非索引是唯一的,这可能会让用户报告奇怪的错误(前 800 个字符是相同或不太可能发生哈希冲突)。如果索引不是唯一的并且未比较原始值,则可能会返回不正确的结果(注意:这可能是一个安全漏洞)。
额外的比较可能会影响查询计划,我不会在没有示例查询的情况下进行讨论,但您可以在我上面链接的博客文章中找到一些小示例。使用您现有的表模式和查询,您应该能够对计划将要发生的事情做出有根据的猜测。