« 古くて新しい? 遅延ブロッククリーンアウト (deferred block cleanout) #7 | トップページ | 古くて新しい? 遅延ブロッククリーンアウト (deferred block cleanout) #9 »

2021年9月14日 (火)

古くて新しい? 遅延ブロッククリーンアウト (deferred block cleanout) #8

Previously on Mac De Oracle
前回からのつづき(ちょいと寄り道中)
です。

では、とっとと試してみましょうw

バッファキャッシュから溢れ出る程度のデータ量だったら、どうなるのかなーーーー、という検証です。やりたいことは図の通りです。
Photo_20210911234101

検証方法を考えていたのですが、自動共有メモリー管理になっているのと、sga_max_size/sga_targetを小さくしすぎるとOracle Databaseが起動しないなど諸々引きそうなので、shared_pool_sizeを大きく設定して、バッファキャッシュに回せるメモリーを減らすことで、バッファキャッシュを小さく、バッファから溢れる程度のデータ量も少なくて済むようにして試してみることにします。

準備段階から書いてます。再現させる環境をどうセットアップしたかっていうことも重要だと思うのですよね。少々長くなっちゃいますが。



検証準備

CDBに接続して初期化パラメータを調整!!

SGAコンポーネントの状況
Database Buffersが、3G以上になってます。検証データ量も多くなってしまうので、これを1GB程度まで下げたいですね。検証時間も節約できますし、最小の手数で検証できるほうが良いですから:)

SYS@orclcdb> show sga
Total System Global Area 4294963960 bytes
Fixed Size 9143032 bytes
Variable Size 805306368 bytes
Database Buffers 3472883712 bytes
Redo Buffers 7630848 bytes

SYS@orclcdb> select 3472883712 / 1024 / 1024 AS "MB" from dual;

MB
----------
3312

Elapsed: 00:00:00.00


sga_max_size,sga_min_sizeが4GBですが、ここはそのままにします。あまり小さくしすぎると起動しなくなったり。(^^;;;;

SYS@orclcdb> show parameter sga
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
allow_group_access_to_sga boolean FALSE
lock_sga boolean FALSE
pre_page_sga boolean TRUE
sga_max_size big integer 4G
sga_min_size big integer 0
sga_target big integer 4G
unified_audit_sga_queue_size integer 1048576


自動SGA管理なので、Shared Pool Sizeに大きめの値を設定。
自動SGA管理下で自動管理対象メモリーコンポーネントパラメータに値を設定した場合、その値が下限値となり最低でもその値は確保されるという仕組みを利用します!

SYS@orclcdb> show parameter shared_pool

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
shared_pool_reserved_size big integer 39426457
shared_pool_size big integer 0


起動しなくなっても戻しやすいようにspfileをpfileに書き出して退避後に、shared_pool_sizeを3GBへ増やします。これで4Gのうちの3G程度がshared poolに割り当てられ、バッファキャッシュは1GBぐらいになるはず。(VirtualBoxなのでスナップショット取得しておいて戻すのもありですけどw)

SYS@orclcdb> create pfile='pfile20210912.ora' from spfile;

File created.

Elapsed: 00:00:00.00
SYS@orclcdb> alter system set shared_pool_size = 3g scope=both;

System altered.

Elapsed: 00:00:00.77


Database Buffersがいい感じにシュリンクしました。1GBぐらいになりました。これで進めますよー。

SYS@orclcdb> show sga
Total System Global Area 4294963960 bytes
Fixed Size 9143032 bytes
Variable Size 3238002688 bytes
Database Buffers 1040187392 bytes
Redo Buffers 7630848 bytes

SYS@orclcdb> select 1040187392 / 1024 / 1024 AS "MB" from dual;

MB
----------
992

Elapsed: 00:00:00.01


ざっくりとブロック数を計算

SYS@orclcdb> select 1040187392 / 8192 AS "blocks" from dual;

blocks
---------------
126976

Elapsed: 00:00:00.01


前回のHOGE表に200,000 rowsで、66,667 blocks のデータを生成したので、126,976 blocks を満たすデータ量にしようとすると 400,000 rowsほど必要になりそうですね。。。。少々多めで、バッファキャッシュから溢れる程度の量で、 500,000 rowsのデータを登録することにしましょう!!!!

SYS@orclcdb> select ceil(126976 / 66667) * 200000 AS "rows" from dual;

rows
----------
400000

Elapsed: 00:00:00.00


これまでの検証から 10%-15%程度がCOMMITクリーンアウトされ、残りが遅延されるのは確認できたので、126976 blocks のバッファキャッシュだと、 17,777 blocks ぐらいがコミットクリーンアウトされそうですね。(今回のテストケースではコミットクリーンアウトされないけど。。された場合は最大でこの程度。。。というメモです。はい)

SYS@orclcdb> select ceil(126976 * 0.14) AS "blocks for commit cleanout" from dual;

blocks for commit cleanout
--------------------------
17777

Elapsed: 00:00:00.00

前回作成したデータは、200,000rowsで、66,667 blocksだったので、500,000 rows だと、ざっくり 166,668 blocks ほど。

SCOTT@orcl> select ceil(66667 / 2 * 5) AS "blocks" from dual;

blocks
----------
166668

Elapsed: 00:00:00.00


なので、遅延ブロッククリーンアウトされると想定される(コミットクリーンアウト分を覗くと)ブロック数は、148,891 blocks 程度にはなりそう。

SYS@orclcdb>  select ceil((66667 / 2 * 5) - 17777) AS "blocks" from dual;
blocks
----------
148891

Elapsed: 00:00:00.01


それに加えて、バッファキャッシュに収まらず、コミットする前にバッファキャッシュから落とされ、ストレージへかきだされてしまうブロック数は、これまた、ざっくり計算すると 39,692 blocks ほどですかね。バッファキャッシュのサイズから全てのブロックは乗り切らないので、最初に読み込まれていたブロックから落とされていくことにはなりますね。。
とはいえ、この検証ではキャッシュ落とされるブロック数は特に気にしてなくて、バッファキャッシュ以上のブロック数が生成されていればいいので、落とされそうなのが確認できればOK.

SYS@orclcdb>  select ceil((66667 / 2 * 5) - 126976) AS "blocks" from dual;

blocks
----------
39692

Elapsed: 00:00:00.00


とりあえず、生成するデータ量(行数)の算出とバッファキャッシュサイズの調整はおわり。


次に、実際にデータを生成してブロック数とセグメントサイズを確認して、実行用スクリプトの調整を行なっておきます。



PDBでテストデータの実サイズの確認
SCOTT@orcl> @droppurge_create_hoge.sql
1* drop table hoge purge

Table dropped.

Elapsed: 00:00:00.25
1* create table hoge (id number, data varchar2(2000))

Table created.

Elapsed: 00:00:00.04
1* select segment_name,blocks from user_segments where segment_name like '%HOGE%'

no rows selected

Elapsed: 00:00:00.11


500,000行登録!!

SCOTT@orcl> @insert_each_rows_5.sql
1* begin for i in 1..500000 loop insert into hoge values(i, lpad('*', 2000, '*')); end loop; end;

PL/SQL procedure successfully completed.

Elapsed: 00:02:37.68


データが登録されているブロック数は、166,667 blocks で、事前に計算していた 166,668 blocks にほぼおなじ。(狙い通り)
セグメントサイズは、約 1344 MB ですね。

SCOTT@orcl> select count(distinct dbms_rowid.rowid_block_number(rowid)) as "blocks" from hoge;

blocks
----------
166667

Elapsed: 00:00:05.03
SCOTT@orcl> select segment_name,blocks,bytes/1024/1024 AS "MB" from user_segments where segment_name = 'HOGE';

SEGMENT_NAME BLOCKS MB
------------------------------ ---------- ----------
HOGE 172032 1344

Elapsed: 00:00:00.17


Scattered read でTable Full Scanできるように少々隠しパラメータを調整しておきますね。念の為。(セッションレベルで調整してます)
セグメントサイズが、1344 MBなので、_very_large_object_threshold は、2048 MBぐらい設定しておけば、Scattered readのまま行けそうですね。

$ cat table_full_scan.sql
alter session set "_serial_direct_read" = never
.
l
/
alter session set "_very_large_object_threshold" = 2040
.
l
/

!echo set autot trace exp stat
set autot trace exp stat


select * from hoge
.
l
/

!echo set autot off
set autot off


準備完了!!!!!





準備長かったけどw やっと本題です!!!w 実行している内容はいままでと同じなのでかなり端折ってポイントだけ記載。

バッファキャッシュから溢れるほどのデータ量で。コミットクリーンアウトはどうなるのだろうか。。。。想定では、ほぼコミットクリーンアウトできないはずではあるのだが。。。。

CDBのSYSで統計取得(コミット後)

commit cleanouts successfully completedはどれぐらいだったのか。。。。。ありません。commit cleanouts successfully completedに差分がなかったので、コミットクリーンアウトしようして失敗、commit cleanout failures: block lostと同数なので、1ブロックもコミットクリーンアウトできない!  commit cleanout failures: block lostがバッファキャッシュに対象ブロックがなかったことを示しています。

つまり、バッファキャッシュに乗り切らなため、最初にINSERTされたブロックはそのままストレージへ物理書き込みされて追い出された結果。。ということになりますね。

登録したブロック全てが遅延クリーンアウト対象になってしまった、ということになります。コミット時にクリーンアウトできてないわけだから!!!!!!!! (イメージ図でざっくり書いたとおりの感じに。。。

差分のあった統計のみ記載

CDB)システム統計

SOURCE  NAME                                                             VALUE
------- ------------------------------------------------- --------------------
sysstat commit cleanout failures: block lost 3028
sysstat commit cleanouts 3028
sysstat consistent gets 274
sysstat db block changes 1
sysstat no work - consistent read gets 149
sysstat physical reads 60

(PDB) SCOTTのセッション統計

SOURCE  NAME                                                             VALUE
------- ------------------------------------------------- --------------------
sesstat commit cleanout failures: block lost 3028
sesstat commit cleanouts 3028
sesstat db block changes 1


次に、Scattered Readが実行される全表走査を行わせ、遅延ブロッククリーンアウトどれだけ発生するか結果確認!

PDBのSCOTTユーザーで、遅延ブロッククリーンアウト影響有無確認(対象表を全表走査)
想定通り、物理読み込み(この時点ではscattered readなのか、direct path readなのかわかりませんが)になっています。また、大量のREDOログが生成されているので遅延ブロッククリーンアウトが発生しています。

SCOTT@orcl> @table_full_scan.sql
1* alter session set "_serial_direct_read" = never

Session altered.

Elapsed: 00:00:00.00
1* alter session set "_very_large_object_threshold" = 2040

Session altered.

Elapsed: 00:00:00.00
set autot trace exp stat

1* select * from hoge

500000 rows selected.

Elapsed: 00:01:03.08

Execution Plan
----------------------------------------------------------
Plan hash value: 2339479017

--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 669K| 647M| 46462 (1)| 00:00:02 |
| 1 | TABLE ACCESS FULL| HOGE | 669K| 647M| 46462 (1)| 00:00:02 |
--------------------------------------------------------------------------

Note
-----
- dynamic statistics used: dynamic sampling (level=2)

Statistics
----------------------------------------------------------
46 recursive calls
13 db block gets
367852 consistent gets
160269 physical reads
14670268 redo size
1016952118 bytes sent via SQL*Net to client
367706 bytes received via SQL*Net from client
33335 SQL*Net roundtrips to/from client
2 sorts (memory)
0 sorts (disk)
500000 rows processed

set autot off


物理読み込みを伴う全表走査でどの程度の遅延ブロッククリーンアウトが発生したか統計を確認!!!!

CDBのSYSで統計取得(遅延ブロッククリーンアウト有無確認)

想定どおり、INSERTした全ブロックが、immediate (CR) block cleanout applications = 166667 で遅延ブロッククリーンアウトされたことがわかります。(冒頭に記載していますが、データが格納されているブロック数は、 166667 blocks でしたよね)
physical readsは意図通り発生していますが、physical reads directが変化していないので、狙い通りScattered Readになったようですね

差分のあった統計のみ記載

CDB)システム統計

SOURCE  NAME                                                             VALUE
------- ------------------------------------------------- --------------------
sysstat DBWR checkpoint buffers written 241
sysstat DBWR thread checkpoint buffers written 241
sysstat DBWR undo block writes 1109
sysstat cleanouts only - consistent read gets 166667
sysstat commit cleanouts 55
sysstat commit cleanouts successfully completed 55
sysstat consistent gets 377331
sysstat db block changes 166904
sysstat deferred (CURRENT) block cleanout applications 29
sysstat immediate (CR) block cleanout applications 166667
sysstat immediate (CURRENT) block cleanout applications 15
sysstat no work - consistent read gets 38449
sysstat physical reads 160805
sysstat physical writes 137551
sysstat physical writes from cache 137551
sysstat physical writes non checkpoint 137466

(PDB) SCOTTのセッション統計

SOURCE  NAME                                                             VALUE
------- ------------------------------------------------- --------------------
sesstat cleanouts only - consistent read gets 166667
sesstat commit cleanouts 6
sesstat commit cleanouts successfully completed 6
sesstat consistent gets 374538
sesstat db block changes 166710
sesstat deferred (CURRENT) block cleanout applications 3
sesstat immediate (CR) block cleanout applications 166667
sesstat immediate (CURRENT) block cleanout applications 1
sesstat no work - consistent read gets 36779
sesstat physical reads 160513


念の為、今一度、物理読み込みを伴う全表走査を行なって、クリーンアウトされたのか確認してみましょうw(疑い深いw)
もう一度、PDBのSCOTTユーザーで、遅延ブロッククリーンアウト影響有無確認(対象表を全表走査)

redo size0 なのでクリーンアウトは発生してない。想定通り

SCOTT@orcl> @table_full_scan.sql
1* alter session set "_serial_direct_read" = never

Session altered.

Elapsed: 00:00:00.00
1* alter session set "_very_large_object_threshold" = 2040

Session altered.

Elapsed: 00:00:00.00
set autot trace exp stat

1* select * from hoge

500000 rows selected.

Elapsed: 00:00:33.17

Execution Plan
----------------------------------------------------------
Plan hash value: 2339479017

--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 669K| 647M| 46462 (1)| 00:00:02 |
| 1 | TABLE ACCESS FULL| HOGE | 669K| 647M| 46462 (1)| 00:00:02 |
--------------------------------------------------------------------------

Note
-----
- dynamic statistics used: dynamic sampling (level=2)

Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
200399 consistent gets
148198 physical reads
0 redo size
1016952118 bytes sent via SQL*Net to client
367706 bytes received via SQL*Net from client
33335 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
500000 rows processed

set autot off

同様に、統計でも確認してみます!
CDBのSYSで統計取得(遅延ブロッククリーンアウト有無確認)

クリーンアウトを示す統計値は上昇していません!!!(うんうんw)

差分のあった統計のみ記載

CDB)システム統計

SOURCE  NAME                                                             VALUE
------- ------------------------------------------------- --------------------
sysstat DBWR checkpoint buffers written 732
sysstat commit cleanouts 1
sysstat commit cleanouts successfully completed 1
sysstat consistent gets 200522
sysstat db block changes 13
sysstat deferred (CURRENT) block cleanout applications 1
sysstat no work - consistent read gets 200403
sysstat physical reads 148200
sysstat physical writes 68570
sysstat physical writes from cache 68570
sysstat physical writes non checkpoint 68331

(PDB) SCOTTのセッション統計

SOURCE  NAME                                                             VALUE
------- ------------------------------------------------- --------------------
sesstat consistent gets 200414
sesstat db block changes 9
sesstat no work - consistent read gets 200366
sesstat physical reads 148198



OK. Done. ということで、まとめ!

バッファキャッシュには収まりきれないデータ量の場合、コミットクリーンアウトしようとしていたブロックも追い出されてしまうので、結果的に、全ブロックが遅延ブロッククリーンアウトになった。というイメージしていた結果の通りでした。
(今回のケースもシンプルケースなので比較的予想しやすい結果ですが、クリーンアウトに関わる統計は以外に多く、複雑な動きになるものもあります。再現するののめんどくさいのでしませんがw)
Photo_20210911234101

寄り道はここまで、次回は、こんどこそ、direct path readと遅延ブロッククリーンアウトの関係をみていきたいと思います。


来週天気いいかなー。遅い夏休みなのに。微妙な気がしてきた。。。。。



古くて新しい? 遅延ブロッククリーンアウト (deferred block cleanout) #1
古くて新しい? 遅延ブロッククリーンアウト (deferred block cleanout) #2
古くて新しい? 遅延ブロッククリーンアウト (deferred block cleanout) #3
古くて新しい? 遅延ブロッククリーンアウト (deferred block cleanout) #4
古くて新しい? 遅延ブロッククリーンアウト (deferred block cleanout) #5
古くて新しい? 遅延ブロッククリーンアウト (deferred block cleanout) #6
古くて新しい? 遅延ブロッククリーンアウト (deferred block cleanout) #7


|

コメント

コメントを書く