据我所知,当记录是连续的时,InnoDB主键索引的性能要远远高于随机记录时的性能。
但是,我对InnoDB主索引对于几乎是连续的值的性能感到好奇。假设我没有使用auto_increment
,而是使用一些存储为二进制(16)的应用程序端顺序UUID方案,如this excellent article中所述。
如果记录几乎是连续的,但不是完全连续的,这对存储和查询性能意味着什么?
最佳答案
“计算磁盘命中数”。
案例1:所有数据和索引都符合innodb_buffer_pool_size
。
行和/或索引的顺序无关紧要。(没有磁盘命中,除非最后将所有内容持久化到磁盘。)
案例2:数据和/或索引太大,无法放入缓冲池。
案例2a:数据/索引是连续的,或者几乎是连续的,或者具有有限数量的“热点”。
将有一个或一个“数量有限”的块获得所有活动。这些(可能)很容易放在缓冲池中。所以,没有性能问题。
案例2b:数据/索引是随机的(例如,UUID或MD5)。
现在,由于数据/索引太大,无法容纳,而且插入是随机跳转的,将有很多I/O来完成这项工作。I/O是性能杀手。(由于包含“next”UUID的块不太可能缓存在缓冲池中,因此需要对其进行读取、修改并最终写入磁盘。)
数据(InnoDB中)按一个BTree中的PRIMARY KEY
排序。每个“secondary”索引都在自己的BTree中。
现在让我们用另一种方式来解决这个问题。。。
案例1。你只有一个主键,没有副键。
如果在加载之前很容易按PK对数据进行排序,这将使加载运行得更快。(填充一个块,写入磁盘;重复。无法获得更少的磁盘命中率。)
案例2。您有一个AUTO_INCREMENT
主键,外加一个辅助键。
在这种情况下,如果按次键预排序并让AUTO_INCREMENT
执行它的操作,它将运行得很快。
案例3:如果您有两个具有不同特征的键(PK和/或secondary),比如时间戳和UUID,那么
你卡住了。您可以尝试按一个进行预排序以优化它,但另一个将是随机和缓慢的。(一个索引效率高,另一个索引效率低。)
回到你的问题上来。”“几乎是连续的”可能意味着你没有碰到很多不同的障碍。例如,如果你有一年的数据,而PK是一个时间戳,但是每天的数据是混乱的,那么这就是“几乎排序”。在任何时候,你都是一天的时间,而不是一年的时间。
关于mysql - MySQL中“几乎顺序的”主键的性能(InnoDB索引),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35646261/