为什么不建议在Oracle中使用直接参考物化视图?

时间:2014-07-25 22:02:05

标签: sql oracle view materialized-views

引自Oracle在线文档

  

与索引不同,可以使用SELECT语句直接访问实例化视图。但是,建议您尝试避免编写直接引用实例化视图的SQL语句,因为在不影响应用程序的情况下很难更改它们。相反,让查询重写透明地重写您的查询以使用物化视图。

我不太明白上下文中direct reference materialized view的确切含义,听起来像SELECT语句没问题,但建议不要通过外键加入物化视图和订单表/视图甚至不推荐select?为什么呢?

1 个答案:

答案 0 :(得分:5)

文档建议您使用物化视图预聚合或预先计算结果,最好让查询重写工作,而不是直接引用查询中的物化视图。如果您使用物化视图来复制远程数据库中的数据,那么查询重写将无法进行播放,您必须直接引用物化视图。

假设您使用物化视图预先汇总结果,请通过快速示例进行操作。假设您有一个简单的数据仓库,您希望获得该月每种产品的总销售额。直接使用表格,您可能会有类似

的内容
SELECT p.product_name, 
       trunc( s.sales_date, 'MM' ) sales_month, 
       sum( s.sales_amt ) total_sales
  FROM sales_fact s
       JOIN product_dim p
         ON( s.product_id = p.product_id )
 GROUP BY p.product_name, trunc( s.sales_date, 'MM' )

如果要优化它,可以创建多个物化视图,然后依赖查询重写来使用这些物化视图,而不是直接命中表。例如,您可以创建一个物化视图,汇总每天产品的销售额

CREATE OR REPLACE MATERIALIZED VIEW sales_by_product_by_day
  ...
  ENABLE QUERY REWRITE
AS
    SELECT p.product_name, 
           trunc( s.sales_date ) sales_day, 
           sum( s.sales_amt ) total_sales
      FROM sales_fact s
           JOIN product_dim p
             ON( s.product_id = p.product_id )
     GROUP BY p.product_name, trunc( s.sales_date )

当然,您可以返回并重写您的查询以使用sales_by_product_by_day物化视图,即

SELECT product_name,
       trunc( sales_day, 'MM' ) sales_month,
       sum( total_sales ) total_sales
  FROM sales_by_product_by_day
 GROUP BY product_name, trunc( sales_day, 'MM' )

然而,通常最好保留查询(引用sales_factproduct_dim视图)并允许查询重写以使用{{1}来优化查询物化视图。从性能角度来看,直接引用实体化视图或者在查询基表时Oracle是否使用查询重写来使用实体化视图并不重要。

通过对基表编写查询,您可以使开发人员和DBA在将来更轻松地调整可用于优化人们正在运行的完整查询集的物化视图集,而无需不断重写查询。例如,可能会发现您希望物化视图按月按产品汇总。对于这个特定的查询,该物化视图的效率会稍微低一些,但对于许多其他查询来说,这可能会更有效。当然,如果您愿意,可以维护两个物化视图(产生维护许多物化视图的开销)。但是,就像索引一样,对于大多数查询而言,使用较小的索引集合而不是大量适合每个查询的索引,通常情况下会更好。

在大多数数据仓库环境中,人们运行的查询集将随着时间的推移而发展,因此您要使用的物化视图集也会随着时间的推移而发展。如果您的查询违反了基表,您可以添加和修改实体化视图并使用查询重写让优化器选择它们并选择要重写的最佳物​​化视图。但是,如果您的查询引用了特定的物化视图,那么当一个可用的视图可用时,Oracle就无法重写另一个物化视图,并且将来更改可用的物化视图集意味着手动重写大量查询。