嵌套视图中的不需要的查询优化

时间:2014-01-13 10:24:45

标签: sql-server query-optimization data-warehouse nested-views

我有一个Fact Constellation Schema设计的SQL Server数据仓库。我必须建立一个关于4个对象/视图的报告:

  1. 销售实际 - 事实表[销售]
  2. 销售目标 - 事实表[目标]
  3. 股票 - 事实表[库存]
  4. 入境 - 事实表[Transit]
  5. 所有对象/视图都具有相同的签名,例如:

    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秒+一些开销)来检索结果。

    问题:如何在嵌套视图中禁用查询优化以实现这种“计算封装”?

    像编译器那样做:首先联合事实表,然后加入维表 - 不是选项,因为我想保持代码可解释和可重用。

    提前致谢! 君士坦丁

1 个答案:

答案 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吗?