By including nonkey columns, you can create nonclustered indexes that cover more queries. This is because the nonkey columns have the following benefits:

They can be data types not allowed as index key columns.
They are not considered by the Database Engine when calculating the number of index key columns or index key size.

在SqlServer 2016中,当咱们要给一个长度超过1700的列创立索引时,数据库会通知咱们为这个列建索引会超过限度,而include的列是不在这个限度外面的。

create table t1(hid int,hname varchar(4000),hname1 varchar(4000))
create index ind_hname on t1(hname) --正告Warning! The maximum key length
for a nonclustered index is 1700 bytes. The index 'ind_hname' has maximum length of
4000 bytes. For some combination of large values, the insert/update operation will fail.
create index ind_hname on t1(hid) include(hname) --不报错,失常创立,索引键列是hid,蕴含列是hname

官网文档的说法:通过蕴含非键列,能够创立笼罩更多查问的非汇集索引。 这是因为非键列具备下列长处:
1、它们能够是不容许作为索引键列的数据类型。
2、在计算索引键列数或索引键大小时,数据库引擎不思考它们。
当查问中的所有列都作为键列或非键列蕴含在索引中时,带有蕴含性非键列的索引能够显著进步查问性能。 这样能够实现性能晋升,因为查问优化器能够在索引中找到所有列值;不拜访表或汇集索引数据,从而缩小磁盘 I/O 操作。

以上2点的集体了解:
1、它们能够是不容许作为索引键列的数据类型。比方varchar(2000)超过1700不能做索引键列,然而varchar(2000)能够作为蕴含列
2、 index key size索引键大小是指索引键蕴含的所有字段的长度总和的限度,比方我有一个表create table table1 (col1 varchar(500), col2 varchar(500),col3 varchar(500), col4 varchar(500));因为indexed key size的限度是1700, 所以create index ind_t1 on table1(col1, col2,col3)没有问题,因为col1+col2+col3=1500<1700,然而create index ind_t2 on table1(col1, col2,col3,col4)有问题,因为col1+col2+col3+col4=2000>1700,然而咱们能够这样create index ind_t3 on table1(col1, col2,col3) include (col4),即把col4放入蕴含列,它就不占索引键ind_t3的大小

联合以上2点的了解,得出结论
1、include蕴含列只能是针对非汇集索引
2、Index space<>indexed key size+include columns www.pizei.comsize, Index space是整个index段的尺寸包含include列,Index space就是整个索引占用的磁盘空间,它包含索引键和非索引键,而不是说非索引键(蕴含列)就不占索引段的磁盘空间
3、当查问中的所有列就蕴含于索引的键值中,那么就不会产生Lookup回表的操作了,因为找到索引项,就曾经找到所需的数据了,没有必要再到数据行去找了,这种状况,叫做索引笼罩
4、索引定义中非键列(蕴含列)的程序不会影响应用该索引的查问的性能。
5、忽然多进去一个查问,而这个查问字段只是比之前的查问多一个字段的状况下,如果之前的查问曾经有了索引,则能够把之前索引删除,新建一个索引,再把新增的查问字段和之前索引中include字段合并起来一并放入include
6、当查问中的所有列都呈现在索引(键列或蕴含列)中时,这种蕴含列的游戏索引能力带来成果,也就是说它惟一的益处就是间接查问索引就能够返回值,不必回表,应用的范畴太窄了。一旦要通过索引再回表返回数据,那蕴含列太得失相当,因为蕴含列也占用理论的存储空间,这样导致这个索引的index space太大了,老本太高了,特地是超大表,索引如果蕴含太多蕴含列的话,占用存储切实太可怕了。所以 include蕴含列是典型的空间换工夫的打法,须要均衡场景应用,而不是说它肯定很好

以下7、8两点论断,额定夹带的私活,帮忙了解索引扫描的原理
7、100GB的表,10个字段,每个字段均匀10GB,每个字段建设一个索引,均匀每个索引10GB,扫描某个索引时,不是间接扫描整个索引这10GB,而是扫描索引树根节点+索引树干节点+索引叶子节点,这样下来找到对应的索引键值,可能只须要扫描不到10MB的索引,如果要回表,那再加上回表的老本
8、大表创立索引,加上online=on不会影响业务,然而会产生微小的事务日志,所以个别留到业务低峰比方周末操作

论断2的例子:
20210526公司产生的遇到的景象,csdb5的磁盘一下子被应用了200GB
如下语句,ATickMinutesArchive表大小254GB总计10个字段,原来的索引180GB,如下索引一创立,发现索引达到了400GB,也就是如下新建索引有200GB,这个索引大小刚好和表大小统一,阐明include的8个字段和索引键的2个字段同时计算了到了索引大小中

CREATE NONCLUSTERED INDEX NIX_ATickMinutesArchive_001
ON [dbo].[ATickMinutesArchive] ([Symbol],[DateUpdate])
INCLUDE ([Last],[High],[Low],[TotalVol],[TimeUpdate],[Ticks],[OpenPrice],[OpenVolume])
WITH ( ONLINE= ON )

论断3的例子1:
例如,taable1表上有col1列(主键),col2列,col3列,col4列,col5列...
当初要求作以下查问 select col2,col3 from taable1 where col2=@col2
一般来说,在col2列上加非汇集索引,就能够减速此查问。其查问步骤:检索col2列上的非汇集索引,获取对应主键col1,再由主键检索汇集索引,从汇集索引的叶级索引页上获取相干的记录。然而,如果在col2列上加非汇集索引时指定include col3列,这样col3列值便会存储在非汇集索引的叶级索引页上。其查问步骤:检索col2列上的非汇集索引,间接从非汇集索引的叶级索引页上获取相干记录。

论断3的例子2:
如遇到如下查问,则最初一个index_5都能够让上面这些所有查问语句只拜访索引就返回数据,也就是说当查问中的所有列都作为键列或非键列蕴含在索引中时,间接查问索引就能够返回后果

select col1,col2 from table1 where col1=XX
select col1,col2,col3 from table1 where col1=XX
select col1,col2,col3,col4 from table1 where col1=XX
select col1,col2,col3,col4,col5 from table1 where col1=XX
select col1,col2,col3,col4,col5,col6 from table1 where col1=XX
CREATE INDEX [index_5] ON [dbo].[table1] ([col1]) INCLUDE ([col2], [col3],
[col4], [col5], [col6]) WITH (DATA_COMPRESSION = PAGE, ONLINE = ON)

论断4的例子:
索引定义中非键列的程序不会影响应用该索引的查问的性能,比方index_5和index_6成果一样, include前面的col2和col5程序能够随便,能够col2在前,也能够col5在前

CREATE INDEX [index_5] ON [dbo].[table1] ([col1]) INCLUDE ([col2], [col3],
[col4], [col5], [col6]) WITH (DATA_COMPRESSION = PAGE, ONLINE = ON)
CREATE INDEX [index_6] ON [dbo].[table1] ([col1]) INCLUDE ([col5], [col3],
[col2], [col4], [col6]) WITH (DATA_COMPRESSION = PAGE, ONLINE = ON)

论断5的例子:
如遇到如下查问,且曾经存在index_4索引,则能够把index_4删除,新建index_5索引,再把新增的查问col6和之前索引中include字段合并起来一并放入include

select col1,col2,col3,col4,col5,col6 from table1 where col1=XX
CREATE INDEX [index_4] ON [dbo].[table1] ([col1]) INCLUDE ([col2],
[col3], [col4], [col5]) WITH (DATA_COMPRESSION = PAGE, ONLINE = ON)
CREATE INDEX [index_5] ON [dbo].[table1] ([col1]) INCLUDE ([col2],
[col3], [col4], [col5], [col6]) WITH (DATA_COMPRESSION = PAGE, ONLINE = ON)