在 SQL Server 2000 中,某些视图可以更新。如果某个视图可以更新,则使用 INSERT、UPDATE 和 DELETE 语句可通过该视图直接修改根本基表。为某个视图创建索引并不会妨碍该视图的更新。有关可更新视图的详细信息,请参阅关于 SQL Server 2000 的“SQL Server 联机图书”中的“通过视图修改数据(英文)”。
维护成本的考虑因素
设计索引视图时应该考虑以下几点:
数据库中需要有一个额外的存储空间用于索引视图。索引视图的结果集以类似于典型表存储空间的方式物理保存在数据库中。
SQL Server 自动维护视图。因此,对定义视图所据的基表的任何更改都可能引起视图索引的一处或多处更改,从而导致维护开销的增加。
一个视图获得的净性能提高就是视图提供的查询执行节约总计与存储和维护该视图耗费的成本之间的差。
确保将在视图中引用的所有现有表的 SET 选项都正确。
创建任何新表和视图之前,确保会话的 SET 选项已正确设置。
确保视图定义是确定的。
使用 WITH SCHEMABINDING 选项创建视图。
创建视图的唯一群集索引。
使用 SET 选项以获得一致的结果
如果在执行查询时启用不同的 SET 选项,则在 SQL Server 中对同一个表达式求值会产生不同的结果。例如,将 SET 选项 CONCAT_NULL_YIELDS_NULL 设置为 ON 之后,表达式 'abc' + NULL 返回的值是 NULL。而将 CONCAT_NULL_YIEDS_NULL 设置为 OFF 之后,该表达式得出的结果却是 'abc'。索引视图要求多个 SET 选项的值都固定,以确保这些视图能够得到正确维护并返回一致的结果。
只要出现以下情况,就必须将下表中的 SET 选项设置为要求的值列中所示的值:
创建了索引视图。
对索引视图中引用的任何表执行了任何 INSERT、UPDATE 或 DELETE 操作。
查询优化器使用索引视图来生成查询计划。
SET
选项 要求
的值 默认
服务器
的值 OLE DB
和
ODBC 的值 DB LIB
的值
ANSI_NULLS ON OFF ON OFF
ANSI_PADDING ON ON ON OFF
ANSI_WARNING ON OFF ON OFF
ARITHABORT ON OFF OFF OFF
CONCAT_NULL_YIELDS_NULL ON OFF ON OFF
NUMERIC_ROUNDABORT OFF OFF OFF OFF
QUOTED_IDENTIFIER ON OFF ON OFF
如果使用的是 OLE DB 或 ODBC 服务器连接,唯一必须修改的值是 ARITHABORT 的设置。所有 DB LIB 值都必须使用 sp_configure 在服务器级上正确设置或使用 SET 命令从应用程序正确设置。有关 SET 选项的详细信息,请参阅关于 SQL Server 2000 的“SQL Server 联机图书”中的“使用 SQL Server 中的选项(英文)”。
使用确定性函数
索引视图的定义必须是确定性的。如果选择列表中的所有表达式以及 WHERE 和 GROUP BY 子句都是确定性的,则视图就是确定性的。只要用特定的一组输入值对确定性表达式进行求值,一定会返回同一个结果。只有确定性函数可以加入确定性表达式。例如,DATEADD 是确定性函数,因为将任何给定的一组变量值赋予它的三个参数进行求值,返回的总是同一个结果。而 GETDATE 则不是确定性函数,因为始终用同一个变量调用它,而它每次执行后返回的值都不相同。有关详细信息,请参阅关于 SQL Server 2000 的“SQL Server 联机图书”中的“确定性和非确定性函数”。
即便某个表达式是确定性的,但如果其中包含浮动表达式,确切的结果就可能取决于处理器的体系结构或微代码的版本。要确保 SQL Server 2000 中数据的完整性,此类表达式只能加入索引视图的非关键列。不包含浮动表达式的确定性表达式被称为精确的表达式。只有精确的确定性表达式可以加入索引视图的关键列和 WHERE 或 GROUP BY 子句。
查询基于 Northwind(SQL Server 2000 中提供的数据库样本)中的表,并可以写入的方式执行。创建视图的前后,最好使用 SQL 查询优化器中的“显示执行计划”工具来查看查询优化器选定的计划。尽管示例中阐述了优化器是如何选择成本最低的执行计划的,但因为 Northwind 数据库样本太小,因此无法体现性能的提高。
以下查询显示如何从 Order Details 表中返回具有最大总折扣的五种产品的两个方法。
查询 1
SELECT TOP 5 ProductID, SUM(UnitPrice*Quantity) -
SUM(UnitPrice*Quantity*(1.00-Discount))AS Rebate
FROM [Order Details]
GROUP BY ProductID
ORDER BY Rebate DESC
查询 2
SELECT TOP 5 ProductID, SUM(UnitPrice*Quantity*Discount)AS Rebate
FROM [Order Details]
GROUP BY ProductID
ORDER BY Rebate DESC
查询优化器选定的执行计划包含:
对 Order Details 表的群集索引扫描,估计有 2,155 行。
哈希匹配/聚合运算符,该运算符基于 GROUP BY 列将选定的行放入哈希表,然后计算每行的 SUM 聚合。
基于 ORDER BY 子句的 TOP 5 排序运算符。
视图 1
CREATE VIEW Vdiscount1 WITH SCHEMABINDING
AS
SELECT SUM(UnitPrice*Quantity)AS SumPrice,
SUM(UnitPrice*Quantity*(1.00-Discount))
AS SumDiscountPrice, COUNT_BIG(*) AS Count, ProductID
FROM dbo.[Order Details]
GROUP BY ProductID
GO
CREATE UNIQUE CLUSTERED INDEX VDiscountInd ON Vdiscount1 (ProductID)
CREATE VIEW Vdiscount2 WITH SCHEMABINDING
AS
SELECT SUM(UnitPrice*Quantity)AS SumPrice,
SUM(UnitPrice*Quantity*(1.00-Discount))AS SumDiscountPrice,
SUM(UnitPrice*Quantity*Discount)AS SumDiscountPrice2, COUNT_BIG(*)
AS Count, ProductID
FROM dbo.[Order Details]
GROUP BY ProductID
GO
CREATE UNIQUE CLUSTERED INDEX VDiscountInd ON Vdiscount2 (ProductID)
有了该索引视图,现在两个查询的查询执行计划包含:
对 Vdiscount2 视图的群集索引扫描,估计有 77 行
基于 ORDER BY 子句的 TOP 5 排序函数
查询优化器选择该视图是因为它提供了最低的执行成本,尽管在查询中并未引用该视图。
SELECT ProductName, od.ProductID,
AVG(od.UnitPrice*(1.00-Discount)) AS AvgPrice, SUM(od.Quantity) AS Units
FROM [Order Details] od, Products p
WHERE od.ProductID=p.ProductID
GROUP BY ProductName, od.ProductID
CREATE VIEW View3 WITH SCHEMABINDING
AS
SELECT ProductID, SUM(UnitPrice*(1.00-Discount))AS Price,
COUNT_BIG(*)AS Count, SUM(Quantity)AS Units
FROM dbo.[Order Details]
GROUP BY ProductID
Go
CREATE UNIQUE CLUSTERED INDEX iv3 ON View3 (ProductID)
SELECT ProductName, od.ProductID, AVG(od.UnitPrice*(1.00-Discount))
AS AvgPrice, SUM(od.Quantity)AS Units
FROM [Order Details] AS od, Products AS p
WHERE od.ProductID=p.ProductID
AND p.ProductName like '%Tofu%'
GROUP BY ProductName, od.ProductID
查询 6
查询优化器不能将视图 3 用于该查询。附加搜索条件 od.UnitPrice>10 包含视图定义内的表中的列,而该列却不出现在 GROUP BY 列表中,搜索谓词也不出现在视图定义中。
SELECT ProductName, od.ProductID, AVG(od.UnitPrice*(1.00-Discount))
AS AvgPrice, SUM(od.Quantity) AS Units
FROM [Order Details] od, Products p
WHERE od.ProductID = p.ProductID
AND od.UnitPrice > 10
GROUP BY ProductName, od.ProductID
查询 7
相反,查询优化器可以将视图 3 用于查询 7,原因是新搜索条件 od.ProductID in (1,2,13,41) 中定义的列包括在视图定义内的 GROUP BY 子句中。
SELECT ProductName, od.ProductID, AVG(od.UnitPrice*(1.00-Discount))
AS AvgPrice, SUM(od.Quantity) AS Units
FROM [Order Details] AS od, Products AS p
WHERE od.ProductID = p.ProductID
AND od.ProductID in (1,2,13,41)
GROUP BY ProductName, od.ProductID
视图 4
该视图在视图定义中包括了列 od.Discount,可以满足查询 6 的条件。
CREATE VIEW View4 WITH SCHEMABINDING
AS
SELECT ProductName, od.ProductID, SUM(od.UnitPrice*(1.00-Discount))
AS AvgPrice, SUM(od.Quantity) AS Units, COUNT_BIG(*) AS Count
FROM dbo.[Order Details] AS od, dbo.Products AS p
WHERE od.ProductID = p.ProductID
AND od.UnitPrice > 10
GROUP BY ProductName, od.ProductID
GO
CREATE UNIQUE CLUSTERED INDEX VdiscountInd on View4 (ProductName, ProductID)
查询 8
视图 4 的同一个索引还将用于一个添加了与表 Orders 的联接的查询。该查询符合以下条件:查询 FROM 子句中列出的表是索引视图的 FROM 子句中表的超集。
SELECT ProductName, od.ProductID, AVG(od.UnitPrice*(1.00-Discount))
AS AvgPrice, SUM(od.Quantity) AS Units
FROM dbo.[Order Details] AS od, dbo.Products AS p, dbo.Orders AS o
WHERE od.ProductID = p.ProductID and o.OrderID = od.OrderID
AND od.UnitPrice > 10
GROUP BY ProductName, od.ProductID
SELECT ProductName, od.ProductID, AVG(od.UnitPrice*(1.00-Discount)) AvgPrice,
SUM(od.Quantity) AS Units
FROM dbo.[Order Details] AS od, dbo.Products AS p, dbo.Orders AS o
WHERE od.ProductID = p.ProductID and o.OrderID = od.OrderID
AND od.UnitPrice > 25
GROUP BY ProductName, od.ProductID
SELECT ProductName, od.ProductID, AVG(od.UnitPrice*(1.00-Discount))
AS AvgPrice, SUM(od.Quantity) AS Units
FROM dbo.[Order Details] AS od, dbo.Products AS p, dbo.Orders AS o
WHERE od.ProductID = p.ProductID and o.OrderID = od.OrderID
AND od.UnitPrice > 10
AND o.OrderDate > '01/01/1998'
GROUP BY ProductName, od.ProductID
有关详细信息
Microsoft SQL Server 2000 联机图书包含索引视图的详细信息。有关其它信息,请参阅以下资源:
Microsoft SQL Server Web 站点(英文)。
Microsoft SQL Server 开发人员中心(英文)。
SQL Server 杂志(英文)。
Microsoft.public.sqlserver.server 和 microsoft.public.sqlserver.datawarehouse 新闻组,其站点是:news://news.microsoft.com(英文)。
关于 SQL Server 的 Microsoft 正式课程。有关最新的课程信息,请参阅 Microsoft 培训和服务站点(英文)。