如何在InnoDB中为其索引实现B +树处理重复键。
例如,如果有一个包含100万行的表,其中一列的基数为10.如果我们在此列上创建索引,生成的B +树将如何显示?
它只有10个密钥,每个密钥的值是属于该密钥的主键列表(如果是,在什么结构中?链接列表?)或者它是否有1M密钥(如果是,那么B +树必须以不同的方式处理)?
答案 0 :(得分:2)
从某种意义上说,InnoDB BTree没有重复。这是因为PRIMARY KEY
的列附加到为辅助键指定的列。这导致了一个完全有序的列表。
当您通过辅助键(或键的初始部分)进行查找时,查询将向下钻取BTree以查找索引中与您给出的内容匹配的第一行,然后向前扫描以获取其他任何内容。要获取其余列,需要PRIMARY KEY
列进行第二次BTree查找。
优化器很少使用带有"低基数的索引"。例如,不应索引yes / no或true / false或male / female列。优化器会发现简单地扫描表而不是在索引和(通过PK列)主BTree之间来回反弹更快。
根据月球的相位,何时使用指数与撑船的截止值约为20%。
答案 1 :(得分:1)
你建议的案例对于B +树来说是不好的。基数为10表示only 10 of the 1 million values are unique。实际上它不仅对B +树不好,一般来说它也是一个糟糕的指标。根据这个指数,你平均会得到一个约的子集。 100,000个值,您必须查看或使用其他值进一步过滤。
关于结果树的结构,这里有一些事情要记住:
- 如果叶节点已满,则插入可能需要拆分
- 有时,叶子节点的拆分需要拆分下一个更高的节点
- 在最坏的情况下,拆分可能会一直级联到根节点
https://www.percona.com/files/presentations/percona-live/london-2011/PLUK2011-b-
- 叶节点链接在一起作为双向链表
- [...]
- 可以扫描整棵树而无需访问更高的节点
https://www.percona.com/files/presentations/percona-live/london-2011/PLUK2011-b-
如果使用或多或少属于同一等价类的键插入大量数据,我会期望一棵树,这对我们来说无济于事。 10个键可能只存在于根节点中,树中更深层的所有数据都只是未排序的(因为没有任何东西可以对它进行排序)。
由于叶子是双链表,你基本上留下了我在开头写的东西:你必须遍历一大部分值。关于给定的索引,这必须是预期的,并且B +树可能在这种情况下表现良好(列表可以通过所有数据)。
实际上这更深入了一个抽象:叶子是双重链接的,但每个叶子中有多个值(数据或链接到PK)。然而,这些也列在一个列表中,所以如果你只是遍历一切,那就不会产生太大的影响。
请注意,您还可以调查MySQL正在构建的内容。有一些工具可以检查构建的索引数据结构,例如参见
答案 2 :(得分:1)
InnoDB将表存储在B +树索引中,称为内部PRIMARY。索引的关键是您的主键字段。
如果您定义了二级索引,则会有其他B +树索引(在.ibd或ibdata1中),其中键是辅助索引字段,值是主键。
B +树本身并不要求密钥是唯一的。 PRIMARY和所有UNIQUE索引的唯一性在服务器级别强制执行。
这里有一些关于InnoDB如何组织索引并使用它们来访问数据的幻灯片。 http://www.slideshare.net/akuzminsky/efficient-indexes-in-mysql#downloads-panel