关于MySQL索引,我有几个相关的问题:
我的应用程序中有很多插入,我担心MySQL在每次插入之后都会重新构建索引。数据不必是实时的,所以我可以在特定数量的插入之后更新索引(如果可能的话)。
发布于 2014-05-02 19:41:38
MySQL可能已经在做您所描述的事情了,尽可能多。
对于InnoDB (应该是默认的MySQL存储引擎),立即插入和更新并删除更改主键或唯一键索引。但是,他们从不重建整个索引,而是向这些索引中添加新值(或从这些索引中提取值)。
对于非唯一索引,InnoDB执行变化缓冲。也就是说,它将对更改进行排队,这些更改将合并到后面的后台索引中。它甚至将合并更改,以便更有效地对索引进行物理更新。
您不需要做任何事情来启用这个特性,因为默认情况下它是启用的。MySQL 5.1只为INSERT
更改缓冲。此外,MySQL 5.5和更高版本还会更改UPDATE
和DELETE
的缓冲。
如果需要,可以禁用此功能(例如,如果使用SSD,避免随机I/O并不那么重要,您可能希望确保队列中的更改不会累积)。通常,您应该保持启用该功能。
发布于 2014-05-02 19:22:48
MySQL不会在每次插入后“重建”索引。MySQL将一行或多行插入到现有索引中。
MySQL有很多不寻常的选择,我不知道所有的选择。如果有这样一种选择,我会感到惊讶:“哦,让表上的指数与表中的数据不同步。”听起来不合理。
如果您有很多插入,最好的策略是在一个语句中执行插入。而不是:
insert into t(...)
select . . .
from t2
where id = id1;
做:
insert into t(...)
select . . .
from t2
where id in (id1, id2, . . .)
它的一个扩展是插入到临时表中。然后立即将临时表加载到大表中:
insert into t(...)
select ...
from temptable;
最后,有时会更快地删除索引,执行大插入(在一个或多个步骤中),然后重新创建索引。
注意:如果删除唯一索引,也会删除唯一约束。如果您使用的是on duplicate key update
,这一点很重要,因为它需要一个辅助索引来查找重复的键(主键除外)。
发布于 2014-05-02 20:50:08
当MySQL由于插入而更新索引时,它是否重新生成整个索引?
不,MySQL不会“重建”每次插入的索引。
MySQL的默认页面大小是16K。它以1MB的增量(称为区段)分配这些页面。
当第一次创建一个表(重新生成索引)时,页面将被填满15/16,为一些随机插入留下空间。如果索引条目每个为500个字节(主键大小+聚集索引的行数据),则在必须拆分页之前为插入两个新行留出空间。
当MySQL需要在整个页面上插入一行时,页面必须被分割。MySQL将添加一个新页面,并将一半的页面数据移动到新页面。
在一个页面中,记录可能实际上并不是按物理顺序排列的。它们会按插入顺序排列。它们是通过一种链接列表的形式按顺序链接的。因此,即使是随机插入也不会导致数据被物理地重新排序。在需要拆分页面的情况下,数据不会被移动。
5月份随机插入后,您的页面将从1/2满到满。
所有这些工作都会影响插入性能,因为索引必须与每个插入一起更新。此外,包含半整页的索引会对阅读性能产生负面影响。
现在,如果您按索引顺序插入行,那么MySQL只需将行添加到页面的末尾,将它们填满15/16,并在页面时添加一个区段。更不用说性能损失了,因为没有分页,因此不涉及数据的移动,更不用说几乎整页的读取性能好处了。
因此,虽然在更新插入索引时需要进行一些维护,但MySQL并不是在“重建”每个插入的索引。另外,请看比尔·卡温的关于更改缓冲的注意事项,这可能会影响到你。
https://stackoverflow.com/questions/23435361
复制相似问题