文章Slow INSERT into InnoDB table with random PRIMARY KEY column's value描述了如果您使用随机PRIMARY KEY
列,则插入速度会很慢。 MySQL docs说:
如果按顺序(升序或降序)插入索引记录,则生成的索引页大约为15/16。如果以随机顺序插入记录,则页面为1/2至15/16满。
为什么插入会导致大量页面拆分(1/2已满)和随机PRIMARY KEY
列?
非常感谢您的帮助。
答案 0 :(得分:3)
MySQL不会“重建”每个插入的索引。
MySQL的默认页面大小为16K。它以1MB为增量分配这些页面(称为范围)。
首次创建表时(重建索引),页面填满15/16,为一些随机插入(1k的房间)留出空间。如果您的索引条目各为500字节(主键大小+聚簇索引的行数据),则在必须拆分页面之前,需要插入2个新行的空间。
MySQL保留页眉中最高和最低记录的值,因此某个范围内的记录会在同一页上。
当MySQL需要在整页上插入一行时,必须拆分该页面。 MySQL将添加一个新页面,并将一半页面数据移动到新页面。
在页面中,记录实际上可能不是物理顺序。他们将按照他们插入的顺序。它们通过链表的形式按顺序链接。因此,即使是在需要拆分页面之外的随机插入,也不会导致数据被物理移动。
经过多次随机插入后,您的页面将从1/2全部到完整。具有许多半满页的索引将对读取性能产生负面影响(您必须读取两个半满页以读取与一个15/16页整页相同的记录数。)
现在,如果你按索引顺序插入行,那么MySQL只是不断添加到页面的末尾,将它们填满15/16,并在页面时添加一个范围。由于没有页面拆分,因此性能损失要小得多,因此不涉及数据移动,更不用说几乎整页的读取性能优势。
随机插入也会增加页面的碎片,如果您经常读取大量的连续记录(罕见),这可能会影响读取性能。
此外,change buffering可能会对您产生影响。