SQL SERVER大话存储结构_复合索引与包含索引
Posted 有梦就能实现
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL SERVER大话存储结构_复合索引与包含索引相关的知识,希望对你有一定的参考价值。
1 语法及说明
--复合索引 CREATE INDEX IndexName ON tbname(columna,columnb [,columnc...] ) --包含索引 CREATE INDEX IndexName ON tbname(columna [,columnb,columnc...] ) INCLUDE (column1 [,column2,column3...])
2 索引页存储情况
2.1 创建测试表格
1 CREATE TABLE tbindex( 2 id int identity(1,1) not null primary key , 3 name varchar(50) not null, 4 type varchar(10) not null, 5 numbers int not null 6 ) 7 GO 8 9 CREATE INDEX ix_number_name ON tbindex(numbers,name) 10 GO 11 CREATE INDEX ix_name ON tbindex(numbers) INCLUDE (name) 12 GO 13 14 DECLARE @ID INT 15 SET @ID=1 16 WHILE @ID<=5 17 BEGIN 18 INSERT INTO tbindex(name,type,numbers) 19 SELECT 20 name, 21 type, 22 object_id+@id 23 FROM sys.objects 24 25 SET @ID=@ID+1 26 END
2.2 分析索引行
--查看该表格索引的id情况 SELECT * FROM sys.indexes WHERE object_id=object_id(\'tbindex\') --PK__tbindex__3213E83F89582AC3 1 --ix_number_name 2 --ix_number 3 DBCC traceon(3604) DBCC ind(\'dbpage\',\'tbindex\',-1) DBCC PAGE(\'dbpage\',1,395,3) DBCC PAGE(\'dbpage\',1,396,3) DBCC PAGE(\'dbpage\',1,397,3) DBCC PAGE(\'dbpage\',1,398,3)
- 复合索引 IX_number_name的索引节点为pageid=395,再挑选一个叶子结点来分析 pageid=396;
- 包含索引 IX_number 的索引节点为 pageid=397,再挑选一个叶子节点来分析 pageid=398。
3 对查询的影响
3.1 复合索引查询注意事项
1 create table tb_composite( 2 id int identity(1,1) not null primary key, 3 name varchar(50) not null, 4 userid int not null, 5 timepoint datetime not null 6 ) 7 GO 8 9 create index ix_userid_name on tb_composite(userid,name) 10 GO 11 12 create index ix_userid on tb_composite(userid) 13 GO 14 15 INSERT INTO tb_composite(name,userid,timepoint) 16 SELECT 17 newid(),orderid%10000 ,CreatedDate 18 FROM ORDERS
大数据表格
1 --查看表格的数据大小跟非聚集索引大小 2 WITH DATA AS ( 3 SELECT 4 5 O.name tb_name, 6 reservedpages = SUM (reserved_page_count), 7 usedpages = SUM (used_page_count), 8 pages = SUM (CASE WHEN (index_id < 2) THEN (in_row_data_page_count + lob_used_page_count + row_overflow_used_page_count) ELSE 0 END ), 9 rowCounts = SUM (CASE WHEN (index_id < 2) THEN row_count ELSE 0 END ) 10 FROM sys.dm_db_partition_stats S 11 JOIN sys.objects o on s.object_id=o.object_id 12 WHERE O.type=\'U\' 13 GROUP BY O.name 14 ) 15 SELECT 16 17 tb_name, 18 rowCounts, 19 reservedpages*8/1024 reserved_Mb, 20 pages*8/1024 data_Mb, 21 index_Mb=(usedpages-pages)*8/1024, 22 unused_Mb=case when usedpages>reservedpages then 0 else (reservedpages-usedpages)*8/1024 end 23 FROM DATA 24 WHERE tb_name = \'tb_composite\' 25 ORDER BY reserved_Mb DESC 26 Go
- 最左匹配原则:复合索引 键值列假设为(a, b, c, d, e),则等同于索引这几个索引:(a)、(a, b)、(a, b, c)、(a, b, c, d)、(a, b, c, d, e)
- 当where条件 符合 最左匹配原则,那么,执行计划则是 INDEX SEEK ,走索引查找;
- 当where条件 不符合 最左匹配原则,则根据性能评估,走primary index scan 或者 非聚集索引扫描再根据键值去 primary key lookup ;
- 根据最左匹配原则,可以在日常管理中,避免添加一些冗余冗余索引
- 但是也有一个注意事项:随着复合索引的列增加,索引页也会增加,使用其索引会增加一定量的IO,所以,再判断冗余索引的时候,需要考虑下这种情况,通常很少碰到这种情形。
3.2 复合索引与包含索引的查询区别
- 如果where 条件包含include列
- include列无法参与 index seek,因为其索引子节点不存在,只存在于索引叶子节点,所以include列一般都是 展示列;
- include列由于无法做 where 过滤的 index seed,同比 复合索引,IO相对会较大
- 如果展示列仅限于索引键值及include列
- 包含索引中,根据索引键值找到 索引叶子节点后,无须根据主键值或者RID值 回表 去查询行记录,而是直接把 索引叶子节点的 include 列的内容展示即可,减少 回表 的IO;
- 如果where条件仅含键值列,select 展示列仅含 键值列级include列
- 两者性能基本一致,包含索引相对少IO,但是区别不大。
- 所有非聚集索引的限制长度是900个字节,但是 包含索引中的 include列是不计算在索引长度中的,所以如果要是遇到这种索引超过 900 bytes的特殊情况,可以考虑把相关字段放到include中来处理。
以上是关于SQL SERVER大话存储结构_复合索引与包含索引的主要内容,如果未能解决你的问题,请参考以下文章