【问题标题】:do indexes on boolean columns help page caching布尔列上的索引是否有助于页面缓存
【发布时间】:2013-07-19 09:41:27
【问题描述】:

我已经阅读了有关布尔列如何不能用作搜索索引的信息。 但我的问题是.. 如果聚集索引会影响记录的物理排列 难道它不能用来将一种记录放在一起(在同一页面中),这样这些页面被加载到内存中的机会就会减少.. 我会尝试更好地解释:为了桌子

[BookPages]
ID(int)
Deleted(Boolean)
Text(Varchar)

如果聚集索引位于ID 列上,则示例数据为

1, true,  'the quick..'
2, false, 'hello w..'
3, true,  'stack m..'
4, false, 'just thin...'

这意味着删除/活动记录是交错的,所以如果我们搜索记录 2

SELECT [Text] FROM [BookPages] WHERE [Deleted] = false AND [ID] = 2

“叶子”数据页可能以行 (1,2) 结尾,这意味着我们正在将带有已删除字段的记录加载到内存中,我们永远不会对此感兴趣。 但如果索引在 Deleted,ID 列中,则数据现在将是

2, false, 'hello w..'
4, false, 'just thin...'
1, true,  'the quick..'
3, true,  'stack m..'

现在,当我们在 SQL 加载页面时仅针对活动记录时,我们将拥有充满活动记录的页面。..

因此,在历史悠久且删除记录较多的数据库上,我们可以在所需记录上获得更好的局部性,并帮助 IO..

在数千个页面上,我们可以确保其中很大一部分永远不会加载到内存中,并且这些数据将始终只保留在磁盘上。

这个推理正确吗?这会影响(提高)大型数据库的整体性能吗?

【问题讨论】:

  • 如果您正在执行大量删除,您可能需要考虑将已删除的记录移动到存档表中。根据删除的频率和性能,您可能希望使用触发器实时执行存档,或者如果性能是一个问题,您可以按计划(可能每周或每月)运行存档,然后重新组织聚集索引以释放空间。

标签: sql performance boolean paging indexing


【解决方案1】:

是的,这个推理是正确的。实际上,您可以将数据集划分为两个区域,一个热区域和一个冷区域。使用位只是这种技术的一个特例。您还可以使用日期列并在其上进行聚类(当然,这是否可行取决于架构和数据)。

分区也有类似的效果。选择聚类键的重量更轻,但同样好。

通常,自动递增数字上的聚类也具有良好的局部性,因为 IDENTITY 值与年龄相关,而年龄与使用频率相关。

同样的优化不适用于非聚集索引。您也可以为它们使用布尔前缀,但您需要以可搜索的形式提供它:

WHERE SomeNCIndexCol = '1234' AND Deleted IN (0, 1)

SQL Server 不够聪明,无法自行解决这个问题。它不能像 Oracle 那样“跳过”第一个索引级别。所以我们必须手动提供搜索键。 (连接项:https://connect.microsoft.com/SQLServer/feedback/details/695044

另一个问题是写入性能。将行标记为已删除 (SET Deleted = 1) 现在需要 CI 的物理删除+插入对加上每个 NCI 的一对。大多数 ORM 不支持主键更改,因此您可能不应该将此集群键设置为主键。

附带说明,在位列上创建索引也有其他用例。如果 99% 的值为零或一,您绝对可以使用索引来执行查找和键查找。您也可以使用这样的索引进行计数(或在位列上分组)。

【讨论】:

  • 写入性能是个问题,索引维护也是个问题。当您删除行时,您的索引会变得支离破碎。
【解决方案2】:

在具有两个或几个可能值的列上创建索引实际上会适得其反。对布尔列进行聚类也可能不明智,因为您可能希望将其保存到经常查询的其他列。例如,客户名称。如果您的数据库服务器支持碎片,您可以在一个单独的表中逻辑地放置在您的 Deleted 列中具有 false 值的最少访问行。请参阅我的以下相关question/answers

【讨论】:

    猜你喜欢
    • 2015-12-22
    • 2010-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-21
    • 2010-09-19
    相关资源
    最近更新 更多