高速リフレッシュのデータ取得元テーブルへの影響確認

2テーブル結合の集計マテビューで確認
マテビューで参照されている場合と参照されていない場合でinsert10万件の時間を比較する

結論:
高速リフレッシュが有効の場合、更新性能は大幅に劣化する

(8.0.27)


前提:
「マテビュー」記載手順でマテビュー環境構築済
既存ルートユーザの認証方法変更済
alter user 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY password;

 

-- 1. 参照元テーブル作成

drop table test.order_header;
drop table test.order_detail;

create table test.order_header(
orderid    int not null,
orderdate  datetime ,
customerid int
);
alter table test.order_header add constraint order_header_pk primary key (orderid);

create table test.order_detail(
orderid    int not null,
renban     int not null,
productid  int ,
unitprice  int,
orderqty   int
);
alter table test.order_detail add constraint order_detail_pk primary key (orderid,renban);

-- 2. マテビューログ作成

CALL flexviews.create_mvlog('test','order_header');
CALL flexviews.create_mvlog('test','order_detail');

select * from flexviews.mvlogs where table_name='order_header';
select * from flexviews.mvlogs where table_name='order_detail';

select * from flexviews.mvlog_02080293ff8f9f6d311b69e86f92cecd;
select * from flexviews.mvlog_70fbcd3aea64ec543ad200372d6621dc;

insert into test.order_header values(1,'2021-01-01',100);
insert into test.order_header values(2,'2021-01-02',200);

insert into test.order_detail values(1,1,9901,30,1);
insert into test.order_detail values(1,2,9902,50,10);
insert into test.order_detail values(1,3,9903,10,15);
insert into test.order_detail values(2,1,9901,30,2);


-- 3. マテビュー作成

call flexviews.create('test','mview1','INCREMENTAL');

set @mv_id = flexviews.get_id('test', 'mview1');
select @mv_id;

select * from flexviews.mview;

call flexviews.add_table(@mv_id, 'test', 'order_header', 't1', NULL);
call flexviews.add_table(@mv_id, 'test', 'order_detail', 't2', 'on t1.orderid = t2.orderid');

select * from flexviews.mview_table;

call flexviews.add_expr(@mv_id, 'SUM', 't2.unitprice * t2.orderqty', 'total_amount');
call flexviews.add_expr(@mv_id, 'GROUP', 't1.orderdate', 'group_on_orderdate');
call flexviews.add_expr(@mv_id, 'GROUP', 't2.productid', 'group_on_productid');

select * from flexviews.mview_expression;


call flexviews.enable(@mv_id);

 

select * from test.order_header;
select * from test.order_detail;
select * from test.mview1;

insert into test.order_header values(3,'2021-01-02',100);
insert into test.order_detail values(3,1,9901,30,10);
insert into test.order_detail values(3,2,9902,50,20);


-- 4. リフレッシュ動作確認
set @mv_id = flexviews.get_id('test', 'mview1');
select @mv_id;
call flexviews.refresh(@mv_id,'BOTH',NULL);


-- call flexviews.refresh(@mv_id,'COMPUTE',NULL);
-- call flexviews.refresh(@mv_id,'APPLY',NULL);


※うまく動かなくなった場合は下記を実施してリセットする

drop database flexviews;
testスキーマにあるマテビューの実表を削除
CDCサービスkill
CDCセットアップ
CDCサービス起動
install.sql実行

-- 5. データ投入の時間計測

truncate table test.order_header;
truncate table test.order_detail;
truncate table test.mview1;


drop procedure test.proc1;

delimiter //
create procedure test.proc1(in x int)
begin
  declare i int;
  set i = 0;
  while i < x do
    set i = i + 1;
    insert into test.order_header values(
     i
    ,date_add('2020-01-01', interval floor(100 * rand()) day)
    ,floor(rand() * 100)+1
    );

    insert into test.order_detail values(
     i
    ,1
    ,floor(rand() * 100)+1
    ,(floor(rand() * 10)+1) * 100
    ,floor(rand() * 10)+1
    );

    insert into test.order_detail values(
     i
    ,2
    ,floor(rand() * 100)+1
    ,(floor(rand() * 10)+1) * 100
    ,floor(rand() * 10)+1
    );

  end while;
end
//
delimiter ;


call test.proc1(100000);

 

-- 5.1. マテビューの参照テーブルとなっている場合
10万件
(3 min 19.14 sec)

-- 5.2. マテビューの参照テーブルとなっていない場合
10万件
(2 min 41.19 sec)

 

 

(19c)


https://seisenudoku.seesaa.net/article/472425809.html


-- 1. 参照元テーブル作成

drop table order_header purge;
drop table order_detail purge;

create table order_header(
orderid    int not null,
orderdate  timestamp,
customerid int
);
alter table order_header add constraint order_header_pk primary key (orderid);

create table order_detail(
orderid    int not null,
renban     int not null,
productid  int ,
unitprice  int,
orderqty   int
);
alter table order_detail add constraint order_detail_pk primary key  (orderid,renban);

 

insert into order_header values(1,'2021-01-01',100);
insert into order_header values(2,'2021-01-02',200);

insert into order_detail values(1,1,9901,30,1);
insert into order_detail values(1,2,9902,50,10);
insert into order_detail values(1,3,9903,10,15);
insert into order_detail values(2,1,9901,30,2);

commit;

-- 2. マテビューログ作成

create materialized view log on order_header with sequence, rowid
(orderid, orderdate, customerid)
including new values;

create materialized view log on order_detail with sequence, rowid
(orderid, renban, productid, unitprice, orderqty)
including new values;


-- 3. マテビュー作成

 

create materialized view mview1
build immediate  
refresh fast on commit
enable query rewrite as
select
 t1.orderdate
,t2.productid
,sum(t2.unitprice * t2.orderqty) total_amount
,COUNT(T2.UNITPRICE * T2.ORDERQTY) TOTAL_AMOUNT_CNT
,COUNT(*) CNT
from order_header t1
inner join order_detail t2
on t1.orderid = t2.orderid
group by t1.orderdate,t2.productid
;

 


-- 4. リフレッシュ動作確認


select * from order_header order by orderid;
select * from order_detail order by orderid,renban;
select * from mview1 order by orderdate,productid;


insert into order_header values(3,'2021-01-02',100);
insert into order_detail values(3,1,9901,30,10);
insert into order_detail values(3,2,9902,50,20);
commit;


※マテビューの元表に対してTRUNCATEした後、高速リフレッシュをするとエラーになる。

ORA-32321: "TEST"."MVIEW1"のREFRESH FASTはディテール表のTRUNCATE後はサポートされていません

完全リフレッシュなら実行可能

exec DBMS_MVIEW.REFRESH( 'MVIEW1', 'f');
exec DBMS_MVIEW.REFRESH( 'MVIEW1', 'c');

 

-- 5. データ投入の時間計測

truncate table order_header;
truncate table order_detail;
exec DBMS_MVIEW.REFRESH( 'MVIEW1', 'c');

set time on
set timing on

declare
begin
for i in 1..100000 loop
  insert into order_header values
  (i
  ,to_date('20200101','yyyymmdd') + floor(dbms_random.value(0, 100))
  ,floor(dbms_random.value(1, 101))
  );

  insert into order_detail values
  (i
  ,1
  ,floor(dbms_random.value(1, 101))
  ,floor(dbms_random.value(1, 11)) * 100
  ,floor(dbms_random.value(1, 101))
  );

  insert into order_detail values
  (i
  ,2
  ,floor(dbms_random.value(1, 101))
  ,floor(dbms_random.value(1, 11)) * 100
  ,floor(dbms_random.value(1, 101))
  );

  commit;
end loop;
end;
/


select * from order_header order by orderid        fetch first 20 rows only;
select * from order_detail order by orderid,renban fetch first 20 rows only;
select * from mview1 order by orderdate,productid  fetch first 20 rows only;


-- 5.1. マテビューの参照テーブルとなっている場合
10万件
経過: 00:44:28.62


★8万件まですすんだところで下記エラー
ORA-04036: インスタンスにより使用されるPGAモリーPGA_AGGREGATE_LIMITを超えて います ORA-06512: 行26
alter system set pga_aggregate_limit=3G scope=both;
で2G=>3Gに増やして再実行

マテビュー削除
select * from user_mviews;
select * from user_mview_logs;

DROP MATERIALIZED VIEW LOG ON ORDER_DETAIL;
DROP MATERIALIZED VIEW LOG ON ORDER_HEADER;

DROP MATERIALIZED VIEW MVIEW1;

 

-- 5.2. マテビューの参照テーブルとなっていない場合
10万件
経過: 00:00:20.19

 

 

 


(14)

https://qiita.com/nuko_yokohama/items/0ae59f5d797bc79dcc06

-- 1. pg_ivm(IMMV)のインストール


git clone https://github.com/sraoss/pg_ivm
cd pg_ivm

make USE_PGXS=1 PG_CONFIG=/usr/pgsql-14/bin/pg_config
sudo make install USE_PGXS=1 PG_CONFIG=/usr/pgsql-14/bin/pg_config


CREATE EXTENSION pg_ivm;
\dx



現状集約関数に対応していない
truncate未対応

-- 2. 参照元テーブル作成

drop table order_header;
drop table order_detail;

create table order_header(
orderid    int not null,
orderdate  timestamp,
customerid int
);
alter table order_header add constraint order_header_pk primary key (orderid);

create table order_detail(
orderid    int not null,
renban     int not null,
productid  int ,
unitprice  int,
orderqty   int
);
alter table order_detail add constraint order_detail_pk primary key  (orderid,renban);


insert into order_header values(1,'2021-01-01',100);
insert into order_header values(2,'2021-01-02',200);

insert into order_detail values(1,1,9901,30,1);
insert into order_detail values(1,2,9902,50,10);
insert into order_detail values(1,3,9903,10,15);
insert into order_detail values(2,1,9901,30,2);

-- 3. マテビュー作成

select create_immv('mview1', $$
select
 t1.orderdate
,t2.productid
,t2.unitprice * t2.orderqty total_amount
from order_header t1
inner join order_detail t2
on t1.orderid = t2.orderid
$$
);

\dt mview1

select * from mview1;


-- 4. リフレッシュ動作確認


select * from order_header order by orderid;
select * from order_detail order by orderid,renban;
select * from mview1 order by orderdate,productid;


insert into order_header values(3,'2021-01-02',100);
insert into order_detail values(3,1,9901,30,10);
insert into order_detail values(3,2,9902,50,20);


-- 5. データ投入の時間計測

truncate table order_header;
truncate table order_detail;

\timing 1

do $$
declare
begin

  for i in 1..100000 loop
    insert into order_header values
    (i
    ,'2020-01-01'::date + CAST( floor(100 * random()) || 'days' AS interval)
    ,floor(random() * 100)+1
    );

    insert into order_detail values
    (i
    ,1
    ,floor(random() * 100)+1
    ,( floor(random() * 10)+1 ) * 100
    ,floor(random() * 100)+1
    );

    insert into order_detail values
    (i
    ,2
    ,floor(random() * 100)+1
    ,( floor(random() * 10)+1 ) * 100
    ,floor(random() * 100)+1
    );

  end loop;
end
$$
;

select * from order_header order by orderid        fetch first 20 rows only;
select * from order_detail order by orderid,renban fetch first 20 rows only;
select * from mview1 order by orderdate,productid  fetch first 20 rows only;

-- 5.1. マテビューの参照テーブルとなっている場合
10万件
時間: 67658.302 ミリ秒(01:07.658)


-- 5.2. マテビューの参照テーブルとなっていない場合
10万件
時間: 2545.425 ミリ秒(00:02.545)

 

 


(2019)
https://docs.microsoft.com/ja-jp/sql/relational-databases/views/create-indexed-views?view=sql-server-ver15

多数のインデックス付きビュー、または少数ではあるものの非常に複雑なインデックス付きビューで参照されるテーブルに対して
DML (UPDATE、DELETE、INSERT など) を実行する場合、DML 実行時にこれらのインデックス付きビューを更新する必要もあります。
その結果、DML クエリのパフォーマンスが大幅に低下する場合があります。

 

-- 1. 参照元テーブル作成

drop table order_header;
drop table order_detail;

create table order_header(
orderid    int not null,
orderdate  datetime2,
customerid int
);

alter table order_header add constraint order_header_pk primary key (orderid);

create table order_detail(
orderid    int not null,
renban     int not null,
productid  int ,
unitprice  int NOT NULL,
orderqty   int NOT NULL
);
alter table order_detail add constraint order_detail_pk primary key (orderid,renban);

 

insert into order_header values(1,'2021-01-01',100);
insert into order_header values(2,'2021-01-02',200);

insert into order_detail values(1,1,9901,30,1);
insert into order_detail values(1,2,9902,50,10);
insert into order_detail values(1,3,9903,10,15);
insert into order_detail values(2,1,9901,30,2);


-- 2. インデックス付きビュー作成

-- set the options to support indexed views.
set numeric_roundabort off;
set ansi_padding, ansi_warnings, concat_null_yields_null, arithabort,
   quoted_identifier, ansi_nulls on;


-- create view with schemabinding.
if object_id ('mview1', 'view') is not null
   drop view mview1 ;
go

create view mview1
with schemabinding as
select
 t1.orderdate
,t2.productid
,sum(t2.unitprice * t2.orderqty) total_amount
,COUNT_BIG(*) CNT
from dbo.order_header t1
inner join dbo.order_detail t2
on t1.orderid = t2.orderid
group by t1.orderdate,t2.productid
;
go

-- create an index on the view.
create unique clustered index mview1_idx01
on mview1 (orderdate, productid);
go


-- 3. リフレッシュ動作確認


select * from order_header order by orderid;
select * from order_detail order by orderid,renban;
select * from mview1 order by orderdate,productid;


insert into order_header values(3,'2021-01-02',100);
insert into order_detail values(3,1,9901,30,10);
insert into order_detail values(3,2,9902,50,20);


-- 4. データ投入の時間計測

delete from order_header;
delete from order_detail;

※truncateは実行不可
TRUNCATE TABLE 'order_header' できません。オブジェクト 'mview1' によって参照されています。


set nocount on
declare @i int;
set @i = 1;
begin transaction;
while @i <= 100000
begin
  insert into order_header values(
     @i
    ,dateadd(day,floor(100 * rand()),'2020-01-01')
    ,floor(rand() * 100)+1
    );

  insert into order_detail values(
     @i
    ,1
    ,floor(rand() * 100)+1
    ,(floor(rand() * 10)+1) * 100
    ,floor(rand() * 100)+1
    );
    
  insert into order_detail values(
     @i
    ,2
    ,floor(rand() * 100)+1
    ,(floor(rand() * 10)+1) * 100
    ,floor(rand() * 100)+1
    );

  set @i = @i + 1;
end


select top 20 * from order_header order by orderid;
select top 20 * from order_detail order by orderid,renban;
select top 20 * from mview1 order by orderdate,productid;

 

-- 4.1. インデックス付きビューの参照テーブルとなっている場合
10万件
4分12秒


-- 4.2. インデックス付きビューの参照テーブルとなっていない場合
10万件 
2秒