SQL Server性能调优--索引

序言

索引的概念

索引是什么

  数据库中的索引类似于一本书的目录,在一本书中使用目录可以快速找到你想要的信息,而不需要读完全书。在数据库中,数据库程序使用索引可以快速查询到表中的数据,而不必扫描整个表。书中的目录是一个字词以及各字词所在的页码列表,数据库中的索引是表中的值以及各值存储位置的列表。

  例如:数据库中有20000条记录,现在要执行这样一个查询:SELECT * FROM tableName WHERE num=10000。如果没有索引,必须遍历整个表,直到num=10000的这一行为止;如果在num列上创建索引,SQL Server不需要任何扫描,直接在索引里面找10000,就可以得知这一行的位置。可见,索引的建立可以加快数据的查询速度。

  不同数据库中提供了不同的索引类型,SQL Server中的索引有两种:聚集索引和非聚集索引。它们的区别是在物理数据的存储方式上。

  没有聚集索引的数据表都称为堆表。即使上面有非聚集索引,也还是堆表。

索引的分类

1.聚集索引(CLUSTERED)

  聚集索引基于数据行的键值,在表内排序和存储这些数据行。每个表只能有一个聚集索引,因为数据行本身只能按一个顺序存储。

  聚集索引的所有的数据都存储在叶子节点上,数据查询的复杂度都是一样的(树的深度),按照聚集索引列查找数据效率是非常高的。

  上面说了,聚集索引决定了表的物理存储结构,那如果没有创建聚集索引,会如何呢?

  表内的所有页都无序存放,是一个无序的堆结构。堆数据的查询就会造成表扫描,性能是非常低的。

  因此聚集索引的的重要性不言而喻,一般来说,大多会对主键建立聚集索引,大多数普通情况这么做也可以。

  但实际应用应该尊从一个原则就是“频繁使用的、排序的字段上创建聚集索引”

  提示:SQL Server中,一个表只能创建1个聚集索引,多个非聚集索引。设置某列为主键,该列就默认为聚集索引

2.非聚集索引(NONCLUSTERED)

  非聚集索引就相当于使用字典的部首查找,非聚集索引是逻辑上的连续,物理存储并不连续

  PS:聚集索引一个表只能有一个,而非聚集索引一个表可以存在多个。

  除了聚集索引以外的其他索引,都称之为非聚集索引。通常,设计非聚集索引是为了改善经常使用的、没有建立聚集索引的查询的性能。

  创建唯一非聚集索引

CREATE UNIQUE INDEX ProviderInfo_Id_uindex ON dbo.ProviderInfo(Id)

  非聚集索引也是B树(B+树和B-树)的结构,与非聚集索引的存储结构唯一不一样的,就是非聚集索引中不存储真正的数据行。

  聚集索引中已经存放了所有数据,非聚集索引只包含一个指向数据行的指针即可。

  非聚集索引的创建会单独创建索引文件来存储索引结构,会占用一定存储空间,就是用空间换时间;

  非聚集索引的目的很单纯:提高特定条件的查询效率,一个表有可能根据多种查询需求创建多个非聚集索引;

聚集索引与非聚集索引

  在聚集索引中,表中行的物理顺序与键值的逻辑(索引)顺序相同。一个表只能包含一个聚集索引,默认是主键列,聚集索引通常提供更快的数据访问速度。

  非聚集索引可以有多个,物理顺序与键值的逻辑(索引)顺序可以不相同。一个简单的例子:对一个教室的学生,每个人都有一个座位号(座位是物理存在的,只有一种排序,这就是聚集索引),我们可以按学生的年龄、身高、体重排序(这样排出来的顺序座号不连续即物理上不连续,在逻辑上是连续的,就是非聚集索引)

3.唯一索引(UNIQUE)

  每一行的索引值都是唯一的(创建了唯一约束,系统将自动创建唯一索引)

4.主键索引

5.列式存储索引

  列存储索引是SQL Server 2012中为提高数据查询的性能而引入的一个新特性,顾名思义,数据以列的方式存储在页中,不同于聚集索引、非聚集索引及堆表等以行为单位的方式存储。

索引包含列

什么是包含列?

  所谓的包含列就是包含在非聚集索引中,并且不是索引列中的列。或者说的更通俗一点就是:把一些底层数据表的数据列包含在非聚集索引的索引页中,而这些数据列又不是索引列,那么这些列就是包含列。同时,这些包含列并不会对索引中的条目有影响。

为什么要创建带有包含列的索引?

  把需要用到的字段放到包含索引中(在返回的索引中就包含了一切),不用再查物理表,可以达到最优的速度。

什么时候需要建立带有包含列的索引,什么时候不需要建立带有包含列的索引?

其实把一些列作为包含列放在索引结构中就是一种用“空间换时间”的策略。

这个时候,大家可能就会问了:“何必把列放在包含列中这么麻烦,为什么不直接放在索引中?”。

其实把那三个列放在包含列而不是索引列中有以下几个好处:

总结:如何把一些列作为包含列放在索引中,那么就可以在一定的程度上面提升效率,可以把原本需要整表扫描的操作,改为非聚集索引扫描,这样的成本更小。

索引的设计原则

字段上只有【男】或【女】两个不同值,因此就无需建立索引,如果建立索引,不但不会提高查询效率,反而会严重降低更新速度。

在频繁进行排序或分组(即进行GROUP BY 或ORDER BY操作)的列上建立索引,如果待排序的列有多个,可以在这些列上建立组合索引。

索引碎片

  前面说过了,索引在使用一段时间后(主要是新增、修改、删除数据,如果该页已经存储满了,就要进行页的拆分,频繁的拆分,会产生较多的索引碎片)会产生索引碎片,这就造成了索引页在磁盘上存储的不连续。

 

 常用索引语句

在表上创建一个唯一的索引。唯一的索引意味着两个行不能拥有相同的索引值。

CREATE UNIQUE INDEX ProviderInfo_Id_uindex ON dbo.ProviderInfo(Id)

资料

https://www.cnblogs.com/knowledgesea/p/3672099.html

https://www.cnblogs.com/selene/p/4474721.html

https://blog.csdn.net/zc474235918/article/details/50580639

SQL Server索引进阶第五篇:索引包含列

原文地址:https://www.cnblogs.com/cnki/p/8666079.html