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

时间:2012-06-15 18:33:02

标签: sql-server-2005 indexing data-warehouse olap star-schema

考虑以下形式的事实表:

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点之间)。将Dim2Dim3包含在Dim1中的列中是否有用?或者同样在他们中任何一个?

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

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

1 个答案:

答案 0 :(得分:4)

我将尝试回答更一般的问题 - “将其他维度表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子句中所有项目的索引,并且然后得到你的事实数据。