私は以下のスキーマとデータを持っています。2つのテーブルの間に任意の3番目のテーブルを持つ関係
--drop table table_c;
--drop table table_b;
--drop table table_a;
create table table_a (
id number(3,0) primary key,
value varchar2(10)
);
create table table_b (
id number(3,0) primary key,
a_id number(3,0) not null,
value varchar2(10),
constraint b_fk1 foreign key (a_id) references table_a(id)
);
create table table_c (
id number(3,0) primary key,
a_id number(3,0) null,
b_id number(3,0) null,
value varchar2(10),
constraint c_fk1 foreign key (a_id) references table_a(id),
constraint c_fk2 foreign key (b_id) references table_b(id)
);
-- table a
insert into table_a (id, value) values (1, 'a');
insert into table_a (id, value) values (2, 'b');
-- table b
insert into table_b (id, a_id, value) values (1, 1, 'aa');
insert into table_b (id, a_id, value) values (2, 2, 'bb');
-- table c with ref to a
insert into table_c (id, a_id, value) values (1, 1, 'aaa');
insert into table_c (id, a_id, value) values (2, 2, 'bbb');
-- table c with ref to b
insert into table_c (id, b_id, value) values (3, 1, 'ccc');
insert into table_c (id, b_id, value) values (4, 2, 'ddd');
COMMIT;
我々はtable_c
からtable_a
への直接リンクを持っていない場合は、基本的table_a
とtable_b
を通るルートとtable_c
との関係です。
table_c
の各要素は、a_id
またはb_id
のいずれかになります。 a_id
がある場合、b_id
はありません。 b_id
がある場合、a_id
はありません。どちらも同時にnull
になることはできません。同時にnullでないこともあります。
table_a
とtable_c
の関係を示すマテリアライズドビューを作成するように求められました。
私の最初のアイデアは、table_c
を更新して、a_id
が常に最新であるようにすることでした。顧客はデータベースを強く把握しており、これを禁止します。
--drop materialized view mv_d;
--drop materialized view log on table_c;
--drop materialized view log on table_b;
--drop materialized view log on table_a;
create materialized view log on table_a with rowid, sequence;
create materialized view log on table_b with rowid, sequence;
create materialized view log on table_c with rowid, sequence;
create materialized view mv_d
refresh fast on commit
enable query rewrite
as
select a.value as a_val,
c.value as c_val,
a.rowid as a_rowid,
b.rowid as b_rowid,
c.rowid as c_rowid
from table_a a,
table_b b,
table_c c
where (c.a_id is null and c.b_id = b.id and b.a_id = a.id)
or (c.a_id is not null and c.a_id = a.id);
execute dbms_stats.gather_table_stats(user, 'mv_d') ;
このmvの問題は、結果が期待したものではないことです。ここに私が得るものがある。 rowidは相違点と実際の結果を示すために省略されているので、重複する理由を示しています。
select * from mv_d;
-- note, the rowids are for information only, but are abbreviated to only show how they're different.
a_val | c_val | a_rowid | b_rowid | c_rowid
-------+-------+---------+---------+---------
a | aaa | GAAA | WAAA | mAAA
a | ccc | GAAA | WAAA | mAAC
a | aaa | GAAA | WAAB | mAAA
b | bbb | GAAB | WAAA | mAAB
b | bbb | GAAB | WAAB | mAAB
b | ddd | GAAB | WAAB | mAAD
理想的には、私は(rowid
列、OFCをバー)select * from mv_d
から次のような結果を得るだろう。
a_val | c_val
-------+-------
a | aaa
a | ccc
b | bbb
b | ddd
どのようにしてマテリアライズドビューでその結果を取得できますか?
私の実際のデータベースはtable_a
,、table_c
のそれぞれ300万件、600万件、100万件の記録であることに注意してください。フィルタリングされたすべての実際の結果は、約10kレコードのマテリアライズド・ビューに存在します。マテリアライズド・ビューの
この古いスタイルのコードを使用してください? – jarlh
@jarlh 1億レコードの中間mv_dでですか?いいえ、私はそれを持つことはできません。問題はマテリアライズド・ビューの問合せにあり、問合せでは発生しません。 –