考虑以下形式的事实表:
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点之间)。将Dim2
和Dim3
包含在Dim1中的列中是否有用?或者同样在他们中任何一个?
更一般地说,将其他维度表FK列作为覆盖列包含在给定维度的索引中是否有用?
注意:对于事实表,我们假设不需要唯一地标识给定事实。因此,缺少主键或代理键。唯一性由(Dim1,Dim2,Dim3)保证始终是一个独特的元组。
答案 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子句中所有项目的索引,并且然后得到你的事实数据。