事实数据表上覆盖索引的有用性



考虑以下形式的事实数据表:

CREATE TABLE Fact1
(
    Dim1 int NOT NULL,
    Dim2 int NOT NULL,
    Dim3 int NOT NULL,
    Data1 int NOT NULL,
    Data2 int NOT NULL
    ...
)

Fact1的每个维度上都有一个列索引。 假定Dim1是时间维度,粒度低至小时范围(例如,2011 年 3 月 12 日下午 2 点到 6 点之间)。在 Dim1 中包含Dim2Dim3作为覆盖列是否有用?或者同样在他们中的任何一个?

更一般地说,将其他维度表 FK 列作为给定维度索引上的覆盖列是否有用?

注意:对于事实数据表,我们假设不需要唯一标识给定的事实。因此,缺少主键或代理键。唯一性由(Dim1,Dim2,Dim3)始终是唯一元组来保证。

我将

尝试回答更一般的问题 - "将其他维度表 FK 列作为给定维度索引的覆盖列是否有用?

是的。如果您有大量的查询执行诸如 COUNT() 之类的操作,其中覆盖索引允许您扫描较小的数据集,那么添加这些其他维度可能是有价值的。

SELECT Dim1, Dim2, count(*)
from Fact1
group by Dim1, Dim2

如果索引仅位于 Dim1 或 Dim2 上,则最终必须执行 FTS 才能进行此计数。这可能完全没问题。完全扫描并不总是坏事。但是,如果你想加快这些类型的查询(假设事实表非常宽),那么在 Dim1 上添加一个 B 树索引,Dim2 将允许 DBMS 转到索引进行计数,而不必转到表进行计数。请注意,它仍将对索引进行完全扫描,这可能只比全表扫描略快。

一般来说,我怀疑你会看到那么大的性能提升,因为你仍然在扫描索引的所有行,除非索引明显小于表,否则你可能不会得到很大的改进。

由于它是一个事实数据表,因此覆盖维度索引的唯一查询是仅查询维度本身时。任何使用事实的内容都需要索引扫描,然后在表中查找实际数据。

我可能只是在 dims 上为使用键(和连接)的查询构建您的 B 树索引,然后在系统运行一段时间并且已识别常见查询时根据需要添加其他索引。

我能想到的另一种情况是,诸如此类的"覆盖"索引可能有助于加快查询速度,当您的查询侧重于特定维度组合,并且您只需要这些特定行时。

SELECT Dim1, Dim2, Data1, Data2
  FROM Fact1 
 WHERE Dim1 = @A and Dim2 = @B;

如果您在Dim1, Dim2上有一个 b 树索引而不仅仅是 Dim1,您可能会看到非常轻微的性能提升,因为您扫描索引以查找 WHERE 子句中的所有项目,然后获取您的事实数据。

最新更新