6

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

ここで、Query Rewrite を次のクエリで開始する必要があります。

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 個の仮想列でこれを行っています (それらはすべて同じ構造で、上記の単純なケース ステートメントを持っていますが、比較列と結果列が異なります)。

この問題は、ファクト テーブルに仮想列がある場合にのみ発生するようですが、それらを非仮想列に変更すると、ディスク領域が大量に消費されます。Oracle がクエリを書き換えないのはなぜですか? 修正するにはどうすればよいですか?

4

1 に答える 1

2

これがどれほど役立つかはわかりませんが、Oracle では、マテリアライズド ビューがグループ化されたすべての列をステートメントに含める必要があります。(少なくとも仮想列と組み合わせて編集します。これはおそらく「設計によるものではありません」...)

explain_rewriteつけようとしたら

 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

aこれで、両方の列bが選択され、グループ化されます (同じ結果セットを確保するための外部クエリを使用):

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
于 2011-01-31T19:11:13.890 に答える