【发布时间】:2017-12-01 00:35:27
【问题描述】:
数据库是否必须在每次插入新行时重建其索引?
从这个角度来说,这是否意味着如果我插入很多内容,索引将不断重建,因此查询效率降低/无用?
我正在尝试了解一些数据库理论,以便更好地设计数据库。
【问题讨论】:
-
在索引中插入一行与重建索引完全不同。
标签: mysql sql indexing database-design
数据库是否必须在每次插入新行时重建其索引?
从这个角度来说,这是否意味着如果我插入很多内容,索引将不断重建,因此查询效率降低/无用?
我正在尝试了解一些数据库理论,以便更好地设计数据库。
【问题讨论】:
标签: mysql sql indexing database-design
是的,插入会影响它们,但并不像您想象的那么糟糕。与关系数据库中的大多数实体一样,索引的创建和维护通常具有额外的空间以适应增长,并且通常设置为在索引空间几乎耗尽时自动增加额外的空间。 p>
重建索引从头开始,与向索引中添加条目不同。插入新行不会导致重建索引。新条目被添加到上面提到的额外空间中,但运行方式略有不同的聚集索引除外。
大多数数据库管理员还会执行一项称为“更新统计信息”的任务,该任务会更新查询规划器使用的一组内部统计信息,以提出良好的查询策略。作为维护的一部分执行的该任务还有助于使查询优化器与索引的当前状态保持“一致”。
有大量关于数据库工作原理的高质量参考资料,包括独立网站和主要数据库出版商的参考资料。从字面上看,您可以通过成为数据库专家来谋生。但是不要太担心您的插入物会造成麻烦。 ;) 如有疑问,请咨询您的 DBA。
这是否有助于解决您的顾虑?
【讨论】:
更新绝对不需要每次更新时都重建整个索引(同样插入和删除)。
更新索引中的条目会产生一些开销,但成本相当低。大多数索引在内部存储为B+Tree data structure。选择这种数据结构是因为它易于修改。
MySQL 还有一个进一步的优化,称为Change Buffer。此缓冲区有助于通过缓存更改来降低更新索引的性能成本。也就是说,您执行了影响索引的 INSERT/UPDATE/DELETE,并且更改的类型记录在 Change Buffer 中。下次您使用查询读取该索引时,MySQL 会读取更改缓冲区作为对完整索引的一种补充。
一个很好的类比可能是定期发布“勘误表”的已发布文档,因此您需要同时阅读文档和勘误表以了解文档的当前状态。
最终,更改缓冲区中的条目逐渐合并到索引中。这类似于在下次重新打印文档时将勘误表编辑到文档中。
更改缓冲区仅用于二级索引。它对主键或唯一键索引没有任何作用。无法推迟对唯一索引的更新,但它们仍然使用 B+Tree,因此成本不会那么高。
如果您进行OPTIMIZE TABLE 或某些类型的ALTER TABLE 更改而无法就地完成,MySQL 会从头开始重建索引。例如,这对于在删除大量表后对索引进行碎片整理很有用。
【讨论】: