我有一个Fact Constellation Schema设计的SQL Server数据仓库。我必须建立一个关于4个对象/视图的报告:
所有对象/视图都具有相同的签名,例如:
Sales actuals: ProductID, RegionID, SalesManagerID, ..., <product data>, <region data>, ..., Quantity;
Sales targets: ProductID, --null--, SalesManagerID, ..., <product data>, -----null----, ..., Quantity;
Stocks: ProductID, RegionID, -----null-----, ..., <product data>, <region data>, ..., Quantity;
...
为了实现这样的签名,每个对象/视图都来自事实表和5-6维度表。维度表在对象之间共享(包含产品数据的表,包含区域数据的表,......)。
计算每个视图不需要超过5-10秒的SQL。
现在我想将它们合并到一个报告中,我这样做:
Select * from [Sales actuals]
UNION
Select * from [Sales targets]
UNION
Select * from [Stocks]
UNION
Select * from [Inbound]
此处SQL甚至无法在1分钟内检索到10%的数据。似乎查询优化器将4个事实表组合成一个大型向量并附加维度表 - 这会使系统疯狂。
我想要的是保持视图/对象的封装。这意味着,引擎必须首先计算视图(4 * 5秒= 20秒)。然后才应用Union操作(10秒+一些开销)来检索结果。
问题:如何在嵌套视图中禁用查询优化以实现这种“计算封装”?
像编译器那样做:首先联合事实表,然后加入维表 - 不是选项,因为我想保持代码可解释和可重用。
提前致谢! 君士坦丁
答案 0 :(得分:1)
对于初学者,您可能希望将UNION
更改为UNION ALL
?!?
要让服务器执行您想要的操作,可以在“最终”视图中添加NOEXPAND
表提示;但说实话,我从来没有看到它对整体表现有益。
我想知道如果你尝试过以下方面的话,查询优化器会有多聪明:
;WITH facts (dimension_ids & measures)
AS (Select * from [Sales actuals]
UNION ALL
Select * from [Sales targets]
UNION ALL
Select * from [Stocks]
UNION ALL
Select * from [Inbound])
SELECT dimension_values, measures
FROM facts
JOIN dimension1 ON dim1.id = facts.dim1_id
AND dim1.property = @filter_dim1
JOIN dimension2 ON dim2.id = ...
etc...
它可能会做你想要的,虽然我不相信它会比
更好SELECT dimension_values, measures
FROM [Sales actuals] fct
JOIN dimension1 ON dim1.id = fct.dim1_id
AND dim1.property = @filter_dim1
JOIN dimension2 ON dim2.id = ...
UNION ALL
SELECT dimension_values, measures
FROM [Sales targets] fct
JOIN dimension1 ON dim1.id = fct.dim1_id
AND dim1.property = @filter_dim1
JOIN dimension2 ON dim2.id = ...
UNION ALL
etc...
通过你的解释 - 你正在遇到什么,显然有可怕的表现?
PS:我知道这听起来很“基本”,但你是先运行sp_updatestats吗?