一、索引包含列和书签查找
1、索引包含列
SqlServer2005开始增加的“索引包含列”功能,很实用。
-
比如,在大报表查询数据时,where条件用到索引字段Name2,但是要select的字段是Name1,这时候可以使用“索引包含列”把Name1包含在索引字段Name2中,大大提高查询性能。
-
语法: Create [UNIQUE] Nonclustered/Clustered Index IndexName On dbo.Table1(Name2) Include(Name1);
-
接下来分析为什么索引包含列可以大大提高性能。仍然使用DBCC PAGE命令,查看一个非聚集索引并有包含列的索引数据情况:
由上图可知,包含列Name1也存储在索引数据中。
因此,当数据库用索引字段Name2定位到要查找的某一行时,就可以直接把Name1的值返回了,而不用再根据RID(上图是【HEAP RID(Key)】列)定位到数据页中去取值,即减少了书签查找。
当查询只返回一条数据,只有一次书签查找时当然没什么,如果查询返回的数据很大,每一笔都要去数据页找数据取出来,1000笔就是1000次书签查找,可想而知性能消耗很大,这时候“索引包含列”价值就大大体现出来了。
2、书签查找
-
关于一次书签查找,表有聚集索引(比如Id)时就是类似执行了一次 select Name1 from Table1 where Id=1 ,利用聚集索引键Id查找(查找方式就是索引Id的B树结构查找),而如果表没有聚集索引,则是根据数据行指针(由“文件号2byte:页号4byte:槽号2byte”组成)查找。
聚集索引键和行指针一般统称为RID(Row ID)指针。从这里我们可以想到,如果你的表没有很好的聚集索引字段,建议自增长的Id字段做聚集索引主键(冗余出Id字段也行),它符合自增长、不被更改、唯一性、长度小的特性,是聚集索引的很好选择。 -
自增长Id绝大部分情况下是适用的,特殊的情况看具体需求而定吧。还有自增长Id要考虑一个缺陷,当对表大数据量的并发insert记录时,可以想象每个线程都是要insert到末尾那个页,就会发生竞争和等待。
解决这种情况你可以用uniqueidentifier类型字段(16字节,我是不建议使用)或者哈希分区(就是一个表分成多个表,大数据处理中分库分表是正常的)等。
但是我建议先优化你的insert效率(insert性能本身是很快的),测试每秒并发insert数是否满足生产环境,以保留简单稳定高效的自增长Id作法。
自增长Id不一定就是用数据库提供的自增长,你也可以自己写算法生成一个并发情况下也能唯一的Id(这时候一般长度是bitint,8字节整形),这种情况适合场景是分布式数据库中主从复制时Id栏位是要求一定不能出错的情况(主从复制的一般模式下,主库的Id是按主库增长,从库Id也是按从库自己的增长,如果遇到死锁等原因导致主从复制不同步时,那从库的Id就和主库的Id自增长就对不上号了)。
如果自增长Id是冗余出的主键,那主从库Id对不上号也就无影响。 -
另外,上图最后一列【Row Size】还告诉我们,索引列或索引包含列的size不要太长,否则一页容不了几笔记录,这样大大增加了索引页数量,而且索引数据所占的空间也大大增加了。
3、参考资料
摘自脚本之家:https://www.jb51.net/article/143528.htm
网友评论