SQL Server索引介绍

一、索引的分类

  • 聚集索引

SQL Server中的聚集索引是以B-tree的数据结构进行存储的。B-tree中每个数据页都是一个索引节点,最上端的索引节点被称为根节点,最下端的索引节点被称为叶子节点,根节点与叶子节点之间的索引节点为中间节点。

在聚集索引中,叶子节点包含了所有行记录数据。

聚集索引是按照索引键有序存储的。相对于堆存储,聚集索引的范围查询是非常高效的。

一张表只能有一个聚集索引,尽量将聚集索引列设置为IDENTITY。

聚集索引字段不宜进行频繁变更、不建议使用大宽列作为聚集索引。

当聚集索引只有一个字段分区时,其B-tree结构如下图所示,index_id=1为该字段分区的索引。当聚集索引有多个字段分区时,每个字段分区都有一个独立的B-tree结构。如一个聚集索引有4个字段分区,那么该表会创建4个B-tree结构。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6kbsC4q8-1594707963215)(http://note.youdao.com/yws/res/59746/0D8CD630FF3142BD9E0D0FE023C59725)]

  • 非聚集索引

非聚集索引可以氛围两种情况,一种情况是索引组织表存储、另外一种情况是堆表存储。

无论是堆表还是索引组织表,非聚集索引的存储结构都是B-tree存储,都是根据索引键有序存储。堆表与索引组织表的区别主要在于其叶子节点存储内容,堆表通过行指针指向其对应的RID、索引组织表通过行指针指向其对应的聚集索引值。

当使用非聚集索引查询数据时,遍历非聚集索引定位满足条件的数据,然后通过Bookmark的方式根据对应的聚集索引查找非聚集索引外的其他字段数据。

非聚集索引的索引长度上限为900字节,include字段不包含在索引键中,不计算其字段长度

如:Title nvarchar(50)、Revision nchar(5)、FileName nvarchar(400)
可以创建复合索引(Title,Revision) include (FileName),其索引长度为(50+5)*2

CREATE INDEX IX_Document_Title   
ON Production.Document (Title, Revision)   
INCLUDE (FileName);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3nYGOMwG-1594707963218)(http://note.youdao.com/yws/res/59794/E30AAE6A15B341268519CF2AE9BE349B)]

  • 唯一索引

保证索引字段唯一性的约束,一张表可以有多个唯一索引。

唯一索引也可以使用include字段做包含性索引

  • 复合索引

多个字段创建的索引称为复合索引,复合索引需要注意各字段的顺序,建议把选择性高的字段、查询频繁的字段放在前缀列

  • 包含性索引

包含性索引的关键字是include,该索引与覆盖索引类似,都是为了避免回表操作。与覆盖索引不同的是,include字段不在索引键列,而是在非键列,所以无法对include字段进行条件过滤,仅仅为了select查询字段避免回表使用。

在包含性索引中,非键列最大上限为1023

索引键列最大上限为16、字段长度为900字节

同一列无法同时出现在索引键以及include非键列

  • 覆盖索引

查询与过滤字段均通过索引键就可以返回,不需要回表操作,合理使用覆盖索引进行优化。

  • 筛选索引

也称为过滤索引,创建是通过where关键字进行筛选,满足条件的记录创建索引,不满足条件的记录不包含在索引中。

-- 在view_count字段中满足>50的记录上创建索引
create nonclustered index idx_count on deadlock_test(view_count) where view_count>50;

-- 有效利用筛选索引
select id from deadlock_test where view_count>60
-- 无法有效利用筛选索引
select id from deadlock_test where view_count<30
  • 计算列索引

在表中创建一个新的字段用于保存列只算后的结果,为该字段创建索引后,这个索引成为计算索引

计算列数据实际存储在表中,需要额外创建一个字段来添加索引,功能使用上还不如mysql5.7的虚拟列的设计。

CREATE TABLE TestTable (a int, b varbinary(4));

CREATE INDEX TestTabIndex ON dbo.TestTable(a,b)  
WHERE b = CONVERT(Varbinary(4), 1);
  • 索引视图

物化视图,标准的视图不会将结果集永久的存储在数据库中,而是每次使用的时候动态生成,而索引视图通过with schemabinding 的关键字为视图创建唯一聚集索引来把结果集保存在数据库中。

  • 列存储索引

二、聚集索引表和堆表

1、聚集索引表

也叫索引组织表,表的存储是按照聚集索引的顺序进行存储的,聚集索引的叶子节点包含所有记录。二级索引中的叶子节点指向对应的聚集索引值,当查询需要回表时通过聚集索引回表查询。

2、堆表

在SQL Server中,若没有为表创建聚集索引,则该表存储的方式为堆表存储。堆就是无序数据的集合,索引就是将数据变得有序,在索引中键值有序,数据还是无序的。在堆表中,二级索引的每个键都会指向一个RID,若需要查询非索引外其他字段数据通过RID进行回表查询。

三、索引相关命令

1、索引缺失统计

-- 索引缺失统计
select ddmid.statement,ddmid.equality_columns,ddmid.inequality_columns,ddmid.included_columns,
ddmigs.user_seeks,ddmigs.user_scans,ddmigs.avg_total_user_cost,ddmigs.avg_user_impact
from sys.dm_db_missing_index_details ddmid
join sys.dm_db_missing_index_groups ddmig
on ddmid.index_handle=ddmig.index_handle
join sys.dm_db_missing_index_group_stats ddmigs
on ddmig.index_group_handle=ddmigs.group_handle
字段 含义
statement 缺失索引的表名
user_seeks 从服务端启动到现在,缺失索引可以被用户发起请求用于seek操作的次数
user_scans 从服务器启动到现在,缺失索引可以被用户发起请求用于scan操作的次数
avg_total_user_cast 缺失索引被创建后,平均降低资源消耗的成本数,该参数越大表示创建索引后效率提升越高
avg_user_impact 缺失索引创建后,平均降低成本的百分比

2、无效索引统计

-- 无效索引统计
select i.name,ddius.user_seeks,ddius.user_lookups,ddius.user_updates
from sys.dm_db_index_usage_stats ddius
join sys.indexes i
on ddius.index_id=i.index_id and ddius.object_id=i.object_id
order by ddius.user_seeks

3、查看索引的统计信息

-- 查看具体索引的统计信息
dbcc show_statistics('deadlock_test','idx_info_uuid')

-- 查看表中所有索引的统计信息
select * 
from sys.stats as s
where s.object_id=object_id('table_name')

-- 更新指定索引的统计信息
UPDATE STATISTICS dbo.table_name idx_name;

-- 更新表中所有统计信息
UPDATE STATISTICS Sales.SalesOrderDetail;

--更新整个数据库上的所有统计信息
EXEC sp_updatestats;

猜你喜欢

转载自blog.csdn.net/weixin_37692493/article/details/107337391