舒适提示:本篇内容均来自网上,本人只作了稍微处理,未进行细致研究,仅当作之后不备之需,如若你喜欢可尽情转走。 数据库
不少数据库系统性能不理想是由于系统没有通过总体优化,存在大量性能低下的SQL 语句。这类SQL语句性能很差的首要缘由是缺少高效的索引。没有索引除了致使语句自己运行速度慢外,更是致使大量的磁盘读写操做,使得整个系统性能都受之影响而变差。 ide
解决这类系统的首要办法是优化这些没有索引或索引不够好的SQL语句。 性能
1、建立索引的关键 大数据
优化SQL语句的关键是尽量减小语句的logical reads。这里说的logical reads是指语句执行时须要访问的单位为8K的数据页总数。logical reads 越少,其须要的内存和CPU时间也就越少,语句执行速度就越快。不言而喻,索引的最大好处是它能够极大减小SQL语句的logical reads数目,从而极大减小语句的执行时间。 优化
建立索引的关键是索引要可以大大减小语句的logical reads。一个索引好很差,主要看它减小的logical reads多很少。 .net
运行set statistics io命令能够获得SQL语句的logical reads信息。 排序
set statistics io on 索引
select au_id,au_lname ,au_fname 事务
from pubs..authors where au_lname ='Green' 内存
set statistics io on
若是Logical reads很大,而返回的行数不多,也即二者相差较大,那么每每意味者语句须要优化。Logical reads中包含该语句从内存数据缓冲区中访问的页数和从物理磁盘读取的页数。而physical reads表示那些没有驻留在内存缓冲区中须要从磁盘读取的数据页。Read-ahead reads是SQL Server为了提升性能而产生的预读。预读可能会多读取一些数据。
优化的时候咱们主要关注Logical Reads就能够了。
注意若是physical Reads或Read-ahead reads很大,那么每每意味着语句的执行时间(duration)里面会有一部分耗费在等待物理磁盘IO上。
2、单字段索引,组合索引和覆盖索引
单字段索引是指只有一个字段的索引,而组合索引指有多个字段构成的索引。
1. 对出如今where子句中的字段加索引
set statistics profile on
set statistics io on
go
select .... from tb where ...
go
set statistics profile off
set statistics io off
set statistics profile命令将输出语句的执行计划。也许你会问,为何不用SET SHOWPLAN_ALL呢?使用SET SHOWPLAN_ALL也是能够的。不过set statistics profile输出的是SQL 语句的运行时候真正使用的执行计划,而SET SHOWPLAN_ALL输出的是预计(Estimate)的执行计划。使用SET SHOWPLAN_ALL是后面的语句并不会真正运行。
用了Table Scan,也就是对整个表进行了全表扫描。全表扫描的性能一般是不好的,要尽可能避免。
若是上面的select语句是数据库系统常常运行的关键语句, 那么应该对它建立相应的索引。建立索引的技巧之一是对常常出如今where条件中的字段建立索引,Table Scan也变成了Index Seek,性能极大提升设法避免Table scan或Index scan是优化SQL 语句使用的经常使用技巧。一般Index Seek须要的logical reads比前二者要少得多。
2.组合索引
若是where语句中有多个字段,那么能够考虑建立组合索引。组合索引中字段的顺序是很是重要的,越是惟一的字段越是要靠前。另外,不管是组合索引仍是单个列的索引,尽可能不要选择那些惟一性很低的字段。
好比说,在只有两个值0和1的字段上创建索引没有多大意义。因此若是对单字段进行索引,建议使用set statistics profile来验证索引确实被充分使用。logical reads越少的索引越好。
3.覆盖索引
覆盖索引可以使得语句不须要访问表仅仅访问索引就可以获得全部须要的数据。由于汇集索引叶子节点就是数据因此无所谓覆盖与否,因此覆盖索引主要是针对非汇集索引而言。
执行计划中除了index seek外,还有一个Bookmark Lookup关键字。Bookmark Lookup表示语句在访问索引后还须要对表进行额外的Bookmark Lookup操做才能获得数据。
也就是说为获得一行数据起码有两次IO,一次访问索引,一次访问基本表。
若是语句返回的行数不少,那么Bookmark Lookup操做的开销是很大的。覆盖索引可以避免昂贵的Bookmark Lookup操做,减小IO的次数,提升语句的性能。覆盖索引须要包含select子句和WHERE子句中出现的全部字段。Where语句中的字段在前面,select中的在后面。
logical reads,是大大减小了。Bookmark Lookup操做也消失了。因此建立覆盖索引是减小logical reads提高语句性能的很是有用的优化技巧。
实际上索引的建立原则是比较复杂的。有时候你没法在索引中包含了Where子句中全部的字段。在考虑索引是否应该包含一个字段时,应考虑该字段在语句中的做用。
好比说若是常常以某个字段做为where条件做精确匹配返回不多的行,那么就绝对值得为这个字段创建索引。
再好比说,对那些很是惟一的字段如主键和外键,常常出如今group by,order by中的字段等等都值得建立索引。
问题1,是否值得在identity字段上创建汇集索引。
答案取决于identity 字段如何在语句中使用。若是你常常根据该字段搜索返回不多的行,那么在其上创建索引是值得的。反之若是identity字段根本不多在语句中使用,那么就不该该对其创建任何索引。
问题2,一个表应该创建多少索引合适。
若是表的80%以上的语句都是读操做,那么索引能够多些。可是不要太多。特别是不要对那些更新频繁的表其创建不少的索引。不多表有超过5个以上的索引。过多的索引不但增长其占用的磁盘空间,也增长了SQL Server 维护索引的开销。
问题3:为何SQL Server在执行计划中没有使用你认为应该使用的索引?缘由是多样的。
一种缘由是该语句返回的结果超过了表的20%数据,使得SQL Server 认为scan比seek更有效。另外一种缘由多是表字段的statistics过时了,不能准确反映数据的分布状况。你可使用命令UPDATE STATISTICS tablename with FULLSCAN来更新它。
只有同步的准确的statistics才能保证SQL Server 产生正确的执行计划。过期的老的statistics常会致使SQL Server生成不够优化的甚至愚蠢的执行计划。
因此若是你的表频繁更新,而你又以为和之相关的SQL语句运行缓慢,不妨试试UPDATE STATISTIC with FULLSCAN 语句。
问题四、什么使用汇集索引,何时使用非汇集索引
在SQL Server 中索引有汇集索引和非汇集索引两种。它们的主要差异是前者的索引叶子就是数据自己,然后者的叶子节点包含的是指向数据的书签(即数据行号或汇集索引的key)。
对一个表而言汇集索引只能有一个,而非汇集索引能够有多个。
只是汇集索引没有Bookmark Lookup操做。
何时应该使用汇集索引? 何时使用非汇集索引? 取决于应用程序的访问模式。
个人建议是在那些关键的字段上使用汇集索引。一个表通常都须要创建一个汇集索引。
对于何时使用汇集索引,SQL Server 2000联机手册中有以下描述:
在建立汇集索引以前,应先了解您的数据是如何被访问的。可考虑将汇集索引用于:
包含大量非重复值的列。
使用下列运算符返回一个范围值的查询:BETWEEN、>、>=、< 和 <=。
被连续访问的列。
返回大型结果集的查询。
常常被使用联接或 GROUP BY 子句的查询访问的列;通常来讲,这些是外键列。
对 ORDER BY 或 GROUP BY 子句中指定的列进行索引,可使 SQL Server 没必要对数据进行排序,由于这些行已经排序。这样能够提升查询性能。
OLTP 类型的应用程序,这些程序要求进行很是快速的单行查找(通常经过主键)。应在主键上建立汇集索引。
汇集索引不适用于:
频繁更改的列
这将致使整行移动(由于 SQL Server 必须按物理顺序保留行中的数据值)。这一点要特别注意,由于在大数据量事务处理系统中数据是易失的。
宽键
来自汇集索引的键值由全部非汇集索引做为查找键使用,所以存储在每一个非汇集索引的叶条目内。
总结:
如何使一个性能缓慢的系统运行更快更高效,不但须要总体分析数据库系统,找出系统的性能瓶颈,更须要优化数据库系统发出的SQL 语句。
一旦找出关键的SQL 语句并加与优化,性能问题就会迎刃而解。