在更改之前,我有一个持久的计算字段,它使用Checksum
函数和索引来使用它。
alter table Softs add TitleHash AS (CHECKSUM([Title])) PERSISTED;
一切都很好,直到我们发现Checksum产生的哈希值很差,并且可能会出现重复。所以我们决定使用Hashbytes。 我尝试了二进制结果和char结果
alter table Softs add TitleHashCBin AS (CONVERT(BINARY(16),hashbytes('MD4',[Title]))) PERSISTED;
或
alter table Softs add TitleHashCChar AS (CONVERT(CHAR(32),hashbytes('MD4',[Title]),2)) PERSISTED;
不幸的是,我们发现一个简单的SELECT请求不使用索引作为新字段。
SELECT id FROM Softs WHERE TitleHashCBin = 0xC29939F6149FD65100A66AF5FD958D8B
它会扫描构建在Id
列上的主索引。
之后我们创建了二进制列,从TitleHashCBin复制了数据,并为新列创建了索引。
alter table Softs add TitleHashBin AS Binary(16)
并使用了类似的select语句。
SELECT id FROM Softs WHERE TitleHashBin = 0xC29939F6149FD65100A66AF5FD958D8B
这个使用TitleHashBin字段的索引。 计算字段到底是怎么回事。有人可以解释我做错了什么或者它是一个错误? 附: Sql Server 2008 10.0.3798
修改 我刚从表中删除了char列来调查SSMS生成的内容。它生成的实际上与您描述的相同。
BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
GO
--DROP INDEXes here
--GO
ALTER TABLE dbo.Softs DROP COLUMN TitleHashCChar, TitleHashChar
GO
ALTER TABLE dbo.Softs SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
所以我认为我们可以假设表选项是正确的。 之后我重复了select语句,但执行计划与以前相同......
修改 我决定使用简单的二进制字段和插入/更新触发器来更新它们。奇迹般有效。但目前还不清楚它为什么会有如此奇怪的行为?...
答案 0 :(得分:0)
SET选项要求 当执行定义计算列的CREATE TABLE或ALTER TABLE语句时,必须将ANSI_NULLS连接级选项设置为ON。 OBJECTPROPERTY函数报告是否通过IsAnsiNullsOn属性启用该选项。 创建索引的连接以及尝试INSERT,UPDATE或DELETE语句的所有连接都将更改索引中的值,必须将六个SET选项设置为ON并将一个选项设置为OFF。对于没有这些相同选项设置的连接执行的任何SELECT语句,优化程序会忽略计算列上的索引。 NUMERIC_ROUNDABORT选项必须设置为OFF,并且以下选项必须设置为ON:
ANSI_NULLS
ANSI_PADDING
ANSI_WARNINGS
ARITHABORT
CONCAT_NULL_YIELDS_NULL
QUOTED_IDENTIFIER
将ANSI_WARNINGS设置为ON会在数据库兼容级别设置为90时将ARITHABORT隐式设置为ON。如果数据库兼容级别设置为80或更早,则必须将ARITHABORT选项明确设置为ON。有关更多信息,请参阅影响结果的SET选项。