http://www.blogjava.net/allen-zhe/archive/2010/07/23/326966.html 性能优化之索引篇html
近期项目须要, 作了一段时间的SQL Server性能优化,遇到了一些问题,也积累了一些经验,现总结一下,与君共享。SQL Server性能优化涉及到许多方面,如良好的系统和数据库设计,优质的SQL编写,合适的数据表索引设计,甚至各类硬件因素:网络性能、服务器的性能、 操做系统的性能,甚至网卡、交换机等。这篇文章主要讲到如何改善索引,还将有另外一篇讨论如何改善SQL语句。
首先须要强调一下,水能载舟,亦能覆舟。创建“适当”的索引是实现查询优化的首要前提。
当根据索引码的值搜索数据时,索引提供了对数据的快速访问。事实上,没有索引,数据库也能根据SELECT语句成功地检索到结果,但随着表变得越 来越大,使用“适当”的索引的效果就愈来愈明显。索引有助于提升检索性能,但过多或不当的索引也会致使系统低效。由于用户在表中每加进一个索引,数据库就 要作更多的工做。过多的索引甚至会致使索引碎片。因此,要创建一个“适当”的索引体系,特别是对聚合索引的建立,更应精益求精,以使数据库能获得高性能的 发挥。
简述SQL Server的索引
SQL Server提供了两种索引:汇集索引(clustered index,也称聚类索引、簇集索引)和非汇集索引(nonclustered index,也称非聚类索引、非簇集索引)。
汇集索引肯定表中数据的物理顺序。汇集索引相似于电话簿,后者按姓氏排列数据。因为汇集索引规定数据在表中的物理存储顺序,所以一个表只能包含一个汇集索引。但该索引能够包含多个列(组合索引),就像电话簿按姓氏和名字进行组织同样。
汇集索引对于那些常常要搜索范围值的列特别有效。使用汇集索引找到包含第一个值的行后,即可以确保包含后续索引值的行在物理相邻。例如,若是应用 程序执行的一个查询常常检索某一日期范围内的记录,则使用汇集索引能够迅速找到包含开始日期的行,而后检索表中全部相邻的行,直到到达结束日期。这样有助 于提升此类查询的性能。一样,若是对从表中检索的数据进行排序时常常要用到某一列,则能够将该表在该列上汇集(物理排序),避免每次查询该列时都进行排 序,从而节省成本。
非汇集索引与课本中的索引相似。数据存储在一个地方,索引存储在另外一个地方,索引带有指针指向数据的存储位置。索引中的项目按索引键值的顺序存 储,而表中的信息按另外一种顺序存储(这能够由汇集索引规定)。若是在表中未建立汇集索引,则没法保证这些行具备任何特定的顺序。
更详细的介绍请参考MSDN上关于索引的介绍。http://msdn.microsoft.com/zh-cn/library/ms189271.aspx java
使用SQL Server的索引
问题又来了,既然分了两种索引,什么时候何种状况用何种索引?那就看看下表吧。简单的说就是:对于小数目的不一样值,或列常常被分组排序,或须要返回某范围内的数据时使用汇集索引;对于大数目的不一样值,或列常常被分组排序,或列被频繁更新时使用非汇集索引。
数据库
|
使用汇集索引性能优化 |
使用非汇集索引服务器 |
列常常被分组排序网络 |
应数据库设计 |
应性能 |
返回某范围内的数据优化 |
应spa |
不该 |
一个或极少不一样值 |
不该 |
不该 |
小数目的不一样值 |
应 |
不该 |
大数目的不一样值 |
不该 |
应 |
频繁更新的列 |
不该 |
应 |
外键列 |
应 |
应 |
主键列 |
应 |
应 |
频繁修改索引列 |
不该 |
应 |
如何改善索引的一些经验:
1. 索引首先要知足你的应用中最关键或者是被不少用户频繁执行的查询。
若某个查询每个月仅执行一次,要考虑是否值得为其涉及表建立了索引。要知道在当月的其它时间数据库系统对该索引的维护开销是要超过知足该查询的表扫描的开销的。因此,好钢用在刀刃上,好索引用在关键频繁的查询上。
2. 在常常进行链接,可是没有指定为外键的列上创建索引。
在嵌套查询中,对表的顺序存取对查询效率可能产生致命的影响。好比采用顺序存取策略,一个嵌套3层的查询,若是每层都查询 1000行,那么这个查询就要查询10亿行数据。避免这种状况的主要方法就是对链接的列进行索引。例以下面的一条SQL,链接这两个表:tblA(id, c1, c2, …)和tblB(id, …),就须要分别在两个表的id字段上创建索引。
其中Clustered Index Scan的执行计划
其中Clustered Index Seek的执行计划
如此可见造成索引覆盖的必要性。
6. 非汇集索引与精确查找的默契
对于某个表中的某个字段存在大数目的不一样值时,为该字段建个非汇集索引会达到意想不到的效果。由于数据库系统在搜索数据值时,先对非汇集索引进行 搜索,找到数据值在表中的位置,而后从该位置直接检索数据。由于索引包含描述查询所搜索的数据值在表中的精确位置的条目,这也是为何非汇集索引是精确匹 配查询的最佳方法。例如,在employee表为emp_id列建了非汇集索引,要搜索其雇员ID (emp_id) > 1000的全部人,SQL Server会在索引中直接跳到emp_id = 1000这样一个条目以后,列出匹配的emp_id列在表中的页和行,而后直接转到该页该行。
7. 若是你是皮尔斯,SQL Server 的执行计划就是朗多
SQL Server 2005的Microsoft SQL Server Management Studio和Database Engine Tuning Advisor(DETA)是很是好的性能调试助手,可使用它们对SQL语句调优,查看估计的执行计划开销,用DETA生成优化建议,采纳或参考索引优 化部分。
须要注意的是,对于估计的执行计划,不要过于关注里面显示的开销比例,而实际上这个有时会误导。我在实际优化过程当中就被发现,一个index scan的执行项开销只占25%,另外一个键查找的开销占50%,而键查找部分根本没有可优化的,SEEK谓词就是ID=XXX这个创建在主键上的查找。而 仔细分析能够看到,后者CPU开销0.00015,I/O开销0.0013。而前者呢,CPU开销1.4xxxx,I/O开销也远大于后者。所以,优化重 点应该放在前者。
网上这类的文章不少,这里就不作赘述了。能够参考一篇较早的文章:SQL Server性能调优入门(图文版)
另外还有一篇不错的文章,共享在这里:探讨如何在有着1000万条数据的MS SQL SERVER数据库中实现快速的数据提取和数据分页