数据库聚簇索引和非聚簇索引,页分裂的介绍及会产生的问题(整理自网络)

参考

http://www.mamicode.com/info-detail-549679.html

https://blog.csdn.net/wen_3370/article/details/56667906

聚簇索引(Clustered Index)和非聚簇索引 (Non- Clustered Index)

最通俗的解释是:聚簇索引的顺序就是数据的物理存储顺序,而对非聚簇索引的索引顺序与数据物理排列顺序无关。举例来说,你翻到新华字典的汉字“爬”那一页就是P开头的部分,这就是物理存储顺序(聚簇索引);而不用你到目录,找到汉字“爬”所在的页码,然后根据页码找到这个字(非聚簇索引)。

下表给出了何时使用聚簇索引与非聚簇索引:
动作
使用聚簇索引
使用非聚簇索引
列经常被分组排序


返回某范围内的数据

不应
一个或极少不同值
不应
不应
小数目的不同值

不应
大数目的不同值
不应

频繁更新的列
不应

外键列


主键列


频繁修改索引列
不应



聚簇索引的唯一性
正式聚簇索引的顺序就是数据的物理存储顺序,所以一个表最多只能有一个聚簇索引,因为物理存储只能有一个顺序。正因为一个表最多只能有一个聚簇索引,所以它显得更为珍贵,一个表设置什么为聚簇索引对性能很关键。

误区:把主键自动设为聚簇索引
因为这是SQLServer的默认主键行为,你设置了主键,它就把主键设为聚簇索引,而一个表最多只能有一个聚簇索引,所以很多人就把其他索引设置为非聚簇索引。这个是最大的误区。甚至有的主键又是无意义的自动增量字段,那样的话Clustered index对效率的帮助,完全被浪费了。

刚才说到了,聚簇索引性能最好而且具有唯一性,所以非常珍贵,必须慎重设置。一般要根据这个表最常用的SQL查询方式来进行选择,某个字段作为聚簇索引,或组合聚簇索引,这个要看实际情况。

事实上,建表的时候,先需要设置主键,然后添加我们想要的聚簇索引,最后设置主键,SQLServer就会自动把主键设置为非聚簇索引(会自动根据情况选择)。如果你已经设置了主键为聚簇索引,必须先删除主键,然后添加我们想要的聚簇索引,最后恢复设置主键即可。

Index seek 为什么比 Index scan好?
索引扫描也就是遍历B树,而seek是B树查找直接定位。
Index scan多半是出现在索引列在表达式中。数据库 引擎 无法直接确定你要的列的值,所以只能扫描整个整个索引进行计算。index seek就要好很多.数据库引擎只需要扫描几个分支节点就可以定位到你要的记录。回过来,如果聚集索引的叶子节点就是记录,那么Clustered Index Scan就基本等同于full table scan。

一些优化原则
1、缺省情况下建立的索引是非聚簇索引,但有时它并不是最佳的。在非群集索引下,数据在物理上随机存放在数据页上。合理的索引 设计 要建立在对各种查询的分析和预测上。一般来说: 
a.有大量重复值、且经常有范围查询( > ,< ,> =,< =)和order by、group by发生的列,可考 
虑建立群集索引; 
b.经常同时存取多列,且每列都含有重复值可考虑建立组合索引; 
c.组合索引要尽量使关键查询形成索引覆盖,其前导列一定是使用最频繁的列。索引虽有助于提高性能但不是索引越多越好,恰好相反过多的索引会导致系统低效。 用户 在表中每加进一个索引,维护索引集合就要做相应的更新工作。 

2、ORDER BY和GROPU BY使用ORDER BY和GROUP BY短语,任何一种索引都有助于SELECT的性能提高。 

3、多表操作在被实际执行前,查询优化器会根据连接条件,列出几组可能的连接 方案 并从中找出系统开销最小的最佳方案。连接条件要充份考虑带有索引的表、行数多的表;内外表的选择可由公式:外层表中的匹配行数*内层表中每一次查找的次数确定,乘积最小为最佳方案。

4、任何对列的操作都将导致表扫描,它包括数据库 函数 、计算表达式等等,查询时要尽可能将操作移至等号右边。 

5、IN、OR子句常会使用工作表,使索引失效。如果不产生大量重复值,可以考虑把子句拆开。拆开的子句中应该包含索引。

建聚集索引,表格内的数据会按照索引的序存在数据的数据面中,当新的数据行插入到数据表中,或更新表中的数据SQLServer 刷新数据在数据中的存位置,这样,就致索引中的数据存方式改,当中数据已的情况下,就将会建一个新,并将原有中的一半数据放入新中,以挪出空间给新的记录行使用。注:当分裂的次数,会影响效率.

 分裂原因:

当一个数据达到了8K容量,如果此时发生插入或更新数据的操作,将的分裂(又名拆分)

有聚集索引的情况下:聚集索引将被插入和更新的行指向特定的该页由聚集索引关键字决定;

扫描二维码关注公众号,回复: 1519278 查看本文章

只有堆的情况下:只要有空就可以插入新的行,但是如果我们对行数据的更新需要更多的空,以致大于当前的可用空,行就被移到新的中,并且在原位置留下一个转发,指向被移的新行,如果具有转发的行又被移了,那原来的指将重新指向新的位置;

如果堆中有非聚集索引,那尽管插入和更新操作在堆中不会分裂,但是在非聚集索引上仍然分裂。无有无索引,大一半的数据将保留在老面,而另一半将放入新面,并且新面可能被分配到任何可用的。所以,分裂,后果很重,将使物理表生大量数

据碎片,致直接造成I/O 效率的急下降,最后,不得不停止SQLS 的运行并重建索引。

解决方法:置适当的填充因子

填充因子(fillfactor)

然而在混沌之初,就可以在一定程度上避免不愉快出,在建索引,可以为这个索引指定一个填充因子,以便在索引的个叶级页面上保留一定百分比的空,将来数据可以充和减少分裂。填充因子是从100 的百分比数设为100 表示将数据,只有当不会数据行更改(例如只表中)才用此置。越小数据上的空越大,这样可以减少在索引增长过程中分裂的需要,但一操作需要占用更多的硬

例如,当填充因子的值为50 ,数据取性能会降低两倍。所以,只有在表中根据有数据建新索引,并且可以预见将来会对这些数据行哪些更改置填充因子才有意

填充因子(Fillfactor:

指定 SQL Server索引数据时每个索引的充程度。用指定的 fillfactor 到 100

如果没有指定 fillfactor认为0

点:减少了面分裂的次数

缺点:增大了使用的存

猜你喜欢

转载自blog.csdn.net/yanshuanche3765/article/details/80548216