当前位置: 首页 > 科技观察

从MySQL优化的角度:数据库回表和索引的概念

时间:2023-03-15 14:01:09 科技观察

回表先下结论,根据以下实验。如果我想得到['liu','25']这条记录。需要什么步骤。1.先通过['liu']记录对应普通索引index(name),得到主键id:4。2.然后通过聚簇索引定位行记录。也就是上面说的['liu','25']记录数据。所以,上述回表查询是先定位主键值,再定位行记录。再扫描一次索引树。当然,它会消耗更多的CPU、IO、内存等。1、stu_info表casecreatetablestu_info(idintprimarykey,namevarchar(20),ageint,index(name))2、查看刚刚创建的表结构mysql>showcreatetablestu_info\G;****************************1\.row**************************表:stu_infoCreateTable:创建表`stu_info`(`id`int(11)NOTNULL,`name`varchar(20)COLLATEutf8_binDEFAULTNULL,`age`int(11)DEFAULTNULL,PRIMARYKEY(`id`),KEY`name`(`name`))ENGINE=InnoDBDEFAULTCHARSET=utf8COLLATE=utf8_bin1rowinset(0.00sec)3.插入测试数据insertintostu_infovalues(1,'zhang',20);insertintostu_infovalues(4,'liu',25);insertintostu_infovalues(7,'huang',19);insertintostu_infovalues(10,'allen',27);insertintostu_infovalues(30,'benjiemin',27);insertintostu_infovalues(16,'roger',27);insertintostu_infovalues(28,'peter',16);commit4。分析过程下面我们来分析一下这几条数据的索引。由于我们的名称列已编入索引。因此名称索引存储会按照[a~z]的顺序排列。通过select语句,可以得到一些感性的认识。如下:mysql>selectnamefromstu_info;+------------+|name|+------------+|allen||benjiemin||huang||liu||peter||roger||zhang|+------------+上述普通索引二级索引的B+树存储格式可能如下:根据旧金山大学提供的可视化B+树效果.它的可视化地址是:https://www.cs.usfca.edu/~galles/visualization/BPlusTree.html如下图:我是根据上图自己画的。如下图所示:也可以看到namedata创建的B+树长什么样子。你也可以看到,如果我需要找到元素[liu],我需要搜索两次。但是,如果我的要求是除了名字之外还要得到年龄。在这里你需要回到桌子上。为什么?因为我找不到年龄数据。普通索引的叶子节点只存储主键。那么聚簇索引聚簇索引是如何保存的呢?继续使用上面的可视化工具,再分析一波。上图是聚簇索引的示意图。转换成我的图片如下:所以name='liu'查询liu的年龄需要回表。先查询普通索引的B+树,再查询聚簇索引的B+树。最后得到liu的行记录。5、执行计划我们也可以通过执行计划来分析,如下:mysql>explainselectid,name,agefromstu_infowherename='liu'\G;*******************************1\.row***************************id:1select_type:SIMPLEtable:stu_infotype:refpossible_keys:namekey:namekey_len:63ref:constrows:1Extra:Usingindexcondition1rowinset(0.00sec)见Usingindexcondition,我们这里使用了返回表。如果不取年龄,只取id和name,那么。无需返回表。下面实验,继续看执行计划:mysql>explainselectid,namefromstu_infowherename='liu'\G;********************************1\.行***************************id:1select_type:SIMPLEtable:stu_infotype:refpossible_keys:namekey:namekey_len:63ref:constrows:1Extra:Usingwhere;使用index1rowinset(0.00sec)然后,如果我们不想返回表或者做更多的IO。我们可以通过构建复合索引来解决这个问题。通过ALTERTABLEstu_infoDROPINDEXname;altertablestu_infoaddkey(name,age);我们继续看执行计划,如下:mysql>explainselectname,agefromstu_infowherename='liu'\G;***************************1\.row***************************id:1select_type:SIMPLEtable:stu_infotype:refpossible_keys:namekey:namekey_len:63ref:constrows:1Extra:Usingwhere;Usingindex1rowinset(0.00sec)可以看到额外的信息是Usingwhere;使用索引而不是使用索引条件将不会用于返回表。