我有一个大小为2000的nvarchar列。有时当我插入时,它会因错误而失败:
System.Data.SqlClient.SqlException:操作失败。索引条目 索引的长度为1146字节' NonClusteredIndex-20161206-202443' 超过最大长度900字节。
但我不知道该怎么做。该表有45m记录,因此必须有索引。
有什么想法吗?
答案 0 :(得分:2)
索引这么大的字符串列通常是一个相当糟糕的标志。我首先会问你是否真的想要一个全文索引。这对文本而言比对常规索引更有用。
如果确实需要索引,则可以使用计算列提取一定数量的字符并在其上构建索引:
(?>o(?>o(?>o(?>o(?>oo)?o)?o)?o)?o)
o |oooooo <- first o gets matched by first atomic group
o o |ooooo <- second o accordingly
o o o |oooo <- third o accordingly
o o o o |ooo <- fourth o accordingly
o o o o oo|o <- fifth/sixth o by the innermost atomic group
o o o o oo o| <- fourth ag is matched successfully (thus no backtracking into it)
^ <- no more o, so backtracking starts here, no backtracking into fourth ag, try again 3rd
o o o |ooo<o <- 3rd ag can be closed, as well as second and first -> match returned (6 os)
请确保对应使用索引的任何表达式使用alter table t add col100 as (left(col, 100));
create index ind_t_col100 on t(col100);
。
如果索引的目的是保证唯一性,那么您可以计算校验和和前100个字符,并为这些值创建唯一索引。
答案 1 :(得分:0)
另一个解决方案是使用CHECKSUM
(ref)函数创建计算列,然后创建一个索引(ref),将此计算列作为索引键,并将原始列包含在内专栏:
SET NUMERIC_ROUNDABORT OFF
SET ANSI_NULLS, ANSI_PADDING, ANSI_WARNINGS, ARITHABORT, CONCAT_NULL_YIELDS_NULL, QUOTED_IDENTIFIER ON
GO
ALTER TABLE dbo.SomeTable
ADD TextChekcsum AS (CHECKSUM([TextColumn])) -- Non persisted computed column
--or ADD TextChekcsum AS (HASHBYTES'sha1', CHECKSUM([TextColumn])))
GO
CREATE INDEX IX_SomeTable_TextChekcsum_#_TextColumn
ON dbo.SomeTable (TextChecksum)
INCLUDE(TextColumn)
GO
-- In this case, in order to query this column I would use following approach:
DECLARE @ValueToSearch NVARCHAR(4000) -- Replace NVARCHAR(4000) with proper data type and max. length
SELECT ID, TextColumn
FROM dbo.SomeTable st
WHERE st.TextCheksum = CHECKSUM(@ValueToSearch)
--WHERE st.TextCheksum = HASHBYTES('sha1', CHECKSUM(@ValueToSearch))
AND st.TextColumn = @ValueToSearch
GO
注意:根据MS文档(ref)
创建索引的连接以及所有连接 尝试INSERT,UPDATE或DELETE语句来改变其中的值 索引必须将六个SET选项设置为ON并将一个选项设置为 关闭。优化程序忽略任何计算列上的索引 SELECT语句由没有这些的连接执行 相同的选项设置。
第二个注释:SELECT CHECKSUM(HASHBYTES('sha1', N''))
返回917799192
ans SELECT CHECKSUM(HASHBYTES('sha1', N''))
返回468415091
。