您的位置:首页 > 数据库

SQL Server索引

2015-10-21 17:31 211 查看
聚集索引的顺序就是数据的物理存储顺序,因此一个表最多只能有一个聚集索引。

非聚集索引的顺序与物理存储顺序无关。

SQL Server 中的数据是按照 B树(B+树)来索引,那么聚集索引的叶结点存储的是数据本身,而非聚集索引的叶结点,只存储数据的引用,指针。

SQL Server 以页为单位存储数据,一个页占用8k的空间,在分配空间时以8个页,即一个盘区64k为单位。

覆盖索引

在建立索引时,将索引列之外的常用列 include 到索引之中,这样建立的索引就是覆盖索引。当查询中 select 和 where 等所需的列都包含在覆盖索引中时,就不再需要从表中读取行了。

复合索引

在两个或两个以上列建立的索引称为复合索引。

数据库读取

逻辑读取,在执行查询时,是读取存放在内存中的页,这些页是数据库预先读取到内存中去的。

物理读取,在执行查询时,SQL Server 会检查所需数据是否存在于内存中,如果没有,会从硬盘读取到内存中去。

预读取,一个SQL Server 处理的读取,将一部分数据预先读取到内存中,这些数据未必都是有需求的。

填充因子

在新增数据时,如果当前页已经满了,会拆分出新页,同时产生索引碎片。填充因子是在页中填充数据的比例,默认是100%,如果在一个页中设置填充因子是90%,那么在下一次新增数据的时候,页就不会拆分了(数据不是很大),也不会产生索引碎片,但是这样会需要更多的存储空间,也会加大 B树的深度,直接影响数据库效率。

一般来讲,填充因子的设置是因情况而定的。

如果一个表大部分的操作都是读取,那么可以设置填充因子为100%,因为很少会有拆分出新页的时候。如果读取和写入的操作各占一半,可以设置为80,90的比例。如果有大量的写入操作,那么就设置为50,70的比例。

当然,也可以将填充因子设置到100%,然后经常检查索引碎片,在需要的时候重建索引。

建立索引的原则

建立索引的字段尽量小,int 的索引比 text 索引好很多

建立索引的字段唯一性尽量高,不要在一亿数据的表上用性别建立索引。

如果数据库是事务性的,有大量的更新操作,建议每个表建立的索引不超过5个,如果是数据仓库型数据库,建立10个或更多索引也是可以的。

检测索引碎片

通过使用系统函数 sys.dm_db_index_physical_stats 来确定碎片程度。检测指定的索引、表、索引视图的所有索引、数据库中的所有索引或所有数据库中的所有索引碎片,对于已分区的索引,sys.dm_db_index_physical_stats 还提供每个分区的碎片信息。

外部碎片,向表中插入一行数据,页空间不足以容纳这行数据,将导致页拆分,拆分后的页和原来的页在磁盘上并不连续,导致外部碎片。

内部碎片,在页拆分后,索引页的内部空间并没有完全使用,同样读取一个索引页的时候,只能读取到索引页一定百分比的数据。

由 sys.dm_db_index_physical_stats 函数返回的结果集包含以下列:

avg_fragmentation_in_percent,逻辑碎片(索引中的无序页)的百分比,在SSMS索引属性中显示为碎片总计

avg_page_space_used_in_percent,所有页中使用的可用数据存储空间的平均百分比

fragment_count,索引中的碎片(物理上连续的叶页)数量

avg_fragment_size_in_pages,索引中一个碎片的平均页数

知道碎片程度后,可以确定修复碎片的最佳方法(根据avg_fragmentation_in_percent 值):

> 5% 且 < = 30%,ALTER INDEX REORGANIZE

> 30%,ALTER INDEX REBUILD WITH (ONLINE = ON)

这些值是一个大致的指导原则,用于确定重组和重建的临界点,实际值可能随情况发生变化。

也见有说法,外部碎片值介于10-15之间,内部碎片值介于60-75之间时使用重组,其它情况就应该使用重建。

重建索引可以联机执行,也可以脱机执行;重组索引始终要联机执行。

查看一个数据库中外部碎片>10,内部碎片<75的索引

SELECT object_name(dt.object_id) Tablename,si.name
IndexName,
dt.avg_fragmentation_in_percent AS ExternalFragmentation,
dt.avg_page_space_used_in_percent AS InternalFragmentation
FROM (SELECT object_id,index_id,avg_fragmentation_in_percent,avg_page_space_used_in_percent
FROM sys.dm_db_index_physical_stats (db_id('DatabaseName'),null,null,null,'DETAILED')
WHERE index_id <>0) AS dt INNER JOIN sys.indexes si ON si.object_id=dt.object_id
AND si.index_id=dt.index_id AND dt.avg_fragmentation_in_percent>10
AND dt.avg_page_space_used_in_percent<75 ORDER BY avg_fragmentation_in_percent DESC


重建索引并查看重建前后的I/O对比

SET STATISTICS IO ON
SELECT * FROM TABLENAME
ALTER INDEX IXNAME ON TABLENAME REBUILD
SELECT * FROM TABLENAME
SET STATISTICS IO OFF
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: