InnoDB B+ 树索引 - 重复值
InnoDB B+ tree index - duplicate values
在 InnoDB 的 B+ 树索引实现中如何处理重复键。
例如,如果有一个有 100 万行的 table 有一个基数为 10 的列。如果我们在这个列上创建索引,生成的 B+ 树会是什么样子?
它是否只有 10 个键,每个键的值是属于该键的主键列表(如果是,在什么结构中?链表?)或者它是否有 1M 个键(如果是,那么B+树就必须以不同的方式处理)?
索引错误
您提出的案例对于 B+ 树来说是一个糟糕的案例。基数 10 表示 only 10 of the 1 million values are unique。实际上,它不仅对 B+ 树不利,而且通常也是一个不良索引。基于这个索引,你平均会剩下大约的一个子集。 100,000 个值,您必须查看这些值或使用其他值进一步过滤。
B+树属性
关于结果树的结构,这里有一些事情要记住:
- 一个节点不能包含任意多的数据。
- Inserts may require splits if the leaf node is full
- Occasionally the split of a leaf node necessitates split of the next higher node
- In worst case scenarios the split may cascade all the way up to the root node
https://www.percona.com/files/presentations/percona-live/london-2011/PLUK2011-b-
- 叶子被 linked 为双重 linked 列表。
- Leaf nodes are linked together as doubly linked list
- […]
- Entire tree may be scanned without visiting the higher nodes at all
https://www.percona.com/files/presentations/percona-live/london-2011/PLUK2011-b-
预期
如果您插入大量数据,这些数据的键或多或少都属于相同的等价 class,我会期望树,这不会有太大帮助。这 10 个键可能仅存在于根节点中,树中更深的所有数据将只是未排序的(因为没有任何东西可以对其进行排序)。
由于叶子是双重 linked 列表这一事实,您基本上只剩下我在开头写的内容:您必须遍历值的一个大子集。关于给定的索引,这必须是预期的,并且 B+ 树在这种情况下可能表现良好(列表可以只遍历所有数据)。
实际上这更深一层抽象:叶子是双linked,但每个叶子中有多个值(数据或link 到PK)。尽管如此,这些也在一个列表中,所以如果你只是遍历所有内容,它并没有太大的区别。
检查 InnoDB space
请注意,您还可以调查 MySQL 真正在构建什么。有工具可以检查构建的索引数据结构,例如
InnoDB 将 table 存储在内部称为 PRIMARY 的 B+ 树索引中。索引的键就是你的主键字段。
如果你定义了一个二级索引,将会有额外的B+树索引(在.ibd或ibdata1中),其中键是二级索引字段,值是主键。
B+树本身并不要求key是唯一的。 PRIMARY 和所有 UNIQUE 索引的唯一性在服务器级别强制执行。
这里有一些关于 InnoDB 如何组织索引并使用它们访问数据的幻灯片。 http://www.slideshare.net/akuzminsky/efficient-indexes-in-mysql#downloads-panel
从某种意义上说,InnoDB BTree 没有重复项。这是因为 PRIMARY KEY
的列附加到为辅助键指定的列。这导致了一个完全有序的列表。
当您通过辅助键(或键的初始部分)查找时,查询将向下钻取 BTree 以找到索引中与您提供的匹配的第一行,然后向前扫描以获取任何其他行。要获取其余列,需要 PRIMARY KEY
列进行第二次 BTree 查找。
优化器很少会使用 "low cardinality" 的索引。例如,不应为 yes/no 或 true/false 或 male/female 列编制索引。优化器会发现简单地扫描 table 而不是在索引和(通过 PK 列)主 BTree 之间来回跳转更快。
何时使用指数与下注的临界值约为 20%,具体取决于月相。
在 InnoDB 的 B+ 树索引实现中如何处理重复键。
例如,如果有一个有 100 万行的 table 有一个基数为 10 的列。如果我们在这个列上创建索引,生成的 B+ 树会是什么样子?
它是否只有 10 个键,每个键的值是属于该键的主键列表(如果是,在什么结构中?链表?)或者它是否有 1M 个键(如果是,那么B+树就必须以不同的方式处理)?
索引错误
您提出的案例对于 B+ 树来说是一个糟糕的案例。基数 10 表示 only 10 of the 1 million values are unique。实际上,它不仅对 B+ 树不利,而且通常也是一个不良索引。基于这个索引,你平均会剩下大约的一个子集。 100,000 个值,您必须查看这些值或使用其他值进一步过滤。
B+树属性
关于结果树的结构,这里有一些事情要记住:
- 一个节点不能包含任意多的数据。
- Inserts may require splits if the leaf node is full
- Occasionally the split of a leaf node necessitates split of the next higher node
- In worst case scenarios the split may cascade all the way up to the root node
https://www.percona.com/files/presentations/percona-live/london-2011/PLUK2011-b-
- 叶子被 linked 为双重 linked 列表。
- Leaf nodes are linked together as doubly linked list
- […]
- Entire tree may be scanned without visiting the higher nodes at all
https://www.percona.com/files/presentations/percona-live/london-2011/PLUK2011-b-
预期
如果您插入大量数据,这些数据的键或多或少都属于相同的等价 class,我会期望树,这不会有太大帮助。这 10 个键可能仅存在于根节点中,树中更深的所有数据将只是未排序的(因为没有任何东西可以对其进行排序)。
由于叶子是双重 linked 列表这一事实,您基本上只剩下我在开头写的内容:您必须遍历值的一个大子集。关于给定的索引,这必须是预期的,并且 B+ 树在这种情况下可能表现良好(列表可以只遍历所有数据)。
实际上这更深一层抽象:叶子是双linked,但每个叶子中有多个值(数据或link 到PK)。尽管如此,这些也在一个列表中,所以如果你只是遍历所有内容,它并没有太大的区别。
检查 InnoDB space
请注意,您还可以调查 MySQL 真正在构建什么。有工具可以检查构建的索引数据结构,例如
InnoDB 将 table 存储在内部称为 PRIMARY 的 B+ 树索引中。索引的键就是你的主键字段。
如果你定义了一个二级索引,将会有额外的B+树索引(在.ibd或ibdata1中),其中键是二级索引字段,值是主键。
B+树本身并不要求key是唯一的。 PRIMARY 和所有 UNIQUE 索引的唯一性在服务器级别强制执行。
这里有一些关于 InnoDB 如何组织索引并使用它们访问数据的幻灯片。 http://www.slideshare.net/akuzminsky/efficient-indexes-in-mysql#downloads-panel
从某种意义上说,InnoDB BTree 没有重复项。这是因为 PRIMARY KEY
的列附加到为辅助键指定的列。这导致了一个完全有序的列表。
当您通过辅助键(或键的初始部分)查找时,查询将向下钻取 BTree 以找到索引中与您提供的匹配的第一行,然后向前扫描以获取任何其他行。要获取其余列,需要 PRIMARY KEY
列进行第二次 BTree 查找。
优化器很少会使用 "low cardinality" 的索引。例如,不应为 yes/no 或 true/false 或 male/female 列编制索引。优化器会发现简单地扫描 table 而不是在索引和(通过 PK 列)主 BTree 之间来回跳转更快。
何时使用指数与下注的临界值约为 20%,具体取决于月相。