如果我有一个带有IDENTITY
列 ( bigint
) 的非常大的表,并且该表可能会被删除,地址空间(可用 ID)的碎片是否会导致速度变慢SELECTS
?
澄清:
地址空间碎片是指在 ID 列中的值中留下的空白,而不是从表中删除行时发生的磁盘碎片。
如果我有一个带有IDENTITY
列 ( bigint
) 的非常大的表,并且该表可能会被删除,地址空间(可用 ID)的碎片是否会导致速度变慢SELECTS
?
澄清:
地址空间碎片是指在 ID 列中的值中留下的空白,而不是从表中删除行时发生的磁盘碎片。
显然,如果不运行测试,就无法确定这一点。但是,我推测如果它是连续的或分散的,它不会运行得更快或更慢。
假设您的列已编入索引 - SQL Server 将索引存储在 b 树中。这棵树的节点被设计为系统寻呼系统的最佳大小。无论索引的碎片如何,节点内的搜索都将识别正确的子节点页面。由于加载页面所需的时间将超过在节点内搜索所需的时间,我认为碎片不会对查找时间产生任何影响。
另一方面,如果列没有被索引,那么 SQL Server 无论如何都必须进行全表扫描,因此值的分布根本不会影响时间。
它可能产生影响的一个地方是查询计划优化。SQL Server 存储列内容的直方图,以便它可以选择能够提供足够性能的查询计划。在我看来,碎片化可能会导致它选择一个不如它可能考虑过的另一个计划的计划。如果列统计信息不是最新的,就会出现这种情况。如果统计信息是最新的,那么将检测到碎片,优化器可以考虑该信息。
这取决于表的索引方式。假设您还在列上放置聚集索引,则使用该列的任何选择语句都应该非常快。在极端情况下,如果您正在执行范围扫描,可能需要将一些额外的页面拉入内存,但在 ID 上执行此类操作非常罕见。通常你会通过搜索获得这些行。
您仍然应该有一个清理任何碎片的维护计划,尤其是在您进行大量删除的情况下。我不得不承认这不是我的强项,所以我不知道 SQL 2008 和/或您的存储介质是否可能使这变得不必要。
不。
如果它不是索引列,那么碎片肯定无关紧要,因为无论如何引擎都会进行表扫描。(根据实际查询/连接,引擎不一定在做表扫描,但从列本身的角度来看,除了表扫描之外,引擎没有其他更好的工作)
如果是索引列,则索引存储在树结构中,在数据插入或删除过程中会扩展或收缩。对于这种树结构,您需要了解的一件事是,即使您按顺序插入数据,它也是“碎片化的”。这里的碎片不是磁盘分配单元意义上的,而是树中的每个节点都没有完全用于它所覆盖的数据范围。预期的碎片是为了避免过于频繁的树重组。引擎在重构索引树时使用占用率(可以在创建索引时指定)。所以,不管 id 是否连续,它都存储在更大的存储空间中,其中包含一些“间隙”。删除该列不应对性能造成任何明显差异。
但是,数据库也是按页分配存储空间的,这意味着会有碎片和相关的性能问题。但是对于您的问题,这与 id 列上的删除无关。