摘要本文档介绍 SQL Server 企业版的新功能 索引视图讲解索引视图并讨论一些提高性能的具体方案
什么是索引视图?
许多年来Microsoft® SQL Server; 一直都提供创建虚拟表(称为视图)的功能在过去这些视图主要有两种用途
提供安全机制将用户限制在一个或多个基表中的数据的某个子集
提供一种机制允许开发人员定制用户如何才能以逻辑方式查看存储在基表中的数据
SQL Server 已经扩展了 SQL Server 视图的功能以提高系统性能它可以在一个视图上创建唯一的群集索引和非群集索引可以改进最复杂查询的数据访问性能在 SQL Server 中拥有唯一群集索引的视图被称为索引视图
注意 索引视图只是 SQL Server 企业版和 SQL Server 开发人员版的一个功能
从数据库管理系统 (DBMS) 的观点来看视图是数据(元数据)的说明创建典型视图时通过 SELECT 语句(定义一个显示为虚拟表的结果集)来定义元数据当其它查询的 FROM 子句中引用了某个视图时将从系统目录中检索该元数据并对其进行扩展以代替该视图的引用在视图扩展之后查询优化器会为正在执行的查询编译单个执行计划
如果是非索引视图视图在运行时将被实体化任何计算(如联接或聚合)都在为每个引用该视图的查询执行查询期间进行(视图并不总需要被完全实体化查询可以包含其它一些谓词联接或聚合以应用于该视图所引用的表和视图)在视图上创建了唯一的群集索引之后视图的结果集会立即被实体化并持续保存在数据库的物理存储空间中以便节省这种操作所占用的大量资源
在执行查询时有两种方法可以使用索引视图查询可直接引用索引视图更重要的是如果查询优化器确定视图能够替换为查询的部分或全部而且这是低成本的查询计划则可以选择索引视图第二种情况是使用索引视图代替基础表及其普通索引此时不需要在查询中引用视图查询优化器即可在执行查询期间使用该视图这样现有的应用程序无需更改即可从新建的索引视图中获益
通过索引视图提高的性能
使用索引来提高查询性能并不是什么新观念不过索引视图还具有使用标准索引不能获得的其它性能优点索引视图能够在以下方面提高查询性能
能够预先计算聚合并将其存储在索引中从而最大限度地减少在执行查询期间进行成本很高的计算
能够预先联接表并存储生成的数据集
能够存储联接或聚合的组合
下图说明了查询优化器使用索引视图时一般能够提高多少性能提供的查询复杂程度各不相同(例如聚合计算的数量所用表的数量或谓词数)并包括来自实际生产环境的数百万行的大表
图 当查询优化器使用索引视图时一般能够提高多少性能
使用视图的辅助索引
视图的辅助性非群集索引可以提高其它查询性能与表的辅助索引类似视图的辅助索引也可以提供更多选项以便查询优化器在编译过程中从中进行选择例如如果查询包括群集索引未涉及的列优化器可以在计划中选择一个或多个辅助索引从而避免对索引视图或基表进行费时的全局扫描
由于索引需要不断维护所以为架构添加索引会增加数据库的额外开销因此应该认真考虑找到索引和维护额外开销之间的平衡点
使用索引视图的好处
实现索引视图之前请先分析数据库的工作量运用自己对查询以及各种工具(例如 SQL 分析器)的知识来鑒别使用索引视图可以获益的查询如果经常进行聚合和联接最好使用索引视图
并非所有查询都会从索引视图中获益与普通索引类似如果未使用索引视图就没有好处可言在此情况下不但不能提高性能还会加大磁盘空间的占用增加维护和优化的成本但是如果使用了索引视图它们可以(成数量级地)明显地提高数据访问的性能这是因为查询优化器使用存储在索引视图中的预先计算的结果从而大大降低了执行查询的成本
查询优化器只在查询的成本比较大时才考虑使用索引视图这样可以避免在查询优化成本超出因使用索引视图而节省的成本时试图使用各种索引视图当查询成本低于 时几乎不使用索引视图
使用索引视图可以受益的应用包括
决定支持工作量
数据集市
联机分析处理 (OLAP) 库和源
数据挖掘工作量
从查询的类型和模式的角度来看受益的应用可被归纳为包含以下内容的应用
大表的联接和聚合
查询的重复模式
重复聚合相同或重叠的列集
针对相同关键字重复联接相同的表
上述的组合
相反包含许多写入的联机事务处理 (OLTP) 系统或更新频繁的数据库可能会因为要同时更新视图和根本基表而使维护成本增加所以不能利用索引视图
查询优化器如何使用索引视图
SQL Server 查询优化器可自动确定何时可以将索引视图用于给定的查询执行中查询中无需直接引用视图优化器就可以将该视图用于查询执行计划因此无需对现有的应用程序本身进行任何更改这些应用程序即可利用索引视图唯一需要做的就是创建索引视图
优化器的考虑因素
查询优化器会考虑几个条件来确定索引视图能涵盖部分查询还是整个查询这些条件符合查询中的单个 FROM 子句并包含以下内容
查询 FROM 子句中的表必须是索引视图 FROM 子句中的表的超集
查询中的联接条件必须是视图中联接条件的超集
查询中的聚合列必须是视图中的聚合列的子集
查询选择列表中的所有表达式都必须源自于视图选择列表或源自于不包括在视图定义中的表
查询搜索条件谓词必须是视图定义中搜索条件谓词的超集视图搜索谓词中的每个合取项都必须以同样的形式出现在查询搜索谓词中
查询搜索条件谓词中的所有列(属于视图定义中的表)都必须出现在下列一项或多项中
视图定义中的同一个谓词
GROUP BY 列表
视图选择列表(若没有 GROUP BY 列表)
如果查询包含多个 FROM 子句(子查询派生表UNION)优化器可以选择多个索引视图来管理含有多个 FROM 子句的查询
注意 也存在例外情形即优化器可能将两个 FROM 子句折叠成一个(将子查询折叠成联接或将派生表折叠成联接变体)如果出现此类情况索引视图替换可能会涵盖原查询中的多个 FROM 子句
本文档结尾介绍了演示这些条件的查询示例而建议的最佳方法就是让查询优化器来确定在查询执行计划中使用哪些索引(如果有的话)
使用 NOEXPAND 选项
NOEXPAND 选项强制查询优化器象对待包含群集索引的普通表一样对待视图在此情况下必须在 FROM 子句中直接引用索引视图例如
SELECT Column Column FROM Table View WITH (NOEXPAND)WHERE
使用 EXPAND VIEWS 选项
另外用户可以在查询结束时通过使用 EXPAND VIEWS 选项明确地将索引视图排除在考虑之外例如
SELECT Column Column FROM Table View WHERE OPTION (EXPAND VIEWS)
如果使用该选项查询优化器在评估低成本的方法(该方法涉及查询中引用的列)时将忽略所有视图索引
设计的考虑因素
为数据库系统找到适当的索引集是相当复杂的尽管在设计普通索引时要考虑许多可能性但将索引视图添加到架构会极大地增加设计和潜在结果的复杂性例如索引视图可用于
查询中所引用表的任何子集
查询中条件的任何子集(属于表的上述子集)
分组列
聚合函数如 SUM
应同时设计表的索引和索引视图以便从各个结构中获得最佳结果由于索引和索引视图都可能对给定的查询有用所以单独设计它们会导致多余的建议方案以致存储和维护开销较高在调整数据库的物理设计时必须均衡考虑各种查询集的性能要求与数据库系统必须支持的更新操作因此为索引视图找到一种合理的物理设计是一项很具挑战性的任务因而应该尽可能地使用索引微调向导
如果存在许多索引视图可供查询优化器考虑用于特定查询查询优化成本会显着增加查询优化器可能考虑为查询中表的任意子集定义的所有索引视图拒绝每一个视图之前必须对它进行语法分析然后研究其是否可能成为潜在的替换体这可能需要一些时间尤其是在有数百个此类的视图用于给定的查询时
视图必须符合几项要求您才能为其创建唯一的群集索引在设计阶段请考虑以下要求
视图以及视图中引用的所有表都必须在同一数据库中并具有同一个所有者
索引视图无需包含要供优化器使用的查询中引用的所有表
必须先为视图创建唯一群集索引然后才可以创建其它索引
创建基表视图和索引以及修改基表和视图中的数据时必须正确设置某些 SET 选项(在本文档的后文中讨论)另外如果这些 SET 选项正确查询优化器将不考虑索引视图
视图必须使用架构绑定创建视图中引用的任何用户定义的函数必须使用 SCHEMABINDING 选项创建
另外还要求有一定的磁盘空间来存放由索引视图定义的数据
设计准则