0

我正在创建一个过滤索引,以便 WHERE 过滤器包含完整的查询条件。有了这样的索引,似乎不需要键列,尽管 SQL 要求我添加一个。例如,考虑下表:

CREATE TABLE Invoice
(
    Id INT NOT NULL IDENTITY PRIMARY KEY,
    Data VARCHAR(MAX) NOT NULL,
    IsProcessed BIT NOT NULL DEFAULT 0,
    IsInvalidated BIT NOT NULL DEFAULT 0
)

表上的查询查找要处理的新发票,即:

SELECT *
FROM Invoice
WHERE IsProcessed = 0 AND IsInvalidated = 0

因此,我可以使用过滤索引调整这些查询:

CREATE INDEX IX_Invoice_IsProcessed_IsInvalidated
ON Invoice (IsProcessed)
WHERE (IsProcessed = 0 AND IsInvalidated = 0)
GO

我的问题:关键列应该IX_Invoice_IsProcessed_IsInvalidated是什么?大概没有使用键列。我的直觉使我选择了一个较小的列,并使索引结构保持相对平坦。我应该选择表主键 ( Id) 吗?过滤器列之一,还是两者都?

4

3 回答 3

1

因为您在该表上有一个聚集索引,所以您在该索引的键列中放入什么并不重要。意思Id是那里是免费的。您唯一能做的就是include索引的包含部分中的所有内容,以便在索引的叶级别实际拥有方便的数据,以排除对表的键查找。或者,如果队列很大,那么在关键部分中,其他一些列可能会很有用。

现在,如果该表没有主键,那么您必须将include连接或其他用途所需的所有列指定或指定为键列。否则,将发生堆上的 RID 查找,因为在索引的叶级别上,您将引用数据页。

于 2014-03-12T17:13:51.060 回答
0

这个过滤索引覆盖了多少百分比的表?如果它很小,您可能希望覆盖整个表以处理索引中的“SELECT *”而不碰到表。如果它是表格的很大一部分,尽管这不是最佳选择。然后我建议使用聚集索引或主键。我必须进行更多研究,因为我现在忘记了哪个是最佳的,但是如果它们相同,则应该设置。

于 2014-03-12T17:13:50.683 回答
0

我建议你声明如下

CREATE INDEX IX_Invoice_IsProcessed_IsInvalidated
ON Invoice (Id)
INCLUDE (Data)
WHERE (IsProcessed = 0 AND IsInvalidated = 0)

INCLUDE 子句意味着数据列的值将作为索引的一部分存储。

如果您没有 INCLUDE 子句,则查询计划

SELECT Id, Data
FROM Invoice
WHERE IsProcessed = 0 AND IsInvalidated = 0

将涉及两步过程

  • 使用索引查找符合条件的主键值列表
  • 从表中获取与那些主键匹配的数据

另一方面,如果索引包含 [Data] 列,那么它将正确覆盖查询,因为无需使用主键查找数据

虽然你不会得到什么

这样做的缺点是您将为这些记录存储两次 varchar(MAX) 数据,因此需要将更多数据写入数据库并且将使用更多存储空间,尽管这不是什么大问题'只是在谈论一小部分数据。

与往常一样,您投入的时间和精力越多,就越容易将它们拿回来。

于 2014-08-22T13:11:13.377 回答