Firebird 不会对记录进行聚类。它旨在避免需要集群的问题和集群索引带来的碎片问题。索引和数据分别存储在不同类型的页面上。每个数据页仅包含一个表中的数据。记录按照它们被插入的顺序存储,给予或接受并发插入,通常在单独的页面上进行。当旧记录被删除时,新记录将被存储在它们的位置,因此新记录有时会与旧记录出现在同一页面上。
许多表使用人工主键,通常是升序,可能是数据库生成的序列或时间戳。这种做法会导致记录按键顺序存储,但这种顺序并不能保证。也不是很有趣。当主键是人工的时,大多数返回相关记录组的查询都是在二级索引上完成的。这对于聚集的记录来说是一个性能损失,因为二级索引上的查找需要遍历两个索引,因为二级索引只提供主索引的键,必须遍历主索引才能找到数据。
在碎片整理和空间使用的更大问题上,Firebird 会跟踪页面上的可用空间,以便将新记录插入到已删除记录的页面上。如果一个页面完全为空,它将被重新分配。这种空间管理是在数据库运行时完成的。如您所知,Firebird 使用多版本并发控制,因此当更新或删除记录时,Firebird 会创建一个新的记录版本,但保留旧版本。当提交更改之前运行的所有事务都结束时,旧的记录版本不再有任何用途,Firebird 将删除它。在许多应用程序中,旧版本会在正常运行数据库的过程中被删除。当交易触及旧版本的记录时,Firebird 检查旧版本的状态,如果没有正在运行的事务可以读取它们,则将其删除。有一个名为“Sweep”的功能可以系统地删除不需要的旧记录版本。Sweep 可以与其他数据库活动同时运行,但最好在数据库负载较低时安排它。所以不,在你运行扫描之前没有任何东西被删除是不正确的。
此致,
安哈里森
谁与 Firebird 及其前辈合作了很长时间
顺便说一句 - 正如第一个回答的人提到的那样,Firebird 确实在页面上留下空间,以便旧版本的记录与新版本保持在同一页面上。它不是固定的空间百分比,而是存储在页面上的每条记录 16 个字节,因此记录非常短的表的页面具有更多可用空间,而具有长记录的表则更少。