SQL Server性能调优--索引(1)
序言
索引的概念
索引是什么
数据库中的索引类似于一本书的目录,在一本书中使用目录可以快速找到你想要的信息,而不需要读完全书。在数据库中,数据库程序使用索引可以快速查询到表中的数据,而不必扫描整个表。书中的目录是一个字词以及各字词所在的页码列表,数据库中的索引是表中的值以及各值存储位置的列表。
例如:数据库中有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)
强制指定索引
from 表名 with (nolock,INDEX([acctstat001] ))
资料
https://www.cnblogs.com/knowledgesea/p/3672099.html
https://www.cnblogs.com/selene/p/4474721.html
https://blog.csdn.net/zc474235918/article/details/50580639