Ube*_*en1 13 index sql-server sql-server-2012 computed-column
我正在努力寻找有关 SQL Server 如何实际存储非持久计算列的任何文档。
以下面的例子为例:
--SCHEMA
CREATE TABLE dbo.Invoice
(
InvoiceID INT IDENTITY(1, 1) PRIMARY KEY,
CustomerID INT FOREIGN KEY REFERENCES dbo.Customer(CustomerID),
InvoiceStatus NVARCHAR(50) NOT NULL,
InvoiceStatusID AS CASE InvoiceStatus
WHEN 'Sent' THEN 1
WHEN 'Complete' THEN 2
WHEN 'Received' THEN 3
END
)
GO
--INDEX
CREATE NONCLUSTERED INDEX IX_Invoice ON Invoice
(
CustomerID ASC
)
INCLUDE
(
InvoiceStatusID
)
GO
Run Code Online (Sandbox Code Playgroud)
我知道它存储在叶级别,但是如果该值没有持久化,那么如何存储任何内容?在这种情况下,索引如何帮助 SQL Server 找到这些行?
非常感谢任何帮助,
非常感谢,
编辑:
感谢 Brent & Aaron 回答这个问题,这里的 PasteThePlan清楚地展示了他们的解释。
Bre*_*zar 11
当 SQL Server 在计算域上创建索引时,计算域会在那时写入磁盘 - 但仅限于该索引的 8K 页。SQL Server 可以在读取聚集索引时计算 InvoiceStatusID - 无需将该数据写入聚集索引。
当您在 dbo.Invoice 中删除/更新/插入行时,索引中的数据会保持最新。(当 InvoiceStatus 更改时,SQL Server 知道也更新 IX_Invoice。)
您可以亲眼看到这一点的最佳方式是实际操作:创建这些对象,并执行触及 InvoiceStatusID 字段的更新。如果您需要帮助查看索引更新发生的位置,请发布执行计划(PasteThePlan.com 对此很有帮助)。
索引的、非持久化计算列的值不持久化在表的数据页中,但持久化在索引页中。它在表中保持非持久化,无论它是在 0、1 还是多个索引中持久化。
只是为了说明 Brent 的描述,以您给出的示例为例,让我们插入一行:
INSERT dbo.Invoice(CustomerID, InvoiceStatus) VALUES(1,N'Sent');
Run Code Online (Sandbox Code Playgroud)
现在,让我们看看索引页:
DBCC TRACEON(3604, -1);
DBCC IND(N'dbname', N'dbo.Invoice', 2);
Run Code Online (Sandbox Code Playgroud)
(显然更改dbname,并且在您的情况下索引 ID 可能不是 2。)
输出(你的肯定会有所不同):
最后,让我们检查页面PageType2:
DBCC PAGE(7, 1, 584, 3);
Run Code Online (Sandbox Code Playgroud)
(您可能需要更改 7 以匹配您的数据库 ID,如果您有多个数据文件,您可能需要更改第二个参数以匹配PageFID第一个结果。)
输出:
那是在索引页上。
PERSISTED计算列的属性与值是否保留在表中(聚集索引或堆)有关,而不是值是否保留在索引中。
在CREATE INDEX有关于计算列和索引的限制要求:
可以包括确定性且精确或不精确的计算列。从 image、ntext、text、varchar(max)、nvarchar(max)、varbinary(max) 和 xml 数据类型派生的计算列可以包含在非键列中,只要计算列数据类型允许作为包含柱子。有关更多信息,请参阅计算列上的索引。
计算列是否持久化没有限制。
以及进一步(不是关于包含而是关于索引主要部分中的计算列):
可以在计算列上创建索引。此外,计算列可以具有属性
PERSISTED。这意味着数据库引擎将计算值存储在表中,并在计算列所依赖的任何其他列更新时更新它们。数据库引擎在为列创建索引以及在查询中引用索引时使用这些持久值。要索引计算列,计算列必须(是)确定性和精确的。但是,使用该
PERSISTED属性将可索引计算列的类型扩展为包括:...
| 归档时间: |
|
| 查看次数: |
1895 次 |
| 最近记录: |