InnoDB 二级索引包括值而不是指向 PK 的指针,这怎么够了?
InnoDB secondary index includes value instead of pointer to PK, how is it enough?
我正在阅读 Effective Mysql - Optimizing Mysql Statements
,在 chapter 3
中有这样的解释:
The secondary indexes in InnoDB use the B-tree data structure; however, they differ from the MyISAM implementation. In InnoDB, the secondary index stores the physical value of the primary key. In MyISAM, the secondary index stores a pointer to the data that contains the primary key value.
This is important for two reasons. First, the size of secondary indexes in InnoDB can be much larger when a large primary key is defined—for example when your primary key in InnoDB is 40 bytes in length. As the number of secondary indexes increase, the comparison size of the indexes can become significant. The second difference is that the secondary index now includes the primary key value and is not required as part of the index. This can be a significant performance improvement with table joins and covering indexes.
有很多问题出现在我的脑海中,主要是因为对作者试图传达的内容缺乏理解。
不清楚作者在第二个区别中的意思
第二段。 不再需要作为索引的一部分?
InnoDB二级索引B树只存PK值还是PK值
和指向它的指针?或 PK 值和指向数据行的指针?
这种存储方式(第2题的答案)会带来什么样的性能提升?
This 问题包含示例和答案。他解释了它是如何包含PK值的,但我仍然不明白的是,
要完成连接,如果二级索引中不存在指针而只有值,不会 MySQL 使用二级索引中的值对主键索引进行全索引扫描吗?这比也有指针更有效率吗?
二级索引是一种间接访问数据的方式。与主(聚集)索引不同,当您遍历 InnoDB 中的二级索引并到达叶节点时,您会找到查询要查找的对应行的主键 value。使用此值遍历主索引以获取行。这意味着 2 InnoDB 中的索引查找 .
对于 MyISAM,因为辅助节点的叶子是指向实际行的指针,所以您只需要 1 次索引查找。
二级索引是根据你table的某些属性形成的,这些属性不是PK。因此,根据定义,PK 不需要成为索引的一部分。无论是 (InnoDB) 还是 (MyISAM) 都是具有相应性能影响的实现细节。
现在 InnoDB 遵循的方法与 MyISAM 相比(2 次查找 vs 1 次查找)乍一看似乎效率低下,但这并不是因为主索引保存在内存中所以惩罚很低。
但优点是 InnoDB 可以拆分和移动行以优化 inserts/updates/deletes 行上的 table 布局,而无需对二级索引进行任何更新,因为它不直接引用受影响的行
基础..
MyISAM 的 PRIMARY KEY 和 secondary keys 是一样的。 -- 两者都是 .MYI
文件中的 BTree,其中叶节点中的 "pointer" 指向 .MYD
文件。
"pointer" 是 .MYD
文件中的字节偏移量,或者是记录号(对于 FIXED
)。两者都会导致 "seek" 进入 .MYD
文件。
InnoDB 的数据,包括 PRIMARY KEY
的列,存储在一个按 PK 排序的 BTree 中。
这使得 PK 查找稍微快一些。两者都向下钻取 BTree,但 MyISAM 需要额外查找。
每个 InnoDB 二级键都存储在一个单独的 BTree 中。但在这种情况下,叶节点包含 PK 的任何额外列。因此,辅助键查找首先会根据辅助键向下钻取 BTree。在那里它将找到辅助键和主键的所有列。 如果 这些都是您需要的列,则这是一个 "covering index" 查询,没有进一步的操作。 (比 MyISAM 快。)
但通常您需要一些其他列,因此 PK 的列用于向下钻取 data/PK BTree 以查找该行中的其余列。 (比 MyISAM 慢。)
因此,在一些 情况下,MyISAM 做的工作较少; 一些 InnoDB 做较少工作的情况。还有很多其他事情正在发生; InnoDB 赢得了许多超过 MyISAM 的比较基准。
正在缓存...
MyISAM 控制 key_buffer 中 1KB 索引块的缓存。数据块由操作系统缓存。
InnoDB 在 buffer_pool.
中缓存数据和二级索引块(两种情况下均为 16KB)
"Caching"指的是根据需要交换in/out块,大致有一个"least recently used"算法。
没有 BTree 加载到 RAM 中。没有 BTree 明确地 保存在 RAM 中。根据需要请求每个块,希望将其缓存在 RAM 中。对于小于关联缓冲区 (key_buffer / buffer_pool) 的数据 and/or 索引,BTree 可能会 保留在 RAM 中直到关闭.
source-of-truth 在磁盘上。 (好吧,InnoDB 在日志文件中使用了一些复杂的技巧来避免在块被刷新到磁盘之前发生崩溃时丢失数据。崩溃后重新启动时会自动进行清理。)
拔插头..
MyISAM:
混乱#1:索引将处于不干净的状态。需要 CHECK TABLE
和 REPAIR TABLE
。
混乱 #2:如果您在一条语句中 UPDATEing
一千行的中间,有些会被更新,有些不会。
InnoDB:
如上所述,InnoDB 以 原子方式 执行操作,甚至在拔掉插头时也是如此。没有索引被破坏。没有UPDATE
剩下half-finished;它将是 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
我正在阅读 Effective Mysql - Optimizing Mysql Statements
,在 chapter 3
中有这样的解释:
The secondary indexes in InnoDB use the B-tree data structure; however, they differ from the MyISAM implementation. In InnoDB, the secondary index stores the physical value of the primary key. In MyISAM, the secondary index stores a pointer to the data that contains the primary key value.
This is important for two reasons. First, the size of secondary indexes in InnoDB can be much larger when a large primary key is defined—for example when your primary key in InnoDB is 40 bytes in length. As the number of secondary indexes increase, the comparison size of the indexes can become significant. The second difference is that the secondary index now includes the primary key value and is not required as part of the index. This can be a significant performance improvement with table joins and covering indexes.
有很多问题出现在我的脑海中,主要是因为对作者试图传达的内容缺乏理解。
不清楚作者在第二个区别中的意思 第二段。 不再需要作为索引的一部分?
InnoDB二级索引B树只存PK值还是PK值 和指向它的指针?或 PK 值和指向数据行的指针?
这种存储方式(第2题的答案)会带来什么样的性能提升?
This 问题包含示例和答案。他解释了它是如何包含PK值的,但我仍然不明白的是,
要完成连接,如果二级索引中不存在指针而只有值,不会 MySQL 使用二级索引中的值对主键索引进行全索引扫描吗?这比也有指针更有效率吗?
二级索引是一种间接访问数据的方式。与主(聚集)索引不同,当您遍历 InnoDB 中的二级索引并到达叶节点时,您会找到查询要查找的对应行的主键 value。使用此值遍历主索引以获取行。这意味着 2 InnoDB 中的索引查找 .
对于 MyISAM,因为辅助节点的叶子是指向实际行的指针,所以您只需要 1 次索引查找。
二级索引是根据你table的某些属性形成的,这些属性不是PK。因此,根据定义,PK 不需要成为索引的一部分。无论是 (InnoDB) 还是 (MyISAM) 都是具有相应性能影响的实现细节。
现在 InnoDB 遵循的方法与 MyISAM 相比(2 次查找 vs 1 次查找)乍一看似乎效率低下,但这并不是因为主索引保存在内存中所以惩罚很低。
但优点是 InnoDB 可以拆分和移动行以优化 inserts/updates/deletes 行上的 table 布局,而无需对二级索引进行任何更新,因为它不直接引用受影响的行
基础..
MyISAM 的 PRIMARY KEY 和 secondary keys 是一样的。 -- 两者都是 .MYI
文件中的 BTree,其中叶节点中的 "pointer" 指向 .MYD
文件。
"pointer" 是 .MYD
文件中的字节偏移量,或者是记录号(对于 FIXED
)。两者都会导致 "seek" 进入 .MYD
文件。
InnoDB 的数据,包括 PRIMARY KEY
的列,存储在一个按 PK 排序的 BTree 中。
这使得 PK 查找稍微快一些。两者都向下钻取 BTree,但 MyISAM 需要额外查找。
每个 InnoDB 二级键都存储在一个单独的 BTree 中。但在这种情况下,叶节点包含 PK 的任何额外列。因此,辅助键查找首先会根据辅助键向下钻取 BTree。在那里它将找到辅助键和主键的所有列。 如果 这些都是您需要的列,则这是一个 "covering index" 查询,没有进一步的操作。 (比 MyISAM 快。)
但通常您需要一些其他列,因此 PK 的列用于向下钻取 data/PK BTree 以查找该行中的其余列。 (比 MyISAM 慢。)
因此,在一些 情况下,MyISAM 做的工作较少; 一些 InnoDB 做较少工作的情况。还有很多其他事情正在发生; InnoDB 赢得了许多超过 MyISAM 的比较基准。
正在缓存...
MyISAM 控制 key_buffer 中 1KB 索引块的缓存。数据块由操作系统缓存。
InnoDB 在 buffer_pool.
中缓存数据和二级索引块(两种情况下均为 16KB)"Caching"指的是根据需要交换in/out块,大致有一个"least recently used"算法。
没有 BTree 加载到 RAM 中。没有 BTree 明确地 保存在 RAM 中。根据需要请求每个块,希望将其缓存在 RAM 中。对于小于关联缓冲区 (key_buffer / buffer_pool) 的数据 and/or 索引,BTree 可能会 保留在 RAM 中直到关闭.
source-of-truth 在磁盘上。 (好吧,InnoDB 在日志文件中使用了一些复杂的技巧来避免在块被刷新到磁盘之前发生崩溃时丢失数据。崩溃后重新启动时会自动进行清理。)
拔插头..
MyISAM:
混乱#1:索引将处于不干净的状态。需要 CHECK TABLE
和 REPAIR TABLE
。
混乱 #2:如果您在一条语句中 UPDATEing
一千行的中间,有些会被更新,有些不会。
InnoDB:
如上所述,InnoDB 以 原子方式 执行操作,甚至在拔掉插头时也是如此。没有索引被破坏。没有UPDATE
剩下half-finished;它将是 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