SQL Server数据库性能优化之索引篇

SQL Server性能优化涉及到许多方面,如良好的系统和数据库设计,优质的SQL编写,合适的数据表索引设计,甚至各种硬件因素:网络性能、服务器的性能、操作系统的性能,甚至网卡、交换机等。这篇文章主要讲到如何改善索引

当根据索引码的值搜索数据时,索引提供了对数据的快速访问。事实上,没有索引,数据库也能根据SELECT语句成功地检索到结果,但随着表变得越来越大,使用“适当”的索引的效果就越来越明显。索引有助于提高检索性能,但过多或不当的索引也会导致系统低效。因为用户在表中每加进一个索引,数据库就要做更多的工作。过多的索引甚至会导致索引碎片。所以,要建立一个“适当”的索引体系,特别是对聚合索引的创建,更应精益求精,以使数据库能得到高性能的发挥。

    简述SQL Server的索引
    SQL Server提供了两种索引:聚集索引(clustered index,也称聚类索引、簇集索引)和非聚集索引(nonclustered index,也称非聚类索引、非簇集索引)。
聚集索引确定表中数据的物理顺序。聚集索引类似于电话簿,后者按姓氏排列数据。由于聚集索引规定数据在表中的物理存储顺序,因此一个表只能包含一个聚集索引。但该索引可以包含多个列(组合索引),就像电话簿按姓氏和名字进行组织一样。
    聚集索引对于那些经常要搜索范围值的列特别有效。使用聚集索引找到包含第一个值的行后,便可以确保包含后续索引值的行在物理相邻。例如,如果应用程序执行的一个查询经常检索某一日期范围内的记录,则使用聚集索引可以迅速找到包含开始日期的行,然后检索表中所有相邻的行,直到到达结束日期。这样有助于提高此类查询的性能。同样,如果对从表中检索的数据进行排序时经常要用到某一列,则可以将该表在该列上聚集(物理排序),避免每次查询该列时都进行排序,从而节省成本。
    非聚集索引与课本中的索引类似。数据存储在一个地方,索引存储在另一个地方,索引带有指针指向数据的存储位置。索引中的项目按索引键值的顺序存储,而表中的信息按另一种顺序存储(这可以由聚集索引规定)。如果在表中未创建聚集索引,则无法保证这些行具有任何特定的顺序。
    更详细的介绍请参考MSDN上关于索引的介绍。http://msdn.microsoft.com/zh-cn/library/ms189271.aspx

使用SQL Server的索引
    问题又来了,既然分了两种索引,何时何种情况用何种索引?那就看看下表吧。简单的说就是:对于小数目的不同值,或列经常被分组排序,或需要返回某范围内的数据时使用聚集索引;对于大数目的不同值,或列经常被分组排序,或列被频繁更新时使用非聚集索引。


 


使用聚集索引


使用非聚集索引


列经常被分组排序




返回某范围内的数据



不应


一个或极少不同值


不应


不应


小数目的不同值



不应


大数目的不同值


不应



频繁更新的列


不应



外键列




主键列




频繁修改索引列


不应


如何改善索引的一些经验:

1. 索引首先要满足你的应用中最关键或者是被很多用户频繁执行的查询。
    若某个查询每月仅执行一次,要考虑是否值得为其涉及表创建了索引。要知道在当月的其它时间数据库系统对该索引的维护开销是要超过满足该查询的表扫描的开销的。所以,好钢用在刀刃上,好索引用在关键频繁的查询上。

2. 在经常进行连接,但是没有指定为外键的列上建立索引。
    在嵌套查询中,对表的顺序存取对查询效率可能产生致命的影响。比如采用顺序存取策略,一个嵌套3层的查询,如果每层都查询1000行,那么这个查询就要查询10亿行数据。避免这种情况的主要方法就是对连接的列进行索引。例如下面的一条SQL,连接这两个表:tblA(id, c1, c2, …)和tblB(id, …),就需要分别在两个表的id字段上建立索引。

select a.id, a.c1, a.c2, … from tblA a where exists (select 1 from tblB b where b.id = a.id)

3. 排序或分组对索引的影响
    · 在频繁进行排序或分组(即进行group   by或order   by操作)的列上建立索引。如果待排序的列有多个,可以在这些列上建立复合索引。
    · 索引中一定要包含所有的group by或order by操作列,且group by或order by操作列中列的次序一定要与索引中的次序相同。
    · 简化或避免对大数据量表的排序。当能够利用索引自动以适当的次序产生输出时,优化器就避免了排序的步骤。 
    · 排序的列若来自不同的表,同样会在执行计划中引起一个排序的开销。为了避免不必要的排序,就要正确地增建索引,合理地合并数据库表(尽管有时可能影响表的规范化,但相对于效率的提高是值得的)。如果排序不可避免,那么应当试图简化它,如缩小排序的列的范围等。

4. 非黑即白就别索引了
    在条件表达式中经常用到的不同值较多的列上建立非聚集索引,在不同值很少的列上就不要建立索引了。比如在某表的“状态”列上只有“是”与“否”两个不同值,就没必要建了,因为此时表扫描来得更有效。若建了索引,不但查询效率没提高,反而严重降低了更新速度。

5. “索引覆盖”是怎样炼成的
    对某个表tblA建了个聚集索引tblA_idx(c1, c2, c3)。这样实际上是建立了三个索引:(c1), (c1, c2), (c1, c2, c3)。

select min(c1) from tblA where c1 > 1 -- 会触发Clustered Index Seek。
select min(c1) from tblA where c1 > 1 and c2 = 2 -- 会触发Clustered Index Seek。
select min(c1) from tblA where c1 > 1 and c3 < 3 -- 会触发Clustered Index Scan。
select min(c1) from tblA where c2 = 2 and c3 < 3 -- 会触发Clustered Index Scan。
select min(c1) from tblA where c1 > 1 and c2 = 2 and c3 < 3 -- 会触发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开销也远大于后者。因此,优化重点应该放在前者。

时间: 2024-10-10 18:07:02

SQL Server数据库性能优化之索引篇的相关文章

SQL Server数据库性能优化之索引篇【转】

http://www.blogjava.net/allen-zhe/archive/2010/07/23/326966.html 性能优化之索引篇 近期项目需要, 做了一段时间的SQL Server性能优化,遇到了一些问题,也积累了一些经验,现总结一下,与君共享.SQL Server性能优化涉及到许多方面,如良好的系统和数据库设计,优质的SQL编写,合适的数据表索引设计,甚至各种硬件因素:网络性能.服务器的性能. 操作系统的性能,甚至网卡.交换机等.这篇文章主要讲到如何改善索引,还将有另一篇讨论

SQL Server数据库性能优化之SQL语句篇(转载)

SQL Server数据库性能优化之SQL语句篇 原文地址:http://www.blogjava.net/allen-zhe/archive/2010/07/23/326927.html 期项目需要,做了一段时间的SQL Server性能优化,遇到了一些问题,也积累了一些经验,现总结一下,与君共享.SQL Server性能优化涉及到许多方面,如良好的系统和数据库设计,优质的SQL编写,合适的数据表索引设计,甚至各种硬件因素:网络性能.服务器的性能.操作系统的性能,甚至网卡.交换机等.这篇文章主

SQL Server数据库性能优化之SQL语句篇

SQL Server数据库性能优化之SQL语句篇 近期项目需要,做了一段时间的SQL Server性能优化,遇到了一些问题,也积累了一些经验,现总结一下,与君共享.SQL Server性能优化涉及到许多方面,如良好的系统和数据库设计,优质的SQL编写,合适的数据表索引设计,甚至各种硬件因素:网络性能.服务器的性能.操作系统的性能,甚至网卡.交换机等.这篇文章主要讲到如何改善SQL语句,还将有另一篇讨论如何改善索引.如何改善SQL语句的一些原则: 1. 按需索取字段,跟“SELECT *”说拜拜

SQL Server数据库性能优化之SQL语句篇【转】

SQL Server数据库性能优化之SQL语句篇http://www.blogjava.net/allen-zhe/archive/2010/07/23/326927.html 近期项目需要, 做了一段时间的SQL Server性能优化,遇到了一些问题,也积累了一些经验,现总结一下,与君共享.SQL Server性能优化涉及到许多方面,如良好的系统和数据库设计,优质的SQL编写,合适的数据表索引设计,甚至各种硬件因素:网络性能.服务器的性能. 操作系统的性能,甚至网卡.交换机等.这篇文章主要讲到

SQL Server 查询性能优化——创建索引原则(一)

索引是什么?索引是提高查询性能的一个重要工具,索引就是把查询语句所需要的少量数据添加到索引分页中,这样访问数据时只要访问少数索引的分页就可以.但是索引对于提高查询性能也不是万能的,也不是建立越多的索引就越好.索引建少了,用WHERE子句找数据效率低,不利于查找数据.索引建多了,不利于新增.修改和删除等操作,因为做这些操作时,SQL SERVER除了要更新数据表本身,还要连带地立即更新所有的相关索引,而且过多的索引也会浪费硬盘空间.因此要建得恰到好处,这就需要经验了. 一:索引的基本目的 索引的基

转载——SQL Server数据库性能优化之SQL语句篇

转载自:http://www.blogjava.net/allen-zhe/archive/2010/07/23/326927.html 1. 按需索取字段,跟“SELECT *”说拜拜 字段的提取一定要按照“用多少提多少”的原则,避免使用“SELECT *”这样的操作.做了这样一个实验,表tblA有1000万数据: select top 10000 c1, c2, c3, c4 from tblA order by c1 desc  --用时:4673毫秒select top 10000 c1

SQL Server 数据库性能优化(转载)

原文地址:http://www.cnblogs.com/sydeveloper/archive/2013/04/03/2992881.html 一.数据库设计优化 1.不要使用游标. 使用游标不仅占用内存,而且还用不可思议的方式锁定表,它们可以使DBA所能做的一切性能优化等于没做.游标里每执行一次fetch就等于执行一次select. 2.创建适当的索引 每当为一个表添加一个索引,select会更快,可insert和delete却大大变慢,因为创建了维护索引需要许多额外的工作. (1)采用函数处

SQL Server 数据库性能优化

1. 查看执行时间和cpu set statistics time on select * from Bus_DevHistoryData set statistics time off 执行后在消息里可以看到 2. 查看查询对I/O的操作情况 set statistics io on select * from Bus_DevHistoryData set statistics io off 执行之后的结果: 扫描计数:索引和表执行次数 逻辑读取:数据缓存中读取的页数 物理读取:从磁盘中读取的

SQL Server数据库性能优化技巧

查询速度慢的原因很多,常见如下几种: 1.没有索引或者没有用到索引: 2.I/O吞吐量小,形成了瓶颈效应: 3.内存不足: 4.网络速度慢: 5.查询出的数据量过大: 6.锁或者死锁: 7.返回了不必要的行和列: 8.查询语句不好,没有优化. 可以通过如下方法来优化查询: 硬件/网络方面 1.升级硬件. 2.提高网速. 3.扩大服务器的内存. 4.增加服务器CPU个数. 5.把数据.日志.索引放到不同的I/O设备上. 6.DB Server和APP Server分离. 7.应用分布式分区视图.