• (转)Sql Server之旅——第八站 复合索引和include索引到底有多大区别?


    索引和锁,这两个主题对我们开发工程师来说,非常的重要。。。只有理解了这两个主题,我们才能写出高质量的sql语句,在之前的博客中,我所说的

    索引都是单列索引。。。当然数据库不可能只认单列索引,还有我这篇的复合索引,说到复合索引,可能熟悉的人又会说到include索引,那这两个索引到底

    有什么区别呢,当然我也是菜鸟一枚。。。所以下面的也是我的个人见解。。。

    一:从数据页角度看问题

    1. 做两个表,插入两条数据,在test1上做复合索引,在test2上做include索引,如下图:

    复制代码
     1 -- 在test1表中插入2条记录
     2 CREATE TABLE test1(ID int,Name CHAR(5),Email CHAR(10))
     3 INSERT INTO test1 VALUES(1,'aaaaa','111@qq.com')
     4 INSERT INTO test1 VALUES(2,'bbbbb','222@qq.com')
     5 CREATE INDEX idx_test1 ON dbo.test1(Name,Email)
     6 
     7 -- 在test2表中插入2条记录
     8 CREATE TABLE test2(ID int,Name CHAR(5),Email CHAR(10))
     9 INSERT INTO test2 VALUES(1,'aaaaa','111@qq.com')
    10 INSERT INTO test2 VALUES(2,'bbbbb','222@qq.com')
    11 CREATE INDEX idx_test2 ON dbo.test2(Name) INCLUDE(Email)
    复制代码

    2. 然后通过DBCC 命令查看数据页记录

    <1> 先来看看test1表中各个槽位的信息

    1 DBCC TRACEON(2588,3604)
    2 DBCC IND(Ctrip,test1,-1)
    3 DBCC PAGE(Ctrip,1,194,1) 
    复制代码
     1 Slot 0, Offset 0x60, Length 27, DumpStyle BYTE
     2 
     3 Record Type = INDEX_RECORD           Record Attributes =  NULL_BITMAP     Record Size = 27
     4 
     5 Memory Dump @0x000000000FB0A060
     6 
     7 0000000000000000:   16616161 61613131 31407171 2e636f6d †.aaaaa111@qq.com 
     8 0000000000000010:   c0000000 01000000 030000†††††††††††††...........      
     9 
    10 Slot 1, Offset 0x7b, Length 27, DumpStyle BYTE
    11 
    12 Record Type = INDEX_RECORD           Record Attributes =  NULL_BITMAP     Record Size = 27
    13 
    14 Memory Dump @0x000000000FB0A07B
    15 
    16 0000000000000000:   16626262 62623232 32407171 2e636f6d †.bbbbb222@qq.com 
    17 0000000000000010:   c0000000 01000100 030000†††††††††††††...........      
    18 
    19 OFFSET TABLE:
    20 
    21 Row - Offset                         
    22 1 (0x1) - 123 (0x7b)                 
    23 0 (0x0) - 96 (0x60)            
    复制代码

    <2> 再来看看test2表中各个槽位信息

    1 DBCC TRACEON(2588,3604)
    2 DBCC IND(Ctrip,test2,-1)
    3 DBCC PAGE(Ctrip,1,207,1)
    复制代码
     1 Slot 0, Offset 0x60, Length 27, DumpStyle BYTE
     2 
     3 Record Type = INDEX_RECORD           Record Attributes =  NULL_BITMAP     Record Size = 27
     4 
     5 Memory Dump @0x000000000DFCA060
     6 
     7 0000000000000000:   16616161 6161c400 00000100 00003131 †.aaaaa........11 
     8 0000000000000010:   31407171 2e636f6d 030000†††††††††††††1@qq.com...      
     9 
    10 Slot 1, Offset 0x7b, Length 27, DumpStyle BYTE
    11 
    12 Record Type = INDEX_RECORD           Record Attributes =  NULL_BITMAP     Record Size = 27
    13 
    14 Memory Dump @0x000000000DFCA07B
    15 
    16 0000000000000000:   16626262 6262c400 00000100 01003232 †.bbbbb........22 
    17 0000000000000010:   32407171 2e636f6d 030000†††††††††††††2@qq.com...      
    18 
    19 OFFSET TABLE:
    20 
    21 Row - Offset                         
    22 1 (0x1) - 123 (0x7b)                 
    23 0 (0x0) - 96 (0x60) 
    复制代码

    <3> 从test1和test2的数据页来看,都是有两个slot槽位,然后我们把test1和test2的slot0槽位拿出来对比下,是不是就知道两者大概有什么区别了。

    test1のslot0 

    1 0000000000000000:   16616161 61613131 31407171 2e636f6d †.aaaaa111@qq.com 
    2 0000000000000010:   c0000000 01000000 030000†††††††††††††...........    

    test2のslot0 

    1 0000000000000000:   16616161 6161c400 00000100 00003131 †.aaaaa........11 
    2 0000000000000010:   31407171 2e636f6d 030000†††††††††††††1@qq.com...     

    下面我仔细解剖下两表中的slot内容:

     16   6161616161   3131314071712e636f6d  c0000000 0100 0000  0300    00

    16:                              这个是索引记录的系统头数据。

    6161616161:               转换成十进制就是9797979797,也就是字符的aaaaa。

    3131314071712e636f6d:  这个我想你也懂,也就是111@qq.com。

    c000000010000000:        因为我们是堆表,所以这个就是表的RowID,转化为十进制就是: 192:1:0。

    0300:                            这个表示表中的记录数,也就是3条记录。

    如果你对上面的讲解明白了,那我们继续看看test2のslot0,如果你仔细的话,你会看到在test2中,111qq.com是在记录的最后。。。那这说明什

    么问题呢???如果你对记录比较熟悉的话,你就知道,其实记录中的变长字段值一般都是放在记录的尾部。。。好处就是可以做到“行溢出”。也就是

    可以超过索引的900长度限制。。。而复合索引却无法做到。。。如果你不信我可以做个例子,将name和email的长度设为定长500。

    而include索引却可以顺利通过。。。。。

    转:一线码农    Sql Server之旅——第八站 复合索引和include索引到底有多大区别?

  • 相关阅读:
    js jquery 获取服务器控件的三种方法
    jquery.autocomplete.js用法及示例,小白进
    devexpress 经验笔记
    Powerdesigner逆向工程从sql server数据库生成pdm (转载)
    SQLServer的数据类型
    显示隐藏磁盘,显示联想一键恢复的隐藏磁盘分区
    做mapx、ArcEngine的二次开发出现“没有注册类别 (异常来自 HRESULT:0x80040154 (REGDB_E_CLASSNOTREG)”
    我们无法创建新的分区 也找不到现有的分
    Windows无法安装到GPT分区形式磁盘,怎么办?
    oracle 空间数据库说明
  • 原文地址:https://www.cnblogs.com/wangfuyou/p/5662463.html
Copyright © 2020-2023  润新知