使用随机值作为主键时的InnoDB聚集索引性能

时间:2019-06-15 14:42:47

标签: mysql indexing innodb

默认情况下,我的InnoDB存储引擎的主键是自动递增整数。为了隐藏数据库中的行数,应用程序代码为主键实现了一些随机生成器。

这是典型方案的示例:

CREATE TABLE `MUSIC_LINK` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `project_id` int(11) unsigned DEFAULT NULL,
   PRIMARY KEY (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=latin1;

我正在读一本书,才发现InnoDB使用按主键排序的聚簇索引。本质上,这意味着数据库文件中的记录由主键值索引和排序。只要下一条记录的主键始终大于插入的最后一条记录(这是默认情况下,由于自动增量约束),就很好。

当主键不再自动递增时会发生什么?为了使文件按主键排序,每次插入小于最大主键的主键时,都必须进行大量重写。

我是否误解了聚集索引如何在InnoDB中工作?因为这听起来像一个巨大的性能问题。

1 个答案:

答案 0 :(得分:2)

InnoDB:

使用AUTO_INCREMENT PRIMARY KEY,“下一个”行将放置在保存表数据的BTree的“末尾”。这是有效的,并且“最后一个”块将被大量更新。

注意:块保留在buffer_pool中,最终要 写入磁盘。

对于具有“随机” PK(例如GUID,UUID,MD5,SHA1等)的情况,要插入的“下一个”行需要进入保存数据的BTree中的某个“随机”位置。如果buffer_pool足够大,则必要的块仍将位于其中。因此,效率与AI并没有太大差异。

另一方面,如果数据太大而无法容纳到buffer_pool中(或者其他活动不断使这些块溢出),那么插入将需要先获取该块,然后再对其进行修改。

例如,如果表的大小是buffer_pool中可以容纳的大小的20倍,则下一次随机写入将有20的缓存块中有1的机会。也就是说,INSERT有95%的时间必须等待磁盘读取。

但是...您促成对INSERTs的讨论。 SELECTs呢?选择有什么模式(如果有)?如果仍然是“随机”,则PK的类型无关紧要。另一方面,如果选择倾向于到达“最近”项(例如新闻),则AI会赢得大型表,这是因为缓存了所需块的可能性增加了。

集群

评论表示对“集群/ ed / ing”有些困惑。一些定义(在MySQL / MariaDB上下文中):

  • 一组具有相同数据的服务器,可以一起工作。 NDB群集vs Galera群集vs Clustrix(第三方提供)
  • “聚集索引”是将 data 附加到索引的时间。在InnoDB中,PK始终与数据一起聚集。 (注意:MyISAM和其他供应商不一定会这样做。)
  • 当要获取的记录在磁盘上的布局中彼此相邻时(请考虑PK 二级索引),则这些行将“聚集在一起”。值得注意的是,获取一个块会获得所需的几行。

所以,回到评论:

  • PRIMARY KEY中跳来跳去(由于使用了我所谓的随机PK,或者只是由于未按某些相关顺序获取行)而在表中跳来跳去。
  • UUID具有“排序顺序”,但是它对大多数事情都没有用。