17 index sql-server sql-server-2012
目前,我们有一个功能齐全的现有数据库和应用程序。我目前没有能力更改架构。今天,数据库中的每个表都有一个“IsDeleted”NOT NULL BIT 字段,默认值为“0”。当应用程序“删除”数据时,它只是将 IsDeleted 标志更新为 1。
我无法理解的是每个表上的索引应该如何构建。现在,每个查询/加入/等总是实现 IsDeleted 检查。这是我们的开发人员必须遵循的标准。话虽如此,我正在尝试确定是否需要更改每个表上的所有聚集主键索引以包含主键和 IsDeleted BIT 字段。此外,由于每个查询/加入/等。必须实施 IsDeleted 检查,是否适当假设每个索引(非聚集索引)都应包含 IsDeleted 字段作为索引的第一个字段?
我的另一个问题是关于过滤索引。我知道我可以在索引上放置过滤器,例如“WHERE IsDeleted = 0”以减少索引的大小。但是,由于每个连接/查询都必须实现 IsDeleted 检查,这是否会阻止使用过滤索引(因为在连接/查询中使用了 IsDeleted 列)?
请记住,我无法更改 IsDeleted 方法。
Dav*_*oft 13
这里最简单的方法是单独保留键和聚集索引,并对非聚集索引使用过滤索引。
此外,您可以将一些大表迁移到分区堆或分区聚集列存储 (SQL Server 2016+),而不对主键和唯一索引进行分区。这将使您能够将 IsDeleted 行的非键列推送到单独的数据结构,该数据结构可以另外进行不同的压缩或存储在不同的文件组中。
并确保开发人员使用文字而不是参数来过滤 IsDeleted 行。使用参数 SQL Server 必须对这两种情况使用相同的查询计划。
例如
SELECT ... WHERE ... AND IsDeleted=0
Run Code Online (Sandbox Code Playgroud)
并不是:
SELECT ... WHERE ... AND IsDeleted=@IsDeleted
Run Code Online (Sandbox Code Playgroud)
使用参数将阻止使用过滤索引,并可能让您在参数嗅探方面遇到麻烦。
这可能是一个不受欢迎的意见,但我认为没有“到处都这样做”/一刀切的答案。
如果您的查询无故扫描大量 IsDeleted 行,一种解决方案是创建一个过滤的非聚集索引来满足该查询。
另一种选择是创建一个索引视图,该视图可以被许多不同的查询利用,该视图仅被过滤到未删除的行。这在企业版上可能特别有用,在企业版中,自动索引视图匹配无需提供NOEXPAND提示即可工作。
对于小表或大量读取的表,添加过滤的非聚集索引或视图或任何东西实际上可能只会给数据库增加不必要的开销。