我正在阅读Effective Mysql - Optimizing Mysql Statements
,在chapter 3
中有这样的解释:
InnoDB中的二级索引使用B树数据结构;但是,它们不同于MyISAM的实现。 在InnoDB中,辅助索引存储主键的物理值。在MyISAM中,辅助索引存储指向包含主键值的数据的指针。
这很重要,原因有两个。首先,当定义了较大的主键时,例如,当您在InnoDB中的主键长度为40个字节时,InnoDB中的二级索引的大小可能会更大。随着二级索引数量的增加,索引的比较大小可能变得很重要。第二个区别是辅助索引现在包含主键值,并且 不需要作为索引的一部分。 这可以通过表连接和覆盖显着提高性能索引。
我想到了很多问题,主要是由于对作者试图传达的内容缺乏了解。
目前尚不清楚作者在 第二段。不再需要什么 作为索引的一部分 ?
InnoDB二级索引B树仅存储PK值还是PK值 和指针吗?还是PK值和指向数据行的指针?
由于存储方法(第二个问题的答案)会带来什么样的性能提升?
This问题包含一个示例以及一个答案。他解释了它如何包含PK值,但是我仍然不了解的是,
要完成连接,如果指针不在二级索引中,而只有该值,MySQL不会使用二级索引中的值对主键索引进行全索引扫描吗?这比拥有指针还有效吗?
答案 0 :(得分:2)
基础。
MyISAM的主键和辅助键的工作方式相同。 -两者都是.MYI
文件中的BTree,叶节点中的“指针”指向.MYD
文件。
“指针”可以是.MYD
文件的字节偏移量,也可以是记录编号(对于FIXED
)。两者都会导致对.MYD
文件的“搜索”。
InnoDB的数据(包括PRIMARY KEY
的列)存储在PK排序的一个BTree中。
这使PK查找略快一些。两者都钻取了一个BTree,但是MyISAM需要额外的搜索。
每个InnoDB次要密钥存储在单独的BTree中。但是在这种情况下,叶节点包含PK的任何其他列。因此,辅助键查找首先根据辅助键深入该BTree。在那里将找到辅助键和主键的所有列。 如果这些都是您需要的所有列,则这是查询的“覆盖索引”,无需进一步操作。 (比MyISAM快。)
但是通常您需要一些其他列,因此PK的列用于向下钻取数据/ PK BTree来查找行中的其余列。 (比MyISAM慢。)
因此,在某些情况下,MyISAM的工作量较少。在某些情况下,InnoDB的工作量较少。还有很多其他事情正在发生。 InnoDB在MyISAM上赢得了许多比较基准。
正在缓存...
MyISAM控制key_buffer中1KB索引块的缓存。数据块由操作系统缓存。
InnoDB在buffer_pool中同时缓存数据索引块和辅助索引块(两种情况下均为16KB)。
“缓存”是指根据需要用大致“最近最少使用”的算法来交换块。
没有BTree加载到RAM中。没有BTree被明确地保存在RAM中。每个块都根据需要进行请求,并且希望将该块缓存在RAM中。对于小于关联缓冲区(key_buffer / buffer_pool)的数据和/或索引,BTree 可能会发生停留在RAM中直到关机。
真相源在磁盘上。 (好的,在将块刷新到磁盘之前发生崩溃时,InnoDB会使用复杂的技巧来避免日志数据丢失。当崩溃后重新启动时,清理会自动发生。)
拔插头。
MyISAM:
混乱#1:索引将处于不干净的状态。需要CHECK TABLE
和REPAIR TABLE
。
混乱#2:如果您在一个语句中位于UPDATEing
的一千行中间,则某些将被更新,而某些则不会。
InnoDB:
如上所述,InnoDB即使在拔插头的情况下,也会执行原子的功能。没有索引被遗忘。 UPDATE
的所有内容都未完成。将会是ROLLBACKed
。
示例。
给予
columns a,b,c,d,e,f,g
PRIMARY KEY(a,b,c)
INDEX(c,d)
BTree叶子节点将包含:
MyISAM:
PK:a,b,c,pointer
中学:c,d,pointer
InnoDB:
PK:a,b,c,d,e,f,g
(整行与PK一起存储)
中学:c,d,a,b
答案 1 :(得分:1)
二级索引是访问数据的间接方式。与主(聚集)索引不同,在InnoDB中遍历辅助索引并到达叶节点时,您会找到查询要查找的对应行的主键 value 。使用此值可以遍历主索引以获取行。这意味着在InnoDB中 2个索引查找。
对于MyISAM,因为辅助节点的叶子是指向实际行的指针,所以只需要1次索引查找。
二级索引是基于表的某些非PK属性形成的。因此,根据定义,PK不必成为索引的一部分。无论是(InnoDB)还是(MyISAM)都是具有相应性能影响的实现细节。
现在,与MyISAM(2次查询vs 1次查询)相比,InnoDB最初采用的方法似乎效率低下,但这不是因为主索引保留在内存中所以代价很低。
但是优点是InnoDB可以拆分和移动行以优化行的插入/更新/删除中的表布局,而无需在二级索引上进行任何更新,因为它不会直接引用受影响的行