在日期范围内搜索时的复合索引设计(窄与宽)

Composite Index Design (Narrow vs Wide) when searching on date range

我和我的同事就复合索引的设计发生了争执。如果查询中使用了两个字段,我认为更独特的字段应该在第一位。

看这个例子

CREATE TABLE [dbo].[tblPurchase](
    [PurchaseId] [int] NOT NULL,
    [ProductId] [int] NOT NULL,
    [ItemId] [int] NOT NULL,
    [PurchaseDate] [date] NOT NULL,
    [CurrencyId] [int] NOT NULL,
    ...
    ...
    ...
CONSTRAINT [PK_tblPurchase] PRIMARY KEY CLUSTERED 
(
    [PurchaseId] ASC,
    [ProductId] ASC,
    [ItemId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

目前我们有 2 种货币,我们有大约 200 万条记录(注意:我们可能会在不久的将来添加 2 种新货币)。

我决定使用 [PurchaseDate]-[CurrencyId] 作为复合索引创建一个索引,但我的同事认为我们应该将其翻转为使用 [CurrencyId]-[PurchaseDate],因为 CurrencyId 不那么唯一。我们的查询是:

SELECT *
FROM [tblPurchase]
WHERE [PurchaseDate] >= '2022-01-01' AND [PurchaseDate] <= '2022-06-01' AND [CurrencyId] = 1

有什么想法吗?

的最佳索引
WHERE PurchaseDate >= '2022-01-01' AND PurchaseDate <= '2022-06-01' AND CurrencyId = 1

[CurrencyId]-[PurchaseDate]

这与选择性无关。

它可以使用第一列在 CurrencyId 上进行相等搜索,然后在第二列上进行范围搜索,以便准确读取正确的行来解决查询。

对于反向索引顺序,它可以做的最好的事情是在日期谓词上进行范围查找,然后是剩余谓词以丢弃为其他货币读取的行。因此在这种情况下索引查找将读取更多行(假设日期范围内存在其他货币 ID 而不仅仅是 1)。

要使用 phone 书籍类比(按姓氏、名字排序),这与直接查找所有 Smiths 的方式相同从 AliceBob 的名称(找到 Alice Smith starts/would 所在的点,然后读取所有条目,直到找到第一个在之后排序的条目“鲍勃史密斯”)

但是要用它来查找姓氏从 ClarkDavis[ 的所有 Alices 需要做更多的工作=34=](SQL 服务器将读取从 Clark 到 Davis 的所有条目并丢弃非 Alice 的条目)