官方其实对这个问题有过详细的解答,可以看这里的链接:https://bugs.mysql.com/bug.php?id=68546
总结下来主要是下面两点:
-
因为在MySQL语义中,
NULL != NULL
为false, 所以,唯一二级索引可以为NULL,也就导致这种情况下可能会出现重复值,比如:CREATE TABLE t1 (a INT, b INT, c INT, d INT, PRIMARY KEY(a,b,c), UNIQUE KEY (a,d)) ENGINE=InnoDB; INSERT INTO t1 VALUES(1,1,1,NULL),(1,1,2,NULL),...,(1,1,99999,NULL);
是合法的,
PRIMARY KEY
是不允许为NULL的。这个时候,假设
btr_pcur_t::m_old_rec
指向(1,NULL,1,330)
,btr_pcur_restore_position
函数就可以简单的解引用该节点,直接定位到所需的页面上, 但是,如果二级索引的叶子节点只存储(a,d,page_no)
,那么,就需要扫描所有的叶子节点挨个去查找目标page(因为有很多重复的),这样子性能会非常低下。 -
那么,是不是意味着这种优化就适用于唯一非
NULL
二级索引呢?其实也不是的,在MySQL
中,支持MVCC
的方式是通过undo来实现的,这个时候,如果有个事务update/delete
了某一个tuple,由于MySQL是实现的delete-marker
,后续由purge进行真正的删除动作,在二级索引(1,1,page_no)
里,将会存储着多个page_no
,btr_pcur_restore_position
就得挨个进行遍历,性能同样也是非常低下的。