SQL-Server 中计算列的奇怪行为

Stu*_*ler 12 sql-server

在阅读我的 70-433 试卷时,我想到了一些我认为不起作用的东西,但我相信它确实有效。这段话是这样写的:

该列还必须标记为PERSISTED,这意味着 SQL Server 将计算列的表达式的结果物理存储在数据行中,而不是每次在查询中引用时计算它。

由此我明白了两件事:

  1. 非持续计算列计算每次它是在查询中引用时间
  2. 因为计算列没有存储任何内容,所以我假设不能为该列创建索引。

读完后,我觉得这有点奇怪,因为我在以前的项目中设法在非持久化列上创建了索引。

如何为未持久化的东西创建索引,从长远来看这是否有害?


为了证明这一点,我运行了以下 SQL 语句:

CREATE TABLE testTable
(
    ID INT IDENTITY(1,1) PRIMARY KEY,
    telephone VARCHAR(14),
    c_areaCode AS (SUBSTRING(telephone,0,5)),
    cp_areaCode AS (SUBSTRING(telephone,0,5)) PERSISTED
)

INSERT INTO testTable VALUES('09823 000000');
INSERT INTO testTable VALUES('09824 000000');
INSERT INTO testTable VALUES('09825 000000');

CREATE NONCLUSTERED INDEX IX_NotPersisted ON testTable(c_areaCode);
CREATE NONCLUSTERED INDEX IX_Persisted ON testTable(cp_areaCode);
Run Code Online (Sandbox Code Playgroud)

然后运行以下查询:

DBCC FREEPROCCACHE
DBCC FREESYSTEMCACHE('ALL');
DBCC DROPCLEANBUFFERS
GO
SELECT cp_areaCode FROM testTable;
GO
SELECT c_areaCode FROM testTable;
Run Code Online (Sandbox Code Playgroud)

查看上述代码的查询计划后,我可以看到两个选择查询都使用了非持久化索引。又如何?

在此处输入图片说明

Jac*_*las 9

2.因为计算列没有存储任何东西,我假设不能为该列创建索引。

这个假设是不正确的 -任何一种都可以被索引。在任何一种情况下,计算列都必须是确定性的,但是当计算列被持久化时,计算也精确的要求就放宽了(即它可以涉及浮点运算)。

如何为未持久化的东西创建索引,从长远来看这是否有害?

在任何一种情况下,函数的结果都在索引中“持久化” ——唯一的区别是它是否在表中持久化。