【问题标题】:Oracle query rewrite with virtual columns in the source table使用源表中的虚拟列重写 Oracle 查询
【发布时间】:2011-06-18 17:46:51
【问题描述】:

我在 Oracle 11g 中有一个表 demo_fact,它有几个这样定义的虚拟列:

ALTER TABLE demo_fact ADD (demo_measure_from_virtual NUMBER GENERATED ALWAYS AS
  (CASE WHEN  demo_category_column = 20 THEN demo_numericdata_column ELSE 0 END)
  VIRTUAL VISIBLE);

然后我有一个物化视图定义为

CREATE MATERIALIZED VIEW demo_agg_mv 
REFRESH FORCE ON DEMAND
ENABLE QUERY REWRITE
AS 
SELECT
  demo_dim_one,
  demo_dim_two,
  SUM(demo_measure_from_virtual) demo_measure_from_virtual
  FROM demo_fact
  GROUP BY demo_dim_one, demo_dim_two

现在我希望查询重写启动以下查询:

SELECT demo_dim_one, SUM(demo_measure_from_virtual) 
FROM demo_fact
GROUP BY demo_dim_one

但事实并非如此。我运行了 EXPLAIN_REWRITE,这是输出:

QSM-01150: query did not rewrite
QSM-01102: materialized view, DEMO_AGG_MV, requires join back to table, 
           DEMO_FACT, on column, DEMO_MEASURE_FROM_VIRTUAL
QSM-01082: Joining materialized view, DEMO_AGG_MV, with table, DEMO_FACT, 
           not possible
QSM-01102: materialized view, DEMO_AGG_MV, requires join back to table, 
           DEMO_FACT, on column, DEMO_NUMERICDATA_COLUMN

背景故事:我正在使用 70M 行和 50 个虚拟列(它们都具有相同的结构,上面的简单 case 语句,但具有不同的比较列和不同的结果列)

这个问题似乎只在事实表具有虚拟列时才会出现,但将它们更改为非虚拟列会消耗过多的磁盘空间。为什么 Oracle 不重写查询?我能做些什么来解决它?

【问题讨论】:

    标签: oracle oracle11g materialized-views


    【解决方案1】:

    我不知道这对您有多大帮助,但 Oracle 要求将实体化视图分组的所有列都包含在要重写的语句中。 (编辑至少与虚拟列一起使用。这可能“不是设计使然”...)

    如果你尝试explain_rewrite on

     select
        demo_dim_one,
        sum(s)
     from (
        select 
          demo_dim_one,
          sum(demo_measure_from_virtual) s
        from 
           demo_fact
        group by
          demo_dim_one,
          demo_dim_two
     )
     group by demo_dim_one
    

    它应该告诉你它已经重写了查询。

    这可以这样证明:

    将在其上定义虚拟列的表:

    create table tq84_virt_col (
      a  varchar2(2),
      b varchar2(2),
      c  number,
      d  number 
    );
    
    
    insert into tq84_virt_col values ('A', 'X',  1, 1);
    insert into tq84_virt_col values ('A', 'X',  2, 1);
    insert into tq84_virt_col values ('A', 'Y',  3, 0);
    insert into tq84_virt_col values ('A', 'Y',  4, 1);
    
    insert into tq84_virt_col values ('B', 'Y', 11, 1);
    insert into tq84_virt_col values ('B', 'X', 12, 0);
    insert into tq84_virt_col values ('B', 'X', 13, 1);
    

    虚拟列的定义:

    alter table tq84_virt_col add (
      virt_col number generated always as (
        case when d = 1 then c else 0 end
      )
      virtual visible
    );
    

    物化视图。注意:它在 ab 列上分组:

    create materialized view tq84_mat_view
    refresh force on demand
    enable query rewrite
    as 
    select 
      a, b,
      sum(virt_col) sum_virt_col
    from
      tq84_virt_col
    group by 
      a,b 
    

    正如您所观察到的,不会使用物化视图:

    begin
      dbms_mview.explain_rewrite(
        'select a, sum(virt_col) from tq84_virt_col group by a'
      );
    end;
    /
    
    select message
    from rewrite_table;
    
    QSM-01150: query did not rewrite
    QSM-01102: materialized view, TQ84_MAT_VIEW, requires join back to table, TQ84_VIRT_COL, on column, VIRT_COL
    QSM-01082: Joining materialized view, TQ84_MAT_VIEW, with table, TQ84_VIRT_COL, not possible
    QSM-01102: materialized view, TQ84_MAT_VIEW, requires join back to table, TQ84_VIRT_COL, on column, C
    

    现在,ab 两列都被选中并分组(使用外部查询以确保相同的结果集):

    truncate table rewrite_table;
    
    begin
      dbms_mview.explain_rewrite(
        'select a, sum(s) from (select a, sum(virt_col) s from tq84_virt_col group by a, b) group by a'
      );
    end;
    /
    
    select message
    from rewrite_table;
    
    QSM-01151: query was rewritten
    QSM-01209: query rewritten with materialized view, TQ84_MAT_VIEW, using text match algorithm
    QSM-01219: no suitable materialized view found to rewrite this query
    

    【讨论】:

    • 很好的解释!感谢您抽出宝贵的时间。不幸的是,我正在使用 SAP BusinessObjects,所以我希望使用非嵌套查询。我会将此标记为已接受的答案,因为它解释得如此迅速。
    猜你喜欢
    • 2013-08-03
    • 1970-01-01
    • 2014-08-19
    • 2017-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-29
    • 1970-01-01
    相关资源
    最近更新 更多