码迷,mamicode.com
首页 > 其他好文 > 详细

计算列建立索引

时间:2015-07-10 16:58:31      阅读:145      评论:0      收藏:0      [点我收藏+]

标签:计算列   索引   


 

计算列上的索引

只要满足下列要求就可以为计算列定义索引: 

1、所有权要求 

2、确定性要求 

3、精度要求 

4、数据类型要求 

5、SET 选项要求 

所有权要求 

计算列中的所有函数引用必须与表具有相同的所有者。 

测试环境(MSSQL 2012):

--自定义所有者为guest的标量函数GetMonth

CREATE FUNCTION guest.GetMonth(@1 datetime)

returns nvarchar(10)

as

begin

DECLARE @return nvarchar(10)

SET @return=month(@1)

RETURN(@return)

END

--添加计算列AddMonth,使用函数GetMonth

ALTER TABLE T1 ADD AddMonth AS (guest.GetMonth(AddTime))

--为计算列AddMonth创建索引

CREATE INDEX xAddMonth_iID ON T1(AddMonth)INCLUDE(ID)

报错:

消息 1980,级别 16,状态 1,第 1 行

无法对表 ‘T1‘ 的计算列 ‘AddMonth‘ 创建索引,因为基础对象 ‘GetMonth‘ 的所有者不同。

 

确定性要求

 如果下列一项或多项为真,则具有确定性:

1. 表达式引用的所有函数都具有确定性,并且是精确的。 这些函数包括用户定义函数和内置函数。 有关详细信息,请参阅确定性函数和不确定性函数。 如果计算列是 PERSISTED,则函数可能不精确。

2. 表达式引用的所有列都来自包含计算列的表。

3. 没有列引用从多行中请求数据。 例如,聚合函数(如 SUM 或 AVG)依靠来自多行的数据,这使具有不确定性。

4. 没有系统数据访问或用户数据访问。

精度要求 

如果下列一项或多项为,则是精确的: 

a. 表达式的数据类型不是 float 或 real。 

b. 表达式定义中没有使用 float 或 real 数据类型。 

注意:任何 float 或 real 表达式都被认为是不精确的,不能作为索引键;float 或 real 表达式可以在索引视图中使用,但不能作为键使用。 对于计算列同样如此。 如果任何函数、表达式或用户定义函数包含任何 float 或 real 表达式,则被认为是不精确的。 这也包括逻辑表达式(比较)。 

测试环境(MSSQL 2012):

CREATE TABLE T2(ID BIGINT,Score FLOAT,Val REAL)

CREATE INDEX x_Score ON T2(Score)

命令已成功完成。

CREATE INDEX x_Val ON T2(Val)

命令已成功完成。

ALTER TABLE T2 ADD Score1 AS (ID*Score)

ALTER TABLE T2 ADD Val1 AS (ID*Val)

CREATE INDEX x_Score1 ON T2(Score1)

消息 2799,级别 16,状态 1,第 1 行

无法对表 ‘T2‘ 创建索引或统计信息 ‘x_Score1‘,因为计算列 ‘Score1‘ 不精确而且未持久化。请考虑从索引或统计信息键中删除列,或者将计算列标记为持久化。

CREATE INDEX x_Val1 ON T2(Val1)

消息 2799,级别 16,状态 1,第 1 行

无法对表 ‘T2‘ 创建索引或统计信息 ‘x_Val1‘,因为计算列 ‘Val1‘ 不精确而且未持久化。请考虑从索引或统计信息键中删除列,或者将计算列标记为持久化。

ALTER TABLE T2 ADD Val2 AS (CONVERT(BIGINT,ID*Val))

CREATE INDEX x_Val2 ON T2(Val2)

消息 2799,级别 16,状态 1,第 1 行

无法对表 ‘T2‘ 创建索引或统计信息 ‘x_Val2‘,因为计算列 ‘Val2‘ 不精确而且未持久化。请考虑从索引或统计信息键中删除列,或者将计算列标记为持久化。

ALTER TABLE T2 ADD ID1 AS (CONVERT(FLOAT,ID*ID))

CREATE INDEX x_ID1 ON T2(ID1)

消息 2799,级别 16,状态 1,第 1 行

无法对表 ‘T2‘ 创建索引或统计信息 ‘x_ID1‘,因为计算列 ‘ID1‘ 不精确而且未持久化。请考虑从索引或统计信息键中删除列,或者将计算列标记为持久化。

 

测试结论:可以直接在float 或 real列上建立索引,不能在含有float 或 real表达式或者含有float 或 real数据类型的计算列上建索引

数据类型要求 

1. 为计算列定义的的值不能为 textntext 或 image 数据类型。 

2. 只要计算列的数据类型可以作为索引键列,从 imagentexttextvarchar(max)nvarchar(max)varbinary(max) 和 xml 数据类型派生的计算列上就可以创建索引。 

3. 只要计算列的数据类型可以作为非键索引列,从 imagentext 和 text 数据类型派生的计算列就可以作为非聚集索引中的非键(包含性)列。 

SET 选项要求 

a. 执行定义计算列的 CREATE TABLE 或 ALTER TABLE 语句时,必须将 ANSI_NULLS 连接级选项设置为 ON。 OBJECTPROPERTY 函数通过 IsAnsiNullsOn 属性报告此选项是否设置为 ON。 

b. 对于在其中创建索引的连接和所有尝试执行 INSERTUPDATE 或 DELETE 语句(将更改索引中的值)的连接,必须将六个 SET 选项设置为 ON,将一个选项设置为 OFF。 如果不具有上述选项设置的连接执行了任何 SELECT 语句,优化器将忽略计算列的索引。 

NUMERIC_ROUNDABORT选项必须设置为OFF

且下列选项必须设置为 ON: 

1. ANSI_NULLS 

2. ANSI_PADDING 

3. ANSI_WARNINGS 

4. ARITHABORT 

5. CONCAT_NULL_YIELDS_NULL 

6. QUOTED_IDENTIFIER 

当数据库兼容级别设置为 90 或更高时,如果将 ANSI_WARNINGS 设置为 ON,则将使 ARITHABORT 隐式设置为 ON。 

为持久化计算列创建索引 

如果计算列使用确定性但不精确的表达式定义,但在 CREATE TABLE 或 ALTER TABLE 语句中标记为 PERSISTED,则可以在该列上创建索引。 这意味着数据库引擎在表中存储计算值,并且在计算列所依赖的任何其他列发生更新时更新这些值。 如果数据库引擎对列创建了索引并且该索引由某查询引用,则会使用这些持久值。 当数据库引擎不能准确证明返回计算列表达式的函数(特别是在 .NET Framework 中创建的 CLR 函数)是否既具有确定性又精确时,使用此选项可以对计算列创建索引。 

测试环境(MSSQL 2012):

ALTER TABLE T2 ADD ID2 AS (CONVERT(FLOAT,ID*ID))PERSISTED

CREATE INDEX x_ID2 ON T2(ID2)

命令已成功完成。



① https://msdn.microsoft.com/zh-cn/library/ms189292.aspx

计算列建立索引

标签:计算列   索引   

原文地址:http://sukunwu.blog.51cto.com/10453116/1672871

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!