创建索引视图

创建索引视图所需的步骤与视图的成功实现密不可分。

  1. 确保将在视图中引用的所有现有表的 SET 选项都正确。
  2. 创建任何新表和视图之前,确保会话的 SET 选项已正确设置。
  3. 确保视图定义是确定的。
  4. 使用 WITH SCHEMABINDING 选项创建视图。
  5. 创建视图的唯一群集索引。

使用 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 子句。

使用 COLUMNPROPERTY 函数和 IsDeterministic 属性来确定视图列是否是确定性的。使用 COLUMNPROPERTY 函数和 IsPrecise 属性来确定包含架构绑定的视图中的确定性列是否是精确的。如果为 TRUE,则 COLUMNPROPERTY 会返回 1,如果为 FALSE,则返回 0,如果是无效的输入(列不是确定性的),则返回 NULL。例如,SELECT COLUMNPROPERTY(Object_Id('Vdiscount1'),'SumDiscountPrice','IsPrecise') 返回的是 0,因为 SumDiscountPrice 列引用了表 Order Details 中的浮动列 Discount。而同一视图中的列 SumPrice 既是确定性的又是精确的。

注意:   该 SELECT 语句所基于的视图能够在示例部分找到(视图 1)。

其它要求

除“设计准则”、“使用 SET 选项以获得一致的结果”和“使用确定性函数”部分中列出的要求之外,还必须符合以下要求。

基表要求

  • 基表在创建时必须正确设置 SET 选项,否则就不能被包含架构绑定的视图引用。
  • 表必须通过视图定义中的两部分名称(所有者.表名)引用。

函数要求

  • 用户定义的函数必须使用 WITH SCHEMABINDING 选项创建。
  • 用户定义的函数必须通过两部分名称(所有者.函数)引用。

视图要求

  • 视图必须使用 WITH SCHEMABINDING 选项创建。
  • 视图必须只引用同一数据库中的基表,而不能引用其它视图。

语法限制

对视图定义的语法有几个限制。视图定义不能包含以下内容:

  • COUNT(*)
  • ROWSET 函数
  • 派生表
  • 自联接
  • DISTINCT
  • STDEV、VARIANCE、AVG
  • Float* 列、文本列、ntext 列、图像列
  • 子查询
  • 全文谓词(CONTAIN、FREETEXT)
  • 可空表达式的 SUM
  • MIN、MAX
  • TOP
  • OUTER 联接
  • UNION

注意:   索引视图可以包含浮动列,不过,此类列不能包含在群集索引关键字中。

GROUP BY 限制

如果未使用 GROUP BY,表达式不能在选择列表中使用。

如果使用了 GROUP BY,则 VIEW 定义:

  • 必须包含 COUNT_BIG(*)。
  • 不得包含 HAVING、CUBE 或 ROLLUP。

这些限制只适用于索引视图定义。查询可以在其执行计划中使用索引视图,即便该索引视图并不符合这些 GROUP BY 限制。

索引要求

  • 执行 CREATE INDEX 语句的用户必须是视图所有者。
  • 如果视图定义中包含 GROUP BY 子句,唯一群集索引的关键字只能引用 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

添加包括 Rebate 列所需聚合的索引视图将更改查询 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)  

第一个查询的执行计划显示 Vdiscount1 视图由查询优化器使用。不过,由于该视图不包含 SUM(UnitPrice*Quantity*Discount) 聚合,因此不会被第二个查询使用。可以创建另一个可以同时满足上述两个查询的索引视图。

视图 2

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 排序函数

查询优化器选择该视图是因为它提供了最低的执行成本,尽管在查询中并未引用该视图。

查询 3

查询 3 类似于前几个查询,只是 ProductID 已被 OrderID 所取代,视图定义中没有包括该列。这违背了以下条件:查询选择列表中的所有表达式都必须能从未包括在视图定义内的表的视图选择列表中派生。

SELECT TOP 3 OrderID, SUM(UnitPrice*Quantity*Discount) OrderRebate FROM dbo.[Order Details] GROUP BY OrderID ORDER BY OrderRebate desc  

要求单独的索引视图来满足该查询。可以对 Vdiscount2 进行修改,使它包括 OrderID,但是所生成视图的行数将与原表的行数相同,因此,提供的性能也不会高于使用基表所提供的性能。

查询 4

该查询可生成每个产品的平均价格。

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  

索引视图的定义中不能包括复杂的聚合(例如,STDEV、VARIANCE、AVG),不过,如果索引视图中包括几个联合起来执行复杂聚合的简单聚合函数,即可用于执行包含 AVG 的查询。

视图 3

该索引视图包含执行 AVG 函数所需的简单聚合函数。在创建了视图 3 后执行查询 4 时,执行计划会显示正被使用的视图。优化器可以从视图的简单聚合列 Price 和 Count 中导出 AVG 表达式。

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)  

查询 5

该查询与查询 4 相同,只不过包括一个附加搜索条件。即使该附加搜索条件只引用未包括在视图定义内的表中的列,视图 3 也将用于该查询。

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  

最后两个查询是查询 8 的变体。每个变体都违背了一个优化器条件,因此与查询 8 不同,不能使用视图 4。

查询 8a

由于视图定义中的 UnitPrice > 10 与查询中的 UnitPrice > 25 之间的 WHERE 子句不匹配,所以 Q8a 不能使用索引视图。查询搜索条件谓词必须是视图定义中搜索条件谓词的超集。

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  

查询 8b

注意,表 Orders 没有参与索引视图 V4 的定义。尽管如此,在该表中添加谓词将禁止使用索引视图,原因是添加的谓词可能会消除聚合中的其它行(如查询 8b 中所示)。

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 新闻组,其站点是:http://communities.microsoft.com/newsgroups/default.asp?icp=chinacommunity&slcid=cn&MSCOMTB=ICP_中文新闻组(中文)。
  • 关于 SQL Server 的 Microsoft 正式课程。有关最新的课程信息,请参阅 Microsoft 培训和服务站点(英文)。

SQL Server 2000 索引视图提高性能2相关推荐

  1. 使用 SQL Server 2000 索引视图提高性能1

    什么是索引视图? 许多年来,Microsoft SQL Server" 一直都提供创建虚拟表(称为视图)的功能.在过去,这些视图主要有两种用途: 提供安全机制,将用户限制在一个或多个基表中的 ...

  2. 利用虚拟硬盘(把内存当作硬盘)来提高数据库的效率(目前只针对SQL Server 2000)可以提高很多...

    上一篇:让你的笔记本更快一点--我的笔记本的性能测试和虚拟硬盘(把内存当成硬盘)的使用感觉 虚拟硬盘:就是把内存当作硬盘来用,比如有2G的内存,那么可以拿出来1G的内存当作硬盘来用. 自从知道了&qu ...

  3. SQL Server 2000 Service Pack 4 中所修复的 bug 的列表

    有关在 SQL Server 2000 Service Pack 4 已修复的 bug 的详细信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章: 314128  FIX: 一 ...

  4. [推荐] TechNet 广播 SQL Server 2000完结篇

      TechNet中文网络广播在之前已经推出了SQL Server 2000的基础系列和管理专家系列,使广大听众认识并掌握了SQL Server 2000的管理技巧.本次系列作为前两次系列课程的完结篇 ...

  5. 在SQL Server 2000中设置OPTION (MAXDOP 1) 性能提高问题

    Windows 2003 ,      SQL Server 2000 SP4  . 执行下面的语句需要近 20 秒. 但是在后面加入 OPTION (MAXDOP 1)    或者 OPTION ( ...

  6. SQL Server 2000 ——系统表和系统视图

    一.系统表 数据字典的详细信息请查SQL SERVER BOL,这里仅列出一部分. 1.1.sysservers 1.查看所有本地服务器及链接服务器 select * from master..sys ...

  7. 从SQL SERVER 2000到SQL SERVER 2005 视图中存在 ORDER BY 语句的完全解决方案

    首先要看微软的一个官方文章: http://support.microsoft.com/kb/926292/ 文章中提到的补丁程序并未公开,需要与微软联系,工程师会给你下载地址和安装密码.我这里有一个 ...

  8. 同步SQL Server 2000 数据库

    为什么要同步SQL Server 2000 数据库,它都用在什么场合 数据实时备份同步,数据库服务器出问题时我们也有其正常工作时的备份 数据实时备份同步,一台服务器负载不起时,可以用来做负载均衡 数据 ...

  9. Microsoft SQL Server 2000整合规划

    Microsoft SQL Server 2000整合规划 更新日期: 2004年06月24日 SQL Server技术文章 作者:Allan Hirt 投稿人:Tom Davidson和Shaun ...

最新文章

  1. python-django框架中使用docker和elasticsearch配合实现搜索功能
  2. 马斯克放话,星链率先从SpaceX分拆上市,曾预计带来300亿美元营收
  3. 我是如何面试别人List相关知识的
  4. QT 文字字体和颜色设置
  5. 写给80后,我们的人生才刚刚开始
  6. wordpress搭建博客 主题推荐 2019
  7. xshell6左侧导航显示_【iOS12人机交互指南】7.1-导航栏
  8. python面向对象——类(上)
  9. 视频教程-C语言编程入门100题(实战编程)-C/C++
  10. 处理器排行_2019年度PC处理器性能排行榜:AMD反超Intel
  11. Shopee面试问题整理
  12. ESP32 系列之 ESP-IDF 官方构建方案
  13. Wireshark文档阅读笔记-TCP Flags
  14. matlab中:错误使用 handle.handle/set 对象无效或已删除
  15. 低照度水下图像增强论文(L2UWE)+代码+评价方法
  16. 分享一款电脑使用的二维码/条码扫描生成软件--二维码识别精灵
  17. 如何一键删除PPT的动画效果?
  18. 惠州学院计算机基础课程配套练习系统
  19. 步进电机+protues
  20. Q1利润不及预期股价仍大涨,疫情“摧残”下Facebook求生有新机?

热门文章

  1. 进制转换,字符串,字节串之间转换
  2. mac下shell给文件名批量加前缀
  3. IDEA使用Maven打包时如何去掉测试阶段
  4. 记录到日志中的异常栈缺失
  5. RFI远程文件包含的漏洞
  6. iBATIS.NET
  7. VS2005发布网站问题及aspnet_merge.exe”已退出,代码为 1的错误
  8. C#:导入Excel通用类(CSV格式)
  9. SQLServer常见性能问题
  10. 了解动态链接(六)—— 重定位表