在阅读我的 70-433 试卷时,我想到了一些我认为行不通的东西,但我相信它行得通。这段话是这样写的:
该列还必须标记为PERSISTED,这意味着 SQL Server 将计算列表达式的结果物理存储在数据行中,而不是每次在查询中引用它时都计算它。
由此我明白了两点:
- 每次在查询中引用非持久化计算列时都会对其进行计算
- 因为没有为计算列存储任何内容,所以我假设不能为该列创建索引。
看完后,我觉得这有点奇怪,因为我在之前的项目中设法在非持久化列上创建了索引。
如何为不持久的东西创建索引,从长远来看这是有害的?
为了证明这一点,我运行了以下 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);
然后运行以下查询:
DBCC FREEPROCCACHE
DBCC FREESYSTEMCACHE('ALL');
DBCC DROPCLEANBUFFERS
GO
SELECT cp_areaCode FROM testTable;
GO
SELECT c_areaCode FROM testTable;
查看上面代码的查询计划后,我可以看到两个选择查询都使用了非持久索引。再说一次,如何?
这个假设是不正确的——任何一种都可以被索引。在任何一种情况下,计算列都必须是确定性的,但是当计算列被持久化时,计算也是精确的要求就放宽了(即它可以涉及浮点运算)。
在这两种情况下,函数的结果都“保留”在索引中——唯一的区别是它是否保留在表中。