2018年5月 2日 (水)

Oracle Database Connect 2018 エキスパートはどう考えるか? 体感!パフォーマンスチューニング Ⅱ (番外編=没ネタ)

Oracle Database Connect 2018 エキスパートはどう考えるか?体感!パフォーマンスチューニング Ⅱ
~Autonomous Databaseの到来において必要となるチューニングとは~

これ、パフォーマンスチューニングネタをまとめ上げるまで、みなさんスケジュール調整し、
オンライン/オフラインミーティングを繰り返してネタを詰めていくという、かなーり面倒なことをやっています。
私なんて、ネタの候補検討だけで16時間ぐらい使ってますからねw(自分の余暇を使って、半分楽しみながら、締め切りがあるので半分苦しみながらw)


余談はこれくらいにして、今日の本題です。:)

Oracle Database Connect 2018 エキスパートはどう考えるか? 体感!パフォーマンスチューニング Ⅱ で没にしたネタがあるのですが、
そのまま捨てるのも勿体ないので、多少取得情報を追加した状態で公開しちゃおうと思います。


お時間のありますときに、頭の体操、AWRレポートの解析方法(最近はADDM、ASHレポートまで含まれています)のトレーニングにどうぞ。

遅延原因の想定と、想定原因の特定情報は、このエントリでは公開しません。おそらくGW開けの12日あたりか、その一週間後の19日ごろには原因を公開しようかと:)の後半に追記してあります:)

なお、本ページに公開した情報以外に、追加で見たい情報がある場合は、コメント欄やtwのmentionで具体的にリクエストいただければ、取得されている情報の範囲内で追加公開します。取得されてない情報はその旨を追記していきます。:)
まずは、エスパー力全開で、原因を想定してみてください。>
(かなり難易度高めだとは思いますが、過去この状況に遭遇した経験をお持ちのかたは、ここに公開した程度の情報から勘で言い当てたりしちゃうんですよね。実は、昨年末に、何年か振りでこの症状を目にしたのでネタにしよう思いました。)

以下取得された情報は以下のとおり。以下の情報を元に遅延原因を想定してみてください。



なーんでだ?!


状況説明
試験時には問題のなかった処理(30分以内に終了する状態が正常な状態です。)をリリースしました。
ところが、30分以上経過しても終了しません。遅延原因を想定、特定してください。
なお、本番環境のメンテナンス時間中に試験を行ったため、データベースインスタンス内で試験を行いリリースしています。
ちなみに、試験時の処理時間は、約21分でしたが、リリース時は約56分と大幅に遅延。


他のトランザクションが走行している状況をミックスするとより
本物っぽくなり、特定に苦労するので面白いのですが、
遅延している処理だけが走行している状況にしてあります。


資料1 試験時(正常時)AWRレポート
資料2 リリース時(遅延時)AWRレポート
資料3 試験時(正常時)とリリース時(遅延時)のAWR DIFFレポート

資料4 試験時(正常時)CPU利用率グラフ(調査による多少のノイズあり)

1

資料5 リリース時(遅延時)CPU利用率グラグ(スパイク部分調査による多少のノイズあり)

2

GWも後半スタート、天気は少々荒れそうですが、みなさん、よいGWを!



Twitterでのやり取り....
20180506_82405
20180506_82353

ここまでくるとなにかが見えてきたかな。。。原因を特定するまであと一歩な感じ。

追加資料1(遅延時)
top

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
13058 oracle 20 0 10.434g 365704 359548 R 100.0 1.4 1:05.70 oracle_13058_or
5973 oracle 20 0 1955632 253648 73812 S 4.7 1.0 1:42.62 gnome-shell
4657 oracle -2 0 10.417g 58792 55660 S 2.0 0.2 0:12.15 ora_vktm_orcl12
1285 root 20 0 483544 76000 21372 S 1.7 0.3 0:55.11 Xorg
4862 oracle 20 0 10.417g 68960 65868 S 1.3 0.3 0:01.23 ora_lg00_orcl12
223 root 20 0 0 0 0 S 0.7 0.0 0:00.49 kworker/u24:3
13059 oracle 20 0 157976 4564 3544 R 0.7 0.0 0:00.29 top
...略...

追加資料2(遅延時)
sar -P ALL

   ...略...
02:47:29 AM CPU %user %nice %system %iowait %steal %idle
02:47:34 AM all 4.78 0.00 2.36 0.07 0.00 92.80
02:47:34 AM 0 1.06 0.00 1.06 0.85 0.00 97.03
02:47:34 AM 1 0.20 0.00 0.40 0.00 0.00 99.40
02:47:34 AM 2 0.00 0.00 0.00 0.00 0.00 100.00
02:47:34 AM 3 0.00 0.00 0.00 0.00 0.00 100.00
02:47:34 AM 4 0.00 0.00 0.20 0.00 0.00 99.80
02:47:34 AM 5 0.00 0.00 0.00 0.00 0.00 100.00
02:47:34 AM 6 0.00 0.00 0.00 0.00 0.00 100.00
02:47:34 AM 7 68.08 0.00 31.92 0.00 0.00 0.00
02:47:34 AM 8 0.00 0.00 0.00 0.00 0.00 100.00
02:47:34 AM 9 0.00 0.00 0.00 0.00 0.00 100.00
02:47:34 AM 10 0.00 0.00 0.00 0.00 0.00 100.00
02:47:34 AM 11 0.00 0.00 0.20 0.20 0.00 99.60
...略...

追加資料3(遅延時)
perf top -C 7

Samples: 107K of event 'cpu-clock', Event count (approx.): 29550214790                                                              
Overhead Shared Object Symbol
4.36% libc-2.17.so [.] vfprintf
2.77% oracle [.] lxoCpStr
2.00% [kernel] [k] __radix_tree_lookup
1.94% oracle [.] dbgfcsIlcsGetNextDef
1.58% oracle [.] skgovprint
1.48% [kernel] [k] __do_softirq
1.44% [kernel] [k] selinux_file_permission
1.43% oracle [.] dbgaFmtAttrCb_int
1.36% [kernel] [k] system_call_after_swapgs
1.33% oracle [.] dbgaAttrFmtProcArg
1.26% oracle [.] dbgtfmWriteMetadata
1.13% oracle [.] dbgtfdFileWrite
1.02% libc-2.17.so [.] _IO_default_xsputn
...略...



その後のやりとり (Twitter)

20180513_80620

そして核心に迫る追加資料が...あったんです。(しばちょうさん風にはしづらかったw)



正常時(試験時)の追加情報はないようです。リリース後は常に遅いらしい。

ふむふむ。

以下、遅延時のstrace -c -pの情報を取得してもらいました。
straceで眺めるとsystem call write()がダントツで上位にきています。その次が lseek()

追加資料4
strace -c -p

[oracle@localhost ˜]$ sudo strace -c -p 13058
Process 13058 attached
^CProcess 13058 detached
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
77.24 47.883538 1 35085592 write
19.22 11.913638 1 17542850 lseek
3.53 2.191099 1 3414889 getrusage
0.01 0.006377 12 524 semop
0.00 0.000403 7 62 close
0.00 0.000210 4 54 chown
0.00 0.000126 2 63 open
0.00 0.000099 2 54 lstat
0.00 0.000050 1 54 chmod
0.00 0.000029 1 54 stat
0.00 0.000028 3 10 semtimedop
0.00 0.000015 0 54 fcntl
0.00 0.000010 1 8 read
0.00 0.000007 1 8 select
0.00 0.000000 0 3 mmap
0.00 0.000000 0 6 rt_sigprocmask
0.00 0.000000 0 1 rt_sigreturn
0.00 0.000000 0 1 readlink
------ ----------- ----------- --------- --------- ----------------
100.00 61.995629 56044287 total

そろそろ突き止めた感が。

なにかを、どこかに、書き出してますよね。

lsofで書き込みに絞って取得してもった結果は以下のとおり。

[root@localhost ˜]# lsof -p 13058 | grep -E '[0-9]+w'
oracle_13 13058 oracle 1w CHR 1,3 0t0 1038 /dev/null
oracle_13 13058 oracle 2w CHR 1,3 0t0 1038 /dev/null
oracle_13 13058 oracle 7w REG 8,17 2351882843 71176413 /u01/app/oracle/diag/rdbms/orcl12c/orcl12c/trace/orcl12c_ora_13058.trc
oracle_13 13058 oracle 8w REG 8,17 358606101 71176414 /u01/app/oracle/diag/rdbms/orcl12c/orcl12c/trace/orcl12c_ora_13058.trm

ほう。 .trcファイルへ大量の書き込みがあります。

このようになるときは、 なにが起っていると思いますか?

.trcファイルに大量の書き込みのあるケースとして、SQLトレースが有効になっている場合です。(意図したSQLトレースなら問題はないですが...意図していない場合はちょいと問題ですよね。)

ということで、確定診断に移りましょう。

SQL*Plus: Release 12.2.0.1.0 Production on Wed Apr 25 01:23:13 2018

Copyright (c) 1982, 2016, Oracle. All rights reserved.

Connected.
ORCL@SYSTEM>
ORCL@SYSTEM> select username,status,event,sql_trace from v$session where paddr = (select addr from v$process where spid = 13058)

USERNAME STATUS EVENT SQL_TRAC
------------------------------ -------- ---------------------------------------------------------------- --------
SCOTT ACTIVE log file switch completion ENABLED

見ての通り、
SQL_TRACE列がdisabled(デフォルト)からenabledに変わっていることから、.trcファイルへの大量の書き出しは、セッションレベルでSQLトレースが有効化されたため、と言えますよね。


今回の新規リリースバッチ処理遅延の原因は、

SQLトレースを有効化したままリリースしたしまったことにより、オーバーヘッドが発生し、グルグル系バッチ処理のスループットが低下したため! 

ということでした。SQLトレースを利用したあとの無効化をお忘れなく! :)


SQLトレースは便利な機能の一つですが、インスタンスレベルやグルグル系バッチ処理での利用時は大量のトレース情報の書き出し等によるオーバーヘッドが発生します。
便利なツールではありますが、スループットの低下等による影響を考慮して利用するタイプのツールでもあります。
また、利用した後は、必ず、無効化することもお忘れなく...

ミイラ取りがミイラになってしまってはいみないですから.....ね :)

| | コメント (0) | トラックバック (0)

2018年3月18日 (日)

Temp落ち #9 - 自動PGA管理で_pga_max_sizeと戯れたPGAサイズって本当に使えるのか? 12.2.0.1版

Previously on Mac De Oracle

自動PGA管理下で、_pga_max_size隠しパラメータとpga_aggregate_targetを最大値に設定するした場合、global memory boundは
最大で、約839GBまで増加することがわかりました。

ただ、これは、内部的なパラメータ上の話。


今日は、実際にソートやハッシュ結合を行なわせ、PGAのSQL Work Areaサイズがどこまで利用できるものなのか確認してみることにします。

さて、どういう結末になりますやら(w

随分前から同じようなことを試している方はいますし....:)

なぜ今そこをdiggingしちゃってるのか? って?

メモリーたっぷりあるのに、何故Temp落ち? が話題になったからに決まってるじゃないですかw

まず、デフォルト設定では最大サイズだった 1GB を超えられるか? の確認

注意)
事前にpga_aggregate_target および _pga_max_size をそれぞれ 4TB - 1に設定し、パラメータの上では、global memory boundが約839GBにしてあります。

なお、Temp落ちの確認データやスクリプトはTemp落ち #4 - 手動PGA管理で作業領域として指定可能な最大サイズ de Temp落ちの確認のエントリーを参照のこと。

ソートやハッシュ結合は2GB程度になるように調整しています。
2GBのソート

ORCL@SCOTT> @auto_sortwk2gb_optimal.sql

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
workarea_size_policy string AUTO

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
pga_aggregate_target big integer 4398046511103

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
_pga_max_size big integer 4398046511103

NAME VALUE UNIT CON_ID
---------------------------------------------------------------- ---------------- ------------ ----------
global memory bound 879609302016 bytes 0

1 SELECT
2 /*+
3 MONITOR
4 */
5 *
6 FROM
7 m1
8 WHERE
9 id <= 'C750000'
10 ORDER BY
11 id
12* ,rev#
old 1: select dbms_sqltune.report_sql_monitor(sql_id=>'&1', type=>'text') from dual
new 1: select dbms_sqltune.report_sql_monitor(sql_id=>'', type=>'text') from dual

DBMS_SQLTUNE.REPORT_SQL_MONITOR(SQL_ID=>'',TYPE=>'TEXT')
------------------------------------------------------------------------------------------
SQL Monitoring Report

・・・中略・・・

SQL Plan Monitoring Details (Plan Hash Value=3534657201)
========================================================================================================================================================
| Id | Operation | Name | Rows | Cost | Time | Start | Execs | Rows | Read | Read | Mem | Activity | Activity Detail |
| | | | (Estim) | | Active(s) | Active | | (Actual) | Reqs | Bytes | (Max) | (%) | (# samples) |
========================================================================================================================================================
| 0 | SELECT STATEMENT | | | | 34 | +2 | 1 | 1M | | | . | 5.26 | Cpu (1) |
| 1 | SORT ORDER BY | | 1M | 553K | 34 | +2 | 1 | 1M | | | 2GB | 26.32 | Cpu (5) |
| 2 | TABLE ACCESS FULL | M1 | 1M | 90829 | 17 | +1 | 1 | 1M | 2637 | 3GB | . | 68.42 | Cpu (3) |
| | | | | | | | | | | | | | direct path read (10) |
========================================================================================================================================================


2GBのハッシュ結合

ORCL@SCOTT> @auto_hashwk2gb_optimal.sql

・・・中略・・・

NAME VALUE UNIT CON_ID
---------------------------------------------------------------- ------------- ------------ ----------
global memory bound 879609302016 bytes 0

1 SELECT
2 /*+
3 MONITOR
4 LEADING(m1 m2)
5 USE_HASH(m1 m2)
6 */
7 *
8 FROM
9 m1
10 INNER JOIN m2
11 ON
12 m1.id = m2.id
13 AND m1.rev# = m2.rev#
14 WHERE
15* m1.id <= 'C084000'
old 1: select dbms_sqltune.report_sql_monitor(sql_id=>'&1', type=>'text') from dual
new 1: select dbms_sqltune.report_sql_monitor(sql_id=>'', type=>'text') from dual

DBMS_SQLTUNE.REPORT_SQL_MONITOR(SQL_ID=>'',TYPE=>'TEXT')
------------------------------------------------------------------------------------------
SQL Monitoring Report

・・・中略・・・

SQL Plan Monitoring Details (Plan Hash Value=1822065247)
===========================================================================================================================================================
| Id | Operation | Name | Rows | Cost | Time | Start | Execs | Rows | Read | Read | Mem | Activity | Activity Detail |
| | | | (Estim) | | Active(s) | Active | | (Actual) | Reqs | Bytes | (Max) | (%) | (# samples) |
===========================================================================================================================================================
| 0 | SELECT STATEMENT | | | | 37 | +2 | 1 | 840K | | | . | 4.35 | Cpu (1) |
| 1 | HASH JOIN | | 843K | 351K | 37 | +2 | 1 | 840K | | | 2GB | 26.09 | Cpu (5) |
| | | | | | | | | | | | | | PGA memory operation (1) |
| 2 | TABLE ACCESS FULL | M1 | 843K | 90828 | 15 | +1 | 1 | 840K | 2633 | 3GB | . | 52.17 | Cpu (1) |
| | | | | | | | | | | | | | direct path read (11) |
| 3 | TABLE ACCESS FULL | M2 | 846K | 90581 | 23 | +16 | 1 | 840K | 2619 | 3GB | . | 17.39 | Cpu (2) |
| | | | | | | | | | | | | | direct path read (2) |
===========================================================================================================================================================


ソートやハッシュ結合は4GB程度になるように調整しています。
見ての通り、ソートは4GBのメモリー内ソートですが、ハッシュ結合は、2GBまで使ったところで Temp落ち! (こんなもんなんですよ。実は!)
4GBのソート

ORCL@SCOTT> @auto_sortwk4gb_optimal.sql

・・・中略・・・

NAME VALUE UNIT CON_ID
---------------------------------------------------------------- ------------- ------------ ----------
global memory bound 879609302016 bytes 0

1 SELECT
2 /*+
3 MONITOR
4 */
5 *
6 FROM
7 m1
8 WHERE
9 id <= 'C085000'
10 UNION ALL
11 SELECT *
12 FROM
13 m1 m12
14 WHERE
15 id <= 'C085000'
16 ORDER BY
17* 1, 2
old 1: select dbms_sqltune.report_sql_monitor(sql_id=>'&1', type=>'text') from dual
new 1: select dbms_sqltune.report_sql_monitor(sql_id=>'', type=>'text') from dual

DBMS_SQLTUNE.REPORT_SQL_MONITOR(SQL_ID=>'',TYPE=>'TEXT')
-----------------------------------------------------------------------------------------
SQL Monitoring Report

・・・中略・・・

SQL Plan Monitoring Details (Plan Hash Value=2686238998)
============================================================================================================================================================
| Id | Operation | Name | Rows | Cost | Time | Start | Execs | Rows | Read | Read | Mem | Activity | Activity Detail |
| | | | (Estim) | | Active(s) | Active | | (Actual) | Reqs | Bytes | (Max) | (%) | (# samples) |
============================================================================================================================================================
| 0 | SELECT STATEMENT | | | | 40 | +2 | 1 | 2M | | | . | 27.78 | Cpu (5) |
| 1 | SORT ORDER BY | | 2M | 182K | 41 | +1 | 1 | 2M | | | 4GB | 38.89 | Cpu (6) |
| | | | | | | | | | | | | | PGA memory operation (1) |
| 2 | UNION-ALL | | | | 12 | +2 | 1 | 2M | | | . | | |
| 3 | TABLE ACCESS FULL | M1 | 855K | 90828 | 6 | +2 | 1 | 850K | 2633 | 3GB | . | 22.22 | Cpu (2) |
| | | | | | | | | | | | | | direct path read (2) |
| 4 | TABLE ACCESS FULL | M1 | 855K | 90828 | 6 | +8 | 1 | 850K | 2633 | 3GB | . | 11.11 | Cpu (2) |
============================================================================================================================================================


4GBのハッシュ結合
最大3GBのPGAが消費されていますが、Temp落ちしないサイズ、つまり、optimalで処理する場合には、最大2GBが最大サイズとなっています。以下を3GBのハッシュ結合にすると、2GBまでPGAを消費し、一時表領域が3GB利用されます。

ORCL@SCOTT> @auto_hashwk4gb_optimal.sql
old 1: select dbms_sqltune.report_sql_monitor(sql_id=>'&1', type=>'text') from dual
new 1: select dbms_sqltune.report_sql_monitor(sql_id=>'', type=>'text') from dual

DBMS_SQLTUNE.REPORT_SQL_MONITOR(SQL_ID=>'',TYPE=>'TEXT')
------------------------------------------------------------------------------------------
SQL Monitoring Report

・・・中略・・・

SQL Plan Monitoring Details (Plan Hash Value=3532417599)
=========================================================================================================================================================================================
| Id | Operation | Name | Rows | Cost | Time | Start | Execs | Rows | Read | Read | Write | Write | Mem | Temp | Activity | Activity Detail |
| | | | (Estim) | | Active(s) | Active | | (Actual) | Reqs | Bytes | Reqs | Bytes | (Max) | (Max) | (%) | (# samples) |
=========================================================================================================================================================================================
| 0 | SELECT STATEMENT | | | | 216 | +2 | 1 | 3M | | | | | . | . | 4.49 | Cpu (7) |
| 1 | HASH JOIN | | 2M | 670K | 217 | +1 | 1 | 3M | 18091 | 4GB | 18091 | 4GB | 3GB | 4GB | 79.49 | Cpu (87) |
| | | | | | | | | | | | | | | | | direct path read temp (19) |
| | | | | | | | | | | | | | | | | direct path write temp (18) |
| 2 | VIEW | | 2M | 182K | 9 | +2 | 1 | 2M | | | | | . | . | | |
| 3 | UNION-ALL | | | | 9 | +2 | 1 | 2M | | | | | . | . | | |
| 4 | TABLE ACCESS FULL | M1 | 752K | 90828 | 5 | +2 | 1 | 750K | 2633 | 3GB | | | . | . | 1.92 | Cpu (3) |
| 5 | TABLE ACCESS FULL | M1 | 752K | 90828 | 4 | +7 | 1 | 750K | 2633 | 3GB | | | . | . | 1.92 | Cpu (3) |
| 6 | VIEW | | 2M | 181K | 78 | +99 | 1 | 2M | | | | | . | . | 0.64 | Cpu (1) |
| 7 | UNION-ALL | | | | 78 | +99 | 1 | 2M | | | | | . | . | | |
| 8 | TABLE ACCESS FULL | M2 | 759K | 90581 | 50 | +92 | 1 | 750K | 2618 | 3GB | | | . | . | 9.62 | Cpu (2) |
| | | | | | | | | | | | | | | | | direct path read (13) |
| 9 | TABLE ACCESS FULL | M2 | 759K | 90581 | 36 | +141 | 1 | 750K | 2618 | 3GB | | | . | . | 1.92 | Cpu (2) |
| | | | | | | | | | | | | | | | | direct path read (1) |
=========================================================================================================================================================================================


では、最後に
ソートやハッシュ結合のサイズが8GB程度ならどうでしょうか?
結果は、ソートは4GBを使い切ったのち、Temp落ち、ハッシュ結合は、やはり、3GBまで利用したのちTemp落ちでした。なんと!(ちょっとわざとらしいリアクションしてすみませんw)

8GBのソート

ORCL@SCOTT> @auto_sortwk8gb_optimal.sql

・・・中略・・・

NAME VALUE UNIT CON_ID
---------------------------------------------------------------- ------------- ------------ ----------
global memory bound 879609302016 bytes 0

1 SELECT
2 /*+
3 MONITOR
4 */
5 *
6 FROM
7 m1
8 WHERE
9 id <= 'C090000'
10 UNION ALL
11 SELECT *
12 FROM
13 m1 m12
14 WHERE
15 id <= 'C090000'
16 UNION ALL
17 SELECT *
18 FROM
19 m1 m13
20 WHERE
21 id <= 'C090000'
22 UNION ALL
23 SELECT *
24 FROM
25 m1 m14
26 WHERE
27 id <= 'C090000'
28 ORDER BY
29* 1, 2
old 1: select dbms_sqltune.report_sql_monitor(sql_id=>'&1', type=>'text') from dual
new 1: select dbms_sqltune.report_sql_monitor(sql_id=>'', type=>'text') from dual

DBMS_SQLTUNE.REPORT_SQL_MONITOR(SQL_ID=>'',TYPE=>'TEXT')
------------------------------------------------------------------------------------------
SQL Monitoring Report

・・・中略・・・

SQL Plan Monitoring Details (Plan Hash Value=946172832)
=========================================================================================================================================================================================
| Id | Operation | Name | Rows | Cost | Time | Start | Execs | Rows | Read | Read | Write | Write | Mem | Temp | Activity | Activity Detail |
| | | | (Estim) | | Active(s) | Active | | (Actual) | Reqs | Bytes | Reqs | Bytes | (Max) | (Max) | (%) | (# samples) |
=========================================================================================================================================================================================
| 0 | SELECT STATEMENT | | | | 279 | +2 | 1 | 4M | | | | | . | . | 5.79 | Cpu (6) |
| | | | | | | | | | | | | | | | | PGA memory operation (1) |
| | | | | | | | | | | | | | | | | local write wait (7) |
| 1 | SORT ORDER BY | | 4M | 363K | 279 | +2 | 1 | 4M | 38603 | 8GB | 32072 | 8GB | 4GB | 8GB | 84.30 | Cpu (49) |
| | | | | | | | | | | | | | | | | PGA memory operation (1) |
| | | | | | | | | | | | | | | | | direct path read temp (28) |
| | | | | | | | | | | | | | | | | direct path write temp (126) |
| 2 | UNION-ALL | | | | 176 | +2 | 1 | 4M | | | | | . | . | | |
| 3 | TABLE ACCESS FULL | M1 | 907K | 90828 | 16 | +1 | 1 | 900K | 2633 | 3GB | | | . | . | 4.55 | Cpu (2) |
| | | | | | | | | | | | | | | | | direct path read (9) |
| 4 | TABLE ACCESS FULL | M1 | 907K | 90828 | 8 | +17 | 1 | 900K | 2633 | 3GB | | | . | . | 2.48 | Cpu (5) |
| | | | | | | | | | | | | | | | | direct path read (1) |
| 5 | TABLE ACCESS FULL | M1 | 907K | 90828 | 79 | +26 | 1 | 900K | 2633 | 3GB | | | . | . | 2.48 | Cpu (2) |
| | | | | | | | | | | | | | | | | direct path read (4) |
| 6 | TABLE ACCESS FULL | M1 | 907K | 90828 | 72 | +106 | 1 | 900K | 2633 | 3GB | | | . | . | 0.41 | Cpu (1) |
=========================================================================================================================================================================================

8GBのハッシュ結合

ORCL@SCOTT> @auto_hashwk8gb_optimal.sql

・・・中略・・・

NAME VALUE UNIT CON_ID
---------------------------------------------------------------- ------------- ------------ ----------
global memory bound 879609302016 bytes 0

1 SELECT
2 /*+
3 MONITOR
4 LEADING(m1 m2)
5 USE_HASH(m1 m2)
6 */
7 *
8 FROM
9 (
10 SELECT * FROM m1 m11
11 UNION ALL
12 SELECT * FROM m1 m12
13 UNION ALL
14 SELECT * FROM m1 m13
15 ) m1
16 INNER JOIN
17 (
18 SELECT * FROM m2 m21
19 UNION ALL
20 SELECT * FROM m2 m22
21 UNION ALL
22 SELECT * FROM m2 m23
23 ) m2
24 ON
25 m1.id = m2.id
26 AND m1.rev# = m2.rev#
27 WHERE
28* m1.id <= 'C075000'
old 1: select dbms_sqltune.report_sql_monitor(sql_id=>'&1', type=>'text') from dual
new 1: select dbms_sqltune.report_sql_monitor(sql_id=>'', type=>'text') from dual

DBMS_SQLTUNE.REPORT_SQL_MONITOR(SQL_ID=>'',TYPE=>'TEXT')
------------------------------------------------------------------------------------------
SQL Monitoring Report

・・・中略・・・

SQL Plan Monitoring Details (Plan Hash Value=2506347387)
=========================================================================================================================================================================================
| Id | Operation | Name | Rows | Cost | Time | Start | Execs | Rows | Read | Read | Write | Write | Mem | Temp | Activity | Activity Detail |
| | | | (Estim) | | Active(s) | Active | | (Actual) | Reqs | Bytes | Reqs | Bytes | (Max) | (Max) | (%) | (# samples) |
=========================================================================================================================================================================================
| 0 | SELECT STATEMENT | | | | 350 | +2 | 1 | 7M | | | | | . | . | 9.18 | Cpu (18) |
| | | | | | | | | | | | | | | | | PGA memory operation (1) |
| 1 | HASH JOIN | | 5M | 1M | 350 | +2 | 1 | 7M | 31032 | 7GB | 31032 | 7GB | 3GB | 8GB | 67.15 | Cpu (81) |
| | | | | | | | | | | | | | | | | direct path read temp (36) |
| | | | | | | | | | | | | | | | | direct path write temp (22) |
| 2 | VIEW | | 2M | 272K | 27 | +2 | 1 | 2M | | | | | . | . | | |
| 3 | UNION-ALL | | | | 27 | +2 | 1 | 2M | | | | | . | . | 0.97 | Cpu (2) |
| 4 | TABLE ACCESS FULL | M1 | 752K | 90828 | 16 | +1 | 1 | 750K | 2633 | 3GB | | | . | . | 7.25 | Cpu (3) |
| | | | | | | | | | | | | | | | | direct path read (12) |
| 5 | TABLE ACCESS FULL | M1 | 752K | 90828 | 5 | +18 | 1 | 750K | 2633 | 3GB | | | . | . | 1.45 | Cpu (2) |
| | | | | | | | | | | | | | | | | direct path read (1) |
| 6 | TABLE ACCESS FULL | M1 | 752K | 90828 | 7 | +23 | 1 | 750K | 2633 | 3GB | | | . | . | 1.93 | Cpu (2) |
| | | | | | | | | | | | | | | | | direct path read (2) |
| 7 | VIEW | | 2M | 272K | 130 | +97 | 1 | 2M | | | | | . | . | | |
| 8 | UNION-ALL | | | | 130 | +97 | 1 | 2M | | | | | . | . | 0.48 | Cpu (1) |
| 9 | TABLE ACCESS FULL | M2 | 759K | 90581 | 47 | +88 | 1 | 750K | 2618 | 3GB | | | . | . | 4.83 | Cpu (3) |
| | | | | | | | | | | | | | | | | direct path read (7) |
| 10 | TABLE ACCESS FULL | M2 | 759K | 90581 | 41 | +134 | 1 | 750K | 2618 | 3GB | | | . | . | 4.35 | Cpu (5) |
| | | | | | | | | | | | | | | | | direct path read (4) |
| 11 | TABLE ACCESS FULL | M2 | 759K | 90581 | 53 | +174 | 1 | 750K | 2618 | 3GB | | | . | . | 2.42 | Cpu (1) |
| | | | | | | | | | | | | | | | | direct path read (4) |
=========================================================================================================================================================================================


これ、Linuxのカーネルパラメータのvm.max_map_count

/proc/sys/vm/max_map_count

65530

が絡んでるよねという話と、隠しパラメータの realfree_heap関連のパラメータでも調整できそうだよね。という話はあるんですが...それはPL/SQLのはなし...で


_realfree_heap_pagesize 65536 TRUE
_use_realfree_heap TRUE TRUE

とりあえず、
vm/max_map_countを196608

にして
_realfree_heap_pagesize=65536 や
_realfree_heap_pagesize=256K

などとして戯れてみましたが

ソートやハッシュ結合で利用可能なサイズは、それらで制御できるものでもありません。いまのところ。

ORCL@SCOTT> @auto_sortwk8gb_optimal.sql

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
workarea_size_policy string AUTO

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
pga_aggregate_target big integer 4398046511103

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
_pga_max_size big integer 4398046511103

NAME VALUE UNIT CON_ID
---------------------------------------------------------------- ------------- ------------ ----------
global memory bound 879609302016 bytes 0

/proc/sys/vm/max_map_count
196608

1 SELECT
2 /*+
3 MONITOR
4 */
5 *
6 FROM
7 m1
8 WHERE
9 id <= 'C090000'
10 UNION ALL
11 SELECT *
12 FROM
13 m1 m12
14 WHERE
15 id <= 'C090000'
16 UNION ALL
17 SELECT *
18 FROM
19 m1 m13
20 WHERE
21 id <= 'C090000'
22 UNION ALL
23 SELECT *
24 FROM
25 m1 m14
26 WHERE
27 id <= 'C090000'
28 ORDER BY
29* 1, 2
old 1: select dbms_sqltune.report_sql_monitor(sql_id=>'&1', type=>'text') from dual
new 1: select dbms_sqltune.report_sql_monitor(sql_id=>'', type=>'text') from dual

DBMS_SQLTUNE.REPORT_SQL_MONITOR(SQL_ID=>'',TYPE=>'TEXT')
------------------------------------------------------------------------------------------
SQL Monitoring Report

・・・中略・・・

SQL Plan Monitoring Details (Plan Hash Value=946172832)
=========================================================================================================================================================================================
| Id | Operation | Name | Rows | Cost | Time | Start | Execs | Rows | Read | Read | Write | Write | Mem | Temp | Activity | Activity Detail |
| | | | (Estim) | | Active(s) | Active | | (Actual) | Reqs | Bytes | Reqs | Bytes | (Max) | (Max) | (%) | (# samples) |
=========================================================================================================================================================================================
| 0 | SELECT STATEMENT | | | | 295 | +2 | 1 | 4M | | | | | . | . | 3.38 | Cpu (8) |
| 1 | SORT ORDER BY | | 4M | 363K | 297 | +1 | 1 | 4M | 38603 | 8GB | 38600 | 8GB | 4GB | 8GB | 91.56 | Cpu (43) |
| | | | | | | | | | | | | | | | | direct path read temp (12) |
| | | | | | | | | | | | | | | | | direct path write temp (162) |
| 2 | UNION-ALL | | | | 205 | +2 | 1 | 4M | | | | | . | . | 0.84 | Cpu (2) |
| 3 | TABLE ACCESS FULL | M1 | 907K | 90828 | 6 | +2 | 1 | 900K | 2633 | 3GB | | | . | . | 2.11 | Cpu (1) |
| | | | | | | | | | | | | | | | | direct path read (4) |
| 4 | TABLE ACCESS FULL | M1 | 907K | 90828 | 7 | +8 | 1 | 900K | 2633 | 3GB | | | . | . | 0.42 | Cpu (1) |
| 5 | TABLE ACCESS FULL | M1 | 907K | 90828 | 100 | +14 | 1 | 900K | 2633 | 3GB | | | . | . | 0.84 | Cpu (2) |
| 6 | TABLE ACCESS FULL | M1 | 907K | 90828 | 94 | +113 | 1 | 900K | 2633 | 3GB | | | . | . | 0.84 | Cpu (2) |
=========================================================================================================================================================================================


ちなみに、PL/SQLで巨大なPGAメモリーを利用する場合は、しっかり9GBとか...やばい状態になったら、pga_aggregate_limitで抑えてくれると思いますが.....

[oracle@localhost ˜]$ ulimit -v -m
virtual memory (kbytes, -v) unlimited
max memory size (kbytes, -m) unlimited

orcl12c@SYS> @show_param

KSPPINM KSPPSTVL KSPPSTDF
---------------------------------------------- ------------------------------ ------------------------------
_pga_max_size 4398046511103 FALSE
_realfree_heap_pagesize 65536 TRUE
_use_realfree_heap TRUE TRUE
pga_aggregate_limit 0 FALSE
pga_aggregate_target 4398046511103 FALSE


/proc/sys/vm/max_map_count
65530

PGAを大量に消費するスクリプトは以下のブログを参考に
Max PGA Research: Check that a process can allocate a large volume of memory / Yury's Blog


ORCL@SCOTT> @plsql_pga8gb 8192
old 2: c_count number := 1024*&1;
new 2: c_count number := 1024*8192;

PL/SQL procedure successfully completed.

実際に確保されたPGAサイズなど。。。

ORCL@SCOTT> r
1 select
2 vss.value/1024/1024/1024 "GB"
3 ,vsn.name
4 ,vss.sid
5 from
6 v$sesstat vss
7 inner join v$statname vsn
8 on
9 vss.statistic# = vsn.statistic#
10 and vss.con_id = vsn.con_id
11 and (vsn.name like '%pga%' or vsn.name like '%uga%')
12 where
13 sid IN (select sid from v$session where username='SCOTT')
14 order by
15* sid,name

GB NAME SID
---------- ---------------------------------------------------------------- ----------
9.49698084 session pga memory 321
9.49698084 session pga memory max 321
1.48221001 session uga memory 321
3.99991362 session uga memory max 321

[oracle@localhost ˜]$ free -h
total used free shared buff/cache available
Mem: 22G 1.0G 9.6G 11G 11G 10G
Swap: 4.0G 8.7M 4.0G

・・・中略・・・

[oracle@localhost ˜]$ free -h
total used free shared buff/cache available
Mem: 22G 10G 128M 11G 11G 705M
Swap: 4.0G 8.8M 4.0G


ここまでくればおわかりだと思いますが、global memory bound (約839GB)からは巨大なPGAサイズになりそうに思えますが、Temp落ちせずにソート可能なサイズは、隠しパラメータを調整した場合でも最大4GB、ハッシュ結合は、2GBが上限、となっています。いまのところ。。。。

ということは、2014年の以下のプレゼンでも話題になっていましたよね。:)
Overcome Oracle PGA Memory Limits Mar.5.2014 Alex Fatkulin / Enkatic

だったら、どのようにして、Temp落ち に立ち向かえばいいんだろう.....次回へ続く :)




10gR2(64bit)のころのままなので、以下のシリーズも合わせて読んでおくといいですよ:)

Mac De Oracle なんですが、Windows(32bit)でのOracleな話
Mac De Oracle なんですが、Windows(32bit)でのOracleな話 #2
Mac De Oracle なんですが、Windows(32bit)でのOracleな話 #3
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #1
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #2
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #3
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #4
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #5
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #6
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #7
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #8
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #9
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #10
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #11
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #12
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #13
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #14
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #15
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #16
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #17
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #18
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #19
_pga_max_sizeってOracle11gではどうなったっけ? という確認。
_pga_max_sizeってOracle11gではどうなったっけ? という確認。シーズン2
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? Season2 #1
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? Season2 #2
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? Season2 #3
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? Season2 #4
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? Season2 #5
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? Season2 #6
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? Season2 #7
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? Season2 #8


Temp落ち #1 - "Temp落ち" って?
Temp落ち #2 - PGA (Program Global Area)
Temp落ち #3 - 手動PGA管理で作業領域として指定可能な最大サイズ
Temp落ち #4 - 手動PGA管理で作業領域として指定可能な最大サイズ de Temp落ちの確認
Temp落ち #5 - pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? 12.2.0.1版 (その前に少し脱線)
Temp落ち #6 - pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? 12.2.0.1版
Temp落ち #7 - 自動PGA管理で到達可能な最大サイズ de Temp落ちの確認 12.2.0.1版
Temp落ち #8 - 自動PGA管理でパラメータ上設定可能な最大サイズは?(実際に利用可能なサイズとは限りませんが。意味深) 12.2.0.1版

| | コメント (0) | トラックバック (0)

2018年3月12日 (月)

Temp落ち #8 - 自動PGA管理でパラメータ上設定可能な最大サイズは?(実際に利用可能なサイズとは限りませんが。意味深) 12.2.0.1版

Previously on Mac De Oracle

自動PGA管理下では、SQL Work Areaサイズは、pga_aggregate_targetのサイズに応じて変化し、最大1GBまで調整され、それのサイズ以上のソートやハッシュ結合は、もれなく、"Temp落ち" する。
手動PGA管理下では、最大2GBまで指定できました。。自動だと1GBまでなのか。。。と残念がる声が、昔は海だった方面から聞こえた気がしましたが、たぶん、気のせいw

というところまででした。


今日は、自動PGA管理下ではそれが最大なのか? のか? 自己責任で試してみることにしますw

まずはこれまでの復習。

自動PGA管理で、SQL Work Areaサイズの算出に関わるパラメータは以下の通り

pga_aggregate_target = 10MB 〜 4TB - 1
_pga_max_size = 200MB 〜 2GB
Oracleが動的に値を調整している_pga_max_sizeパラメータへユーザーが値を設定してしまうとOracleの自動調整が無効化され、設定した値で固定されてしまうので注意が必要です。

私の観測範囲だとおおよそ以下のように変化します。最近は大量のメモリーを搭載したサーバーが多いので、pga_aggregate_targetが10GB以上という状況も普通になってきたので、自動PGA管理下のSQL Work Areaサイズは最大1GBとざっくり丸暗記しても困ることは思いますw(ちょっと乱暴かw)

pga_aggregate_target = 10MB〜10GB - 1 :
_pga_max_size = 200MB 〜 2047MB
GREATEST(pga_aggregate_target*0.2 ,200MB)

pga_aggregate_target = 10GB以上〜4TB-1 :
_pga_max_size = 2GB
LEAST(pga_aggregate_target*0.2 ,2GB)


_pga_max_sizeはpga_aggregate_targetの値に応じて動的に変化し、それらを元に _smm_max_size が算出される
LEAST(pga_aggregate_target * 0.2, _pga_max_size * 0.5)

pga_aggregate_target = 10MB〜10GB-1
_pga_max_size = 200MB〜2047MB
_smm_max_size = 2MB〜1023MB


pga_aggregate_target = 10GB〜4TB-1
_pga_max_size = 2048MB
_smm_max_size = 1024MB
_smm_max_sizeは、v$pgastatのglobal memory boundだろうということは確からしいということまでは確認しました。

20180307_143308
20180307_143330
いままでの結果をまとめると
PGAのSQL Work Areaサイズの最大サイズを示す global memory boundは、pga_aggregate_targetが10MB〜10GB-1までは2MB〜1023MBで調整され、pga_aggregate_targetが10GB〜4TB-1では、1024MB (1GB) で固定されている、というのが、Oracle 10GR2〜12cR2まで動きであることは間違いなさそう:)

自動PGA管理下でSQL Work Areaを1GBを超えるサイズにするにはどのパラメータをどのような値に設定すればよいか。。。
その鍵を握るパラメータは

_pga_max_size

(いまいちピンとこないという方は、過去のエントリーを参照していただけるとスッキリすると思います。

ただ、冒頭にも書きましたが(昔それでハマったw)、(Oracleが動的に値を調整している_pga_max_sizeパラメータへユーザーが値を設定してしまうとOracleの自動調整が無効化され、設定した値で固定されてしまうので注意が必要です。
という点はお忘れなく。また、今後も同仕様のままである保証はなく、世界中のOracle使いの方達が調べ上げた結果、現状はこんな感じ。
という状況だと認識しておいたほうが無難だと思っています。

とはいえ、実際どこまで設定可能なのか?  1GBを以上使えるのか? 知りたいですよね...

長い前置きはこれぐらいにして、
実際にSQL Work Areaサイズに対応したメモリーが実際にどの程度割り当てられるのかということの確認は後回しですが、 パラメータの上では、どこまで設定できるのかというところを確認しました。


なお、
以下のエラーメッセージから、_pga_max_sizeに設定可能な値は、pga_aggregate_targetと同様(Big Integer)、10MB〜4TB-1までであると思われます。

orcl12c@SYS> show parameter _pga_max_size

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
_pga_max_size big integer 2G

orcl12c@SYS> alter system set "_pga_max_size" = 4T scope=memory;
alter system set "_pga_max_size" = 4T scope=memory
*
行1でエラーが発生しました。:
ORA-02097: 指定した値が無効なので、パラメータを変更できません。 ORA-00093:
_pga_max_sizeは、10Mから4096G-1の間に設定する必要があります。

ということで、
_pga_max_sizeを1GB/10GB/100GB/1TB/4T-1のそれぞれに設定したうえで、Temp落ち #6 - pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? 12.2.0.1版 で利用したスクリプトを利用し、global memory boundやその他パラメータの変化を確認しました。

ログの例

orcl12c@SYS> alter system set "_pga_max_size" = 10m scope=both;

システムが変更されました。

orcl12c@SYS> show parameter _pga_max_size

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
_pga_max_size big integer 10m


orcl12c@SYS> @dotest_auto_workarea
<< 10m >>
接続されました。
1* alter system set pga_aggregate_target=&1 scope=spfile
旧 1: alter system set pga_aggregate_target=&1 scope=spfile
新 1: alter system set pga_aggregate_target=10m scope=spfile

システムが変更されました。

データベースがクローズされました。
データベースがディスマウントされました。
ORACLEインスタンスがシャットダウンされました。
ORACLEインスタンスが起動しました。

Total System Global Area 2147483648 bytes
Fixed Size 8794848 bytes
Variable Size 603983136 bytes
Database Buffers 1526726656 bytes
Redo Buffers 7979008 bytes
データベースがマウントされました。
データベースがオープンされました。
+++ initial parameters +++

KSPPINM KSPPSTVL KSPPSTDF
---------------------------------------------- ------------------------------ ------------------------------
__pga_aggregate_target 16777216 FALSE

・・・中略・・・

pga_aggregate_limit 0 FALSE
pga_aggregate_target 10485760 FALSE

50行が選択されました。

/proc/sys/vm/max_map_count

65530

+++ v$pgastat +++

NAME VALUE UNIT CON_ID
---------------------------------------------------------------- ---------- ------------ ----------
aggregate PGA target parameter 10 MB 0
aggregate PGA auto target 4 MB 0
global memory bound 2 MB 0

・・・中略・・・


結果は以下のグラフと表にまとめたとおり。
_pga_max_size=4TB-1、pga_aggregate_target=4TB-1の時のglobal memory bound (v$pgastat) = _smm_max_size が最大となり、約839GBとなることがわかりました。
パラメータ上は839GB程度まで増加しますが、ほんとうにPGAがそんなサイズまで利用可能なのでしょうか?....(怪しいです。答え、知ってるんですけどねw。。

1g
10g
100g
1t
4t1
Globalmemorybound

ということで、

次回は実際に、そんなに使えんのかよ! という実験をしてみたいと思います :)

つづく。




10gR2(64bit)のころのままなので、以下のシリーズも合わせて読んでおくといいですよ:)
Mac De Oracle なんですが、Windows(32bit)でのOracleな話
Mac De Oracle なんですが、Windows(32bit)でのOracleな話 #2
Mac De Oracle なんですが、Windows(32bit)でのOracleな話 #3
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #1
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #2
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #3
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #4
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #5
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #6
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #7
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #8
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #9
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #10
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #11
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #12
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #13
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #14
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #15
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #16
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #17
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #18
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #19
_pga_max_sizeってOracle11gではどうなったっけ? という確認。
_pga_max_sizeってOracle11gではどうなったっけ? という確認。シーズン2
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? Season2 #1
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? Season2 #2
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? Season2 #3
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? Season2 #4
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? Season2 #5
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? Season2 #6
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? Season2 #7
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? Season2 #8


Temp落ち #1 - "Temp落ち" って?
Temp落ち #2 - PGA (Program Global Area)
Temp落ち #3 - 手動PGA管理で作業領域として指定可能な最大サイズ
Temp落ち #4 - 手動PGA管理で作業領域として指定可能な最大サイズ de Temp落ちの確認
Temp落ち #5 - pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? 12.2.0.1版 (その前に少し脱線)
Temp落ち #6 - pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? 12.2.0.1版
Temp落ち #7 - 自動PGA管理で到達可能な最大サイズ de Temp落ちの確認 12.2.0.1版


| | コメント (0) | トラックバック (0)

2018年3月 8日 (木)

Temp落ち #7 - 自動PGA管理で到達可能な最大サイズ de Temp落ちの確認 12.2.0.1版

Previously on Mac De Oracle

自動PGA管理で利用可能なSQL Work Areaサイズはいくつなのか?の確認でした。
これまで同様、隠しパラメータ等の変更をしないデフォルトの設定では最大1GBまで到達することを確認しました。
また、手動PGA管理で利用可能な最大サイズより小さいことも再確認しました。


今日は自動PGA管理下ではオンメモリーで処理可能なサイズは1GBまでなのか、それを超えた場合はもれなく "Temp落ち" なのか確認することにします。

確認用データおよび方法は前々回のエントリーを参照ください。


自動PGA管理でGlobal Memory Bound = 1GB(自動PGA管理での最大 Sort作業領域サイズ)


メモリーソートで1GBぐらいまで利用していることが確認できます。(ソートされるデータ量は1GB以下程度に制限しています。)
ORCL@SCOTT> @auto_sortwk1gb_optimal

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
workarea_size_policy string AUTO

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
pga_aggregate_target big integer 4398046511103

NAME VALUE UNIT CON_ID
---------------------------------------------------------------- ---------- ------------ ----------
global memory bound 1073741824 bytes 0

1 SELECT
2 /*+
3 MONITOR
4 */
5 *
6 FROM
7 m1
8 WHERE
9 id <= 'C045000'
10 ORDER BY
11 id
12* ,rev#
old 1: select dbms_sqltune.report_sql_monitor(sql_id=>'&1', type=>'text') from dual
new 1: select dbms_sqltune.report_sql_monitor(sql_id=>'', type=>'text') from dual

DBMS_SQLTUNE.REPORT_SQL_MONITOR(SQL_ID=>'',TYPE=>'TEXT')
------------------------------------------------------------------------------------------
SQL Monitoring Report

・・・中略・・・

Global Stats
===========================================================================
| Elapsed | Cpu | IO | Other | Fetch | Buffer | Read | Read |
| Time(s) | Time(s) | Waits(s) | Waits(s) | Calls | Gets | Reqs | Bytes |
===========================================================================
| 4.78 | 3.85 | 0.34 | 0.59 | 30001 | 334K | 2633 | 3GB |
===========================================================================

SQL Plan Monitoring Details (Plan Hash Value=3534657201)
==================================================================================================================================================
| Id | Operation | Name | Rows | Cost | Time | Start | Execs | Rows | Read | Read | Mem | Activity | Activity Detail |
| | | | (Estim) | | Active(s) | Active | | (Actual) | Reqs | Bytes | (Max) | (%) | (# samples) |
==================================================================================================================================================
| 0 | SELECT STATEMENT | | | | 10 | +2 | 1 | 450K | | | . | 33.33 | Cpu (2) |
| 1 | SORT ORDER BY | | 456K | 302K | 11 | +1 | 1 | 450K | | | 1GB | 33.33 | Cpu (2) |
| 2 | TABLE ACCESS FULL | M1 | 456K | 90827 | 3 | +2 | 1 | 450K | 2633 | 3GB | . | 33.33 | Cpu (2) |
==================================================================================================================================================

Temp落ちする程度のデータ量でソートさせた場合も、PGAの作業領域は最大1GBまで利用されていたことが確認できます。

ORCL@SCOTT> @auto_sortwk1gb_mpass    

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
workarea_size_policy string AUTO

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
pga_aggregate_target big integer 4398046511103

NAME VALUE UNIT CON_ID
---------------------------------------------------------------- ---------- ------------ ----------
global memory bound 1073741824 bytes 0

1 SELECT
2 /*+
3 MONITOR
4 */
5 *
6 FROM
7 m1
8 WHERE
9 id <= 'C050000'
10 ORDER BY
11 id
12* ,rev#
old 1: select dbms_sqltune.report_sql_monitor(sql_id=>'&1', type=>'text') from dual
new 1: select dbms_sqltune.report_sql_monitor(sql_id=>'', type=>'text') from dual

DBMS_SQLTUNE.REPORT_SQL_MONITOR(SQL_ID=>'',TYPE=>'TEXT')
------------------------------------------------------------------------------------------
SQL Monitoring Report

・・・中略・・・

Global Stats
===========================================================================================
| Elapsed | Cpu | IO | Other | Fetch | Buffer | Read | Read | Write | Write |
| Time(s) | Time(s) | Waits(s) | Waits(s) | Calls | Gets | Reqs | Bytes | Reqs | Bytes |
===========================================================================================
| 16 | 6.91 | 7.91 | 0.71 | 33335 | 334K | 7996 | 4GB | 4431 | 1GB |
===========================================================================================

SQL Plan Monitoring Details (Plan Hash Value=3534657201)
=====================================================================================================================================================================================
| Id | Operation | Name | Rows | Cost | Time | Start | Execs | Rows | Read | Read | Write | Write | Mem | Temp | Activity | Activity Detail |
| | | | (Estim) | | Active(s) | Active | | (Actual) | Reqs | Bytes | Reqs | Bytes | (Max) | (Max) | (%) | (# samples) |
=====================================================================================================================================================================================
| 0 | SELECT STATEMENT | | | | 22 | +2 | 1 | 500K | | | | | . | . | 6.25 | Cpu (1) |
| 1 | SORT ORDER BY | | 507K | 326K | 22 | +2 | 1 | 500K | 5363 | 1GB | 4431 | 1GB | 1GB | 1GB | 68.75 | Cpu (4) |
| | | | | | | | | | | | | | | | | direct path read temp (1) |
| | | | | | | | | | | | | | | | | direct path write temp (6) |
| 2 | TABLE ACCESS FULL | M1 | 507K | 90828 | 13 | +1 | 1 | 500K | 2633 | 3GB | | | . | . | 25.00 | Cpu (3) |
| | | | | | | | | | | | | | | | | direct path read (1) |
=====================================================================================================================================================================================

自動PGA管理でGlobal Memory Bound = 1GB(自動PGA管理での最大 Hash作業領域サイズ)


Hash Joinの場合も、自動PGA管理の最大サイズ程度まで利用されていることが確認できます。(Temp落ちしない程度のデータ量にしています。)
ORCL@SCOTT> @auto_hashwk1gb_optimal

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
workarea_size_policy string AUTO

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
pga_aggregate_target big integer 4398046511103

NAME VALUE UNIT CON_ID
---------------------------------------------------------------- ---------- ------------ ----------
global memory bound 1073741824 bytes 0

1 SELECT
2 /*+
3 MONITOR
4 LEADING(m1 m2)
5 USE_HASH(m1 m2)
6 */
7 *
8 FROM
9 m1
10 INNER JOIN m2
11 ON
12 m1.id = m2.id
13 AND m1.rev# = m2.rev#
14 WHERE
15* m1.id <= 'C042000'
old 1: select dbms_sqltune.report_sql_monitor(sql_id=>'&1', type=>'text') from dual
new 1: select dbms_sqltune.report_sql_monitor(sql_id=>'', type=>'text') from dual

DBMS_SQLTUNE.REPORT_SQL_MONITOR(SQL_ID=>'',TYPE=>'TEXT')
------------------------------------------------------------------------------------------
SQL Monitoring Report

・・・中略・・・

Global Stats
===========================================================================
| Elapsed | Cpu | IO | Other | Fetch | Buffer | Read | Read |
| Time(s) | Time(s) | Waits(s) | Waits(s) | Calls | Gets | Reqs | Bytes |
===========================================================================
| 7.29 | 5.05 | 0.68 | 1.55 | 28001 | 695K | 5251 | 5GB |
===========================================================================

SQL Plan Monitoring Details (Plan Hash Value=1822065247)
==================================================================================================================================================
| Id | Operation | Name | Rows | Cost | Time | Start | Execs | Rows | Read | Read | Mem | Activity | Activity Detail |
| | | | (Estim) | | Active(s) | Active | | (Actual) | Reqs | Bytes | (Max) | (%) | (# samples) |
==================================================================================================================================================
| 0 | SELECT STATEMENT | | | | 14 | +2 | 1 | 420K | | | . | 22.22 | Cpu (2) |
| 1 | HASH JOIN | | 423K | 268K | 15 | +1 | 1 | 420K | | | 1GB | 22.22 | Cpu (2) |
| 2 | TABLE ACCESS FULL | M1 | 432K | 90827 | 2 | +2 | 1 | 420K | 2633 | 3GB | . | 11.11 | Cpu (1) |
| 3 | TABLE ACCESS FULL | M2 | 423K | 90580 | 13 | +3 | 1 | 420K | 2618 | 3GB | . | 44.44 | Cpu (4) |
==================================================================================================================================================


Hash Joinの場合もSort時と同じように、一時表領域も利用が必要となるデータ量になると、一旦、自動PGA管理の最大サイズ程度まで利用したうえでTemp落ちしていることが確認できます。

ORCL@SCOTT> @auto_hashwk1gb_mpass

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
workarea_size_policy string AUTO

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
pga_aggregate_target big integer 4398046511103

NAME VALUE UNIT CON_ID
---------------------------------------------------------------- ---------- ------------ ----------
global memory bound 1073741824 bytes 0

1 SELECT
2 /*+
3 MONITOR
4 LEADING(m1 m2)
5 USE_HASH(m1 m2)
6 */
7 *
8 FROM
9 m1
10 INNER JOIN m2
11 ON
12 m1.id = m2.id
13 AND m1.rev# = m2.rev#
14 WHERE
15* m1.id <= 'C055000'
old 1: select dbms_sqltune.report_sql_monitor(sql_id=>'&1', type=>>'text') from dual
new 1: select dbms_sqltune.report_sql_monitor(sql_id=>'', type=>'text') from dual

DBMS_SQLTUNE.REPORT_SQL_MONITOR(SQL_ID=>'',TYPE=>'TEXT')
------------------------------------------------------------------------------------------
SQL Monitoring Report

・・・中略・・・

Global Stats
============================================================================================
| Elapsed | Cpu | IO | Other | Fetch | Buffer | Read | Read | Write | Write |
| Time(s) | Time(s) | Waits(s) | Waits(s) | Calls | Gets | Reqs | Bytes | Reqs | Bytes |
============================================================================================
| 24 | 7.18 | 15 | 1.99 | 36668 | 687K | 10829 | 6GB | 5578 | 1GB |
============================================================================================

SQL Plan Monitoring Details (Plan Hash Value=1822065247)
======================================================================================================================================================================================
| Id | Operation | Name | Rows | Cost | Time | Start | Execs | Rows | Read | Read | Write | Write | Mem | Temp | Activity | Activity Detail |
| | | | (Estim) | | Active(s) | Active | | (Actual) | Reqs | Bytes | Reqs | Bytes | (Max) | (Max) | (%) | (# samples) |
======================================================================================================================================================================================
| 0 | SELECT STATEMENT | | | | 33 | +2 | 1 | 550K | | | | | . | . | 14.29 | Cpu (4) |
| 1 | HASH JOIN | | 551K | 293K | 33 | +2 | 1 | 550K | 5578 | 1GB | 5578 | 1GB | 1GB | 1GB | 67.86 | Cpu (8) |
| | | | | | | | | | | | | | | | | direct path read temp (1) |
| | | | | | | | | | | | | | | | | direct path write temp (10) |
| 2 | TABLE ACCESS FULL | M1 | 551K | 90828 | 16 | +1 | 1 | 550K | 2633 | 3GB | | | . | . | 7.14 | Cpu (1) |
| | | | | | | | | | | | | | | | | direct path read (1) |
| 3 | TABLE ACCESS FULL | M2 | 557K | 90580 | 16 | +16 | 1 | 550K | 2618 | 3GB | | | . | . | 10.71 | Cpu (3) |
======================================================================================================================================================================================

PGAの最大サイズは異なりますが、自動PGA管理、手動PGA管理いずれでの場合でも制限値を超えた場合は、もれなく "Temp落ち" するということはご理解いただけたのではないかと思います。


では、次回は恒例?w の隠しパラメータと戯れた場合、自動PGA管理下ではどこまで増加させることができるのか?。。。。確認してみたいと思います。


Temp落ち #1 - "Temp落ち" って?
Temp落ち #2 - PGA (Program Global Area)
Temp落ち #3 - 手動PGA管理で作業領域として指定可能な最大サイズ
Temp落ち #4 - 手動PGA管理で作業領域として指定可能な最大サイズ de Temp落ちの確認
Temp落ち #5 - pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? 12.2.0.1版 (その前に少し脱線)
Temp落ち #6 - pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? 12.2.0.1版

| | コメント (0) | トラックバック (0)

2018年3月 7日 (水)

Temp落ち #6 - pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? 12.2.0.1版

Previously on Mac De Oracle
pga_aggregate_target scope=memory or bothでそれまでとはことなる動きとエラーは発生するところの話でした。


きょうは、自動PGA管理下ではどうなるか確認しておきます。
以前、簡単に確認した範囲結果から、これまでの仕様と大きな違いはないとみています。(変わっていないと思っていたのでブログでも書いていなかったのですが、"Temp落ち"ネタの準備運動も兼ね現状を確認しながら進めてみたいと思います)


まず環境情報から、
確認に利用するインスタンスのPGA以外のパラメータは以下の通りです。
(隠しパラメータは必要がある場合には適宜変更します。また、いくつかのパラメータは確認の都合上物理メモリーサイズ以上に設定することがあります。それらの変更が必要な場合には事前に解説する予定です。)

OS等の情報は以前のエントリーを参照のこと。

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
sga_max_size big integer 12G
sga_min_size big integer 0
sga_target big integer 12G

今回の主役である自動PGA管理のパラメータの初期設定は以下の通り(隠しパラメータを除く)
pga_aggregate_limit = 0 に設定し、pga_aggregate_targetの上限値制限を仕様上のサイズ4096GB - 1まで利用できるようにしておきます。(以前と同様の手順で確認するために、pga_aggregate_limitによる制限を無効化しています。なお、pga_aggregate_limitを0以外に設定して行う場合には、pga_aggregate_targetを4TB - 1まで設定することを考慮すると、pga_aggregate_limitは、8TB以上に設定する必要があります。)

orcl12c@SYS> show parameter pga_aggregate

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
pga_aggregate_limit big integer 0
pga_aggregate_target big integer 10M

上記設定からスタートして、pga_aggregate_targetを10MB/50MB/100MB/500MB/1GB/5GB/10GB/50GB/100GB/500GB/1T/4TB - 1と増加させながら、pgaサイズおよび、関連する隠しパラメータ(_pga_max_sizeや_smm_*など)がどのように変化するか、pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? Season2 #8の手順で確認します。

昔のように実行ログをペタペタ貼っていると長くなるので、確認結果を表とグラフにしました。
想定通り以前と変わっていませんでした:)

デフォルト設定のままであれば、pga_aggregate_targetを限界値まで大きく増やしたとしても、10GB以降、個々のソート操作やハッシュ結合操作で利用できるPGAのSQL work areaサイズはv$pgastatのglobal memory boundの示す通り、1GB(シリアル実行時)が最大であることが確認できます。 えーーー。手動PGA管理より最大サイズ小さいじゃんと、今更驚かないようにしましょうねw (以前からそうなのですからw)
つまり、自動PGA管理の場合、特定の隠しパラメータを変更しない限り、1GBを超えるソート処理やハッシュ結合操作は全て、"Temp落ち" する宿命にあるわけです。12cR2であっても。
え"〜〜〜〜〜っ! と一応、驚いておきましょうw。 メモリーを沢山積んでるマシンは最近多いわけですが、このあたりはなぜか変わってません。
20180307_143101

ちなみに、v$pgastatの示すglobal memory boundは、どこから? という確認がしたくて、 _smm_max_sizeの変化と比較しているグラグも作成しておきました。
_smm_max_sizeパラメータはpga_aggregate_targetのサイズ変化に伴い変化する隠しパラメータですが、このパラメータがglobal memory boundの元になっているのは確からしいですね。
20180307_143308

最後のグラフは、pga_aggregate_targetの値とv$pgastatのglobal memory boundの変化をまとめたグラフです。
global memory boundで示されるPGAのSQL Work Areaサイズの最大サイズには上限があることがわかります:)
20180307_143330

次回は、自動PGA管理では、1GBを超えるソートやハッシュ結合はもれなく"Temp落ち"するのか確認してみることにします。


参考:このエントリーで利用したスクリプト
(今後の確認も兼ねてw このエントリーでネタにしている以外で関連しそうなパラメータも取得して変化を確認できるようにしてあります。)

orcl12c@SYS> !cat show_param.sql
set linesize 200
col ksppinm for a46
col ksppstvl for a30
col ksppstdf for a30
select
a.ksppinm
,b.ksppstvl
,b.ksppstdf
from
x$ksppi a join x$ksppcv b
on a.indx = b.indx
where
a.ksppinm in (
'pga_aggregate_target'
,'pga_aggregate_limit'
,'_use_realfree_heap'
,'_realfree_heap_pagesize'
)
or a.ksppinm like '%\_smm%' escape '\'
or a.ksppinm like '%\_pga%' escape '\'
order by
a.ksppinm
/

!echo /proc/sys/vm/max_map_count
!more /proc/sys/vm/max_map_count

orcl12c@SYS> !cat show_pgstat.sql
select
name
,case
when unit='bytes' then
value/1024/1024
else value
end "VALUE"
,case
when unit='bytes' then
'MB'
else unit
end "UNIT"
,con_id
from
v$pgastat
where
name in (
'aggregate PGA target parameter'
,'aggregate PGA auto target'
,'global memory bound'
,'total PGA used for auto workareas'
,'maximum PGA used for auto workareas'
,'total PGA used for manual workareas'
,'maximum PGA used for manual workareas'
)
;
orcl12c@SYS> !cat auto_workarea.sql
conn sys/oracle@orcl12c as sysdba
alter system set pga_aggregate_target=&1 scope=spfile
.
r
shutdown immediate
startup

prompt +++ initial parameters +++
@show_param

prompt +++ v$pgastat +++
@show_pgstatå
orcl12c@SYS> !cat doTest_auto_workarea.sql
prompt << 10m >>
@auto_workarea 10m

prompt << 50m >>
@auto_workarea 50m

prompt << 100m >>
@auto_workarea 100m

prompt << 500m >>
@auto_workarea 500m

prompt << 1g >>
@auto_workarea 1g

prompt << 5g >>
@auto_workarea 5g

prompt << 10g >>
@auto_workarea 10g

prompt << 50g >>
@auto_workarea 50g

prompt << 100g >>
@auto_workarea 100g

prompt << 500g >>
@auto_workarea 500g

prompt << 1t >>
@auto_workarea 1t

prompt << 4t - 1 >>
@auto_workarea 4398046511103


実行例

orcl12c@SYS> @doTest_auto_workarea.sql
<< 10m >>
Connected.
1* alter system set pga_aggregate_target=&1 scope=spfile
old 1: alter system set pga_aggregate_target=&1 scope=spfile
new 1: alter system set pga_aggregate_target=10m scope=spfile

System altered.

Database closed.
Database dismounted.
ORACLE instance shut down.
ORACLE instance started.

Total System Global Area 1.2885E+10 bytes
Fixed Size 8807168 bytes
Variable Size 1375735040 bytes
Database Buffers 5033164800 bytes
Redo Buffers 24743936 bytes
In-Memory Area 6442450944 bytes
Database mounted.
Database opened.
+++ initial parameters +++

KSPPINM KSPPSTVL KSPPSTDF
---------------------------------------------- ------------------------------ ------------------------------
__pga_aggregate_target 33554432 FALSE

・・・略・・・

pga_aggregate_limit 0 FALSE
pga_aggregate_target 10485760 FALSE

50 rows selected.

/proc/sys/vm/max_map_count

65530

+++ v$pgastat +++

NAME VALUE UNIT CON_ID
---------------------------------------------------------------- ---------- ------------ ----------
aggregate PGA target parameter 10 MB 0
aggregate PGA auto target 4 MB 0
global memory bound 2 MB 0
total PGA used for auto workareas .106445313 MB 0
maximum PGA used for auto workareas .106445313 MB 0
total PGA used for manual workareas 0 MB 0
maximum PGA used for manual workareas 0 MB 0

7 rows selected.

・・・略・・・


Temp落ち #1 - "Temp落ち" って?
Temp落ち #2 - PGA (Program Global Area)
Temp落ち #3 - 手動PGA管理で作業領域として指定可能な最大サイズ
Temp落ち #4 - 手動PGA管理で作業領域として指定可能な最大サイズ de Temp落ちの確認
Temp落ち #5 - pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? 12.2.0.1版 (その前に少し脱線)

| | コメント (0) | トラックバック (0)

2018年2月22日 (木)

Temp落ち #4 - 手動PGA管理で作業領域として指定可能な最大サイズ de Temp落ちの確認


Previously on Mac De Oracle
手動PGA管理で作業領域として指定可能な最大サイズは、2GB - 1までということの確認でした。
本当に、その程度のサイズまでPGAの作業領域が利用されるのでしょうか?。 念のために確認しておきましょう。
実は、それより少ないサイズで頭打ちなんてことは、ないかな〜 と わざとらしく言ってみたりして(意味深w

その前に、指定した作業領域を使い切れるぐらい(つまり、Temp落ちさせられる程度)のデータ量の表を準備しておきます。
今回は、Nested Loop Join(NLJ)やソート回避などのための索引は作成しません。Temp落ちのネタなので。

M1とM2の2表を作成し、それぞれ、2.5GB程度のセグメントサイズにしておきます。
なお、以下の無名PL/SQLブロックでは、FORALLを利用して1000行単位でバルク処理しています。配列を利用するのでメモリー使用量にはそれなりに配慮が必要ですが。:)
単純なぐるぐる系INSERTにしてしまうとデータ量が多い場合、性能的に辛くなってしまうので、ここ重要!

ORCL@SCOTT> l
1 CREATE TABLE m1
2 (
3 id CHAR(7) NOT NULL
4 ,rev# NUMBER NOT NULL
5 ,value NUMBER NOT NULL
6 ,description VARCHAR2(4000)
7 ,additional_info CHAR(200)
8* ) NOLOGGING
ORCL@SCOTT> /

Table created.

ORCL@SCOTT> l
1 DECLARE
2 TYPE IDS_t IS TABLE OF m1.id%TYPE INDEX BY PLS_INTEGER;
3 TYPE REV#S_t IS TABLE OF m1.rev#%TYPE INDEX BY PLS_INTEGER;
4 TYPE VALS_t IS TABLE OF m1.value%TYPE INDEX BY PLS_INTEGER;
5 IDs IDS_t;
6 REV#s REV#S_t;
7 VALs VALS_t;
8 k PLS_INTEGER := 1;
9 BEGIN
10 FOR i IN 1..100000 LOOP
11 FOR j IN 1..10 LOOP
12 IDs(k) := 'C' || TO_CHAR(i, 'FM000000');
13 REV#s(k) := j;
14 VALs(k) := i + j;
15 k := k + 1;
16 END LOOP;
17 IF MOD(i, 100) = 0 THEN
18 FORALL l in 1..1000 EXECUTE IMMEDIATE
19 'INSERT /*+ APPEND_VALUE NO_GATHER_OPTIMIZER_STATISTICS */ INTO m1 '
20 || 'VALUES(:1, :2, :3, LPAD(''X'',2000, ''X''), LPAD(''9'',200,''9''))'
21 USING IDs(l), REV#s(l), VALs(l);
22 COMMIT;
23 k := 1;
24 END IF;
25 END LOOP;
26* END;
ORCL@SCOTT> /

PL/SQL procedure successfully completed.

Elapsed: 00:01:22.45
ORCL@SCOTT> select count(1) from m1;

COUNT(1)
----------
1000000

ORCL@SCOTT> select segment_name,sum(bytes)/1024/1024/1024 "GB" from user_segments where segment_name='M1' group by segment_name;

SEGMENT_NAME GB
------------------------------ ----------
M1 2.5625

ORCL@SCOTT> l
1 CREATE TABLE m2
2 (
3 id CHAR(7) NOT NULL
4 ,rev# NUMBER NOT NULL
5 ,value NUMBER NOT NULL
6 ,description VARCHAR2(4000)
7* ) NOLOGGING
ORCL@SCOTT> /

Table created.

ORCL@SCOTT> l
1 INSERT /*+ APPEND NO_GATHER_OPTIMIZER_STATISTICS */ INTO m2
2* SELECT id,rev#,value,description FROM m1
ORCL@SCOTT> /

1000000 rows created.

Elapsed: 00:00:40.22
ORCL@SCOTT> commit;

Commit complete.

ORCL@SCOTT> exec dbms_stats.gather_table_stats(ownname=>'SCOTT',tabname=>'M1',no_invalidate=>false,method_opt=>'FOR ALL COLUMNS SIZE SKEWONLY');

PL/SQL procedure successfully completed.

ORCL@SCOTT> exec dbms_stats.gather_table_stats(ownname=>'SCOTT',tabname=>'M2',no_invalidate=>false,method_opt=>'FOR ALL COLUMNS SIZE SKEWONLY');

PL/SQL procedure successfully completed.

これで、準備完了。
ちなみに、NO_GATHER_OPTIMIZER_STATISTICSヒントを利用していますが、データ登録後に、ヒストグラムも含めて取得したかったため、バルクロード時のオンラインオプティマイザ統計収集を行わないようにするためのヒントです。
データ登録後オプティマイザ統計を取得するため、データ登録時のオンラインオプティマイザ統計のオーバーヘッドは無駄となるためです。利用できるなら利用したほうがよいとは思いますが、制限もあるのでご一読を(バルク・ロードのためのオンライン統計収集



手動PGA管理で2GB - 1(手動PGA管理での最大 Sort作業領域サイズ)


メモリーソートで2GBぐらいまで利用していることが確認できます。(ソートされるデータ量が2GB以下程度に制限しています。)
ORCL@SCOTT> @manual_sortwk2gb_optimal    
1* alter session set workarea_size_policy=manual

Session altered.

1* alter session set sort_area_size = 2147483647

Session altered.

1 SELECT
2 /*+
3 MONITOR
4 */
5 *
6 FROM
7 m1
8 WHERE
9 id <= 'C075000'
10 ORDER BY
11 id
12* ,rev#
old 1: select dbms_sqltune.report_sql_monitor(sql_id=>'&1', type=>'text') from dual
new 1: select dbms_sqltune.report_sql_monitor(sql_id=>'', type=>'text') from dual

DBMS_SQLTUNE.REPORT_SQL_MONITOR(SQL_ID=>'',TYPE=>'TEXT')
------------------------------------------------------------------------------------------
SQL Monitoring Report

・・・中略・・・

Global Stats
=================================================
| Elapsed | Cpu | Other | Fetch | Buffer |
| Time(s) | Time(s) | Waits(s) | Calls | Gets |
=================================================
| 5.42 | 4.13 | 1.29 | 50001 | 334K |
=================================================

SQL Plan Monitoring Details (Plan Hash Value=3534657201)
===================================================================================================================================
| Id | Operation | Name | Rows | Cost | Time | Start | Execs | Rows | Mem | Activity | Activity Detail |
| | | | (Estim) | | Active(s) | Active | | (Actual) | (Max) | (%) | (# samples) |
===================================================================================================================================
| 0 | SELECT STATEMENT | | | | 15 | +2 | 1 | 750K | . | 20.00 | Cpu (1) |
| 1 | SORT ORDER BY | | 752K | 439K | 16 | +1 | 1 | 750K | 2GB | 60.00 | Cpu (3) |
| 2 | TABLE ACCESS FULL | M1 | 752K | 90828 | 3 | +2 | 1 | 750K | . | 20.00 | Cpu (1) |
===================================================================================================================================

Temp落ちする程度のデータ量でソートさせた場合も、PGAの作業領域は一旦、2GBまで利用されていることが確認できます。

ORCL@SCOTT> @manual_sortwk2gb
1* alter session set workarea_size_policy=manual

Session altered.

1* alter session set sort_area_size = 2147483647

Session altered.

1 SELECT
2 /*+
3 MONITOR
4 */
5 *
6 FROM
7 m1
8 ORDER BY
9 id
10* ,rev#
old 1: select dbms_sqltune.report_sql_monitor(sql_id=>'&1', type=>'text') from dual
new 1: select dbms_sqltune.report_sql_monitor(sql_id=>'', type=>'text') from dual

DBMS_SQLTUNE.REPORT_SQL_MONITOR(SQL_ID=>'',TYPE=>'TEXT')
-------------------------------------------------------------------------------------------
SQL Monitoring Report

・・・中略・・・

Global Stats
===========================================================================================
| Elapsed | Cpu | IO | Other | Fetch | Buffer | Read | Read | Write | Write |
| Time(s) | Time(s) | Waits(s) | Waits(s) | Calls | Gets | Reqs | Bytes | Reqs | Bytes |
===========================================================================================
| 46 | 11 | 15 | 20 | 66668 | 334K | 2148 | 2GB | 2146 | 2GB |
===========================================================================================

SQL Plan Monitoring Details (Plan Hash Value=3534657201)
=====================================================================================================================================================================================
| Id | Operation | Name | Rows | Cost | Time | Start | Execs | Rows | Read | Read | Write | Write | Mem | Temp | Activity | Activity Detail |
| | | | (Estim) | | Active(s) | Active | | (Actual) | Reqs | Bytes | Reqs | Bytes | (Max) | (Max) | (%) | (# samples) |
=====================================================================================================================================================================================
| 0 | SELECT STATEMENT | | | | 60 | +2 | 1 | 1M | | | | | . | . | 6.38 | Cpu (2) |
| | | | | | | | | | | | | | | | | PGA memory operation (1) |
| 1 | SORT ORDER BY | | 1M | 553K | 61 | +1 | 1 | 1M | 2148 | 2GB | 2146 | 2GB | 2GB | 2GB | 91.49 | Cpu (32) |
| | | | | | | | | | | | | | | | | direct path read temp (10) |
| | | | | | | | | | | | | | | | | direct path write temp (1) |
| 2 | TABLE ACCESS FULL | M1 | 1M | 90822 | 27 | +2 | 1 | 1M | | | | | . | . | 2.13 | Cpu (1) |
=====================================================================================================================================================================================

手動PGA管理で2GB - 1(手動PGA管理での最大 Hash作業領域サイズ)
Hash Joinの場合も、手動PGA管理で設定可能な最大サイズ程度まで利用されていることが確認できます。(Temp落ちしない程度のデータ量にしています。)

ORCL@SCOTT> @manual_hashwk2gb_optimal
1* alter session set workarea_size_policy = manual

Session altered.

1* alter session set hash_area_size = 2147483647

Session altered.

1 SELECT
2 /*+
3 MONITOR
4 LEADING(m1 m2)
5 USE_HASH(m1 m2)
6 */
7 *
8 FROM
9 m1
10 INNER JOIN m2
11 ON
12 m1.id = m2.id
13 AND m1.rev# = m2.rev#
14 WHERE
15* m1.id <= 'C075000'
old 1: select dbms_sqltune.report_sql_monitor(sql_id=>'&1', type=>'text') from dual
new 1: select dbms_sqltune.report_sql_monitor(sql_id=>'', type=>'text') from dual

DBMS_SQLTUNE.REPORT_SQL_MONITOR(SQL_ID=>'',TYPE=>'TEXT')
------------------------------------------------------------------------------------------
SQL Monitoring Report

・・・中略・・・

Global Stats
===========================================================================
| Elapsed | Cpu | IO | Other | Fetch | Buffer | Read | Read |
| Time(s) | Time(s) | Waits(s) | Waits(s) | Calls | Gets | Reqs | Bytes |
===========================================================================
| 8.05 | 4.66 | 0.16 | 3.23 | 50001 | 717K | 2618 | 3GB |
===========================================================================

SQL Plan Monitoring Details (Plan Hash Value=1822065247)
==================================================================================================================================================
| Id | Operation | Name | Rows | Cost | Time | Start | Execs | Rows | Read | Read | Mem | Activity | Activity Detail |
| | | | (Estim) | | Active(s) | Active | | (Actual) | Reqs | Bytes | (Max) | (%) | (# samples) |
==================================================================================================================================================
| 0 | SELECT STATEMENT | | | | 21 | +2 | 1 | 750K | | | . | 12.50 | Cpu (1) |
| 1 | HASH JOIN | | 752K | 181K | 22 | +1 | 1 | 750K | | | 2GB | 25.00 | Cpu (2) |
| 2 | TABLE ACCESS FULL | M1 | 752K | 90828 | 2 | +2 | 1 | 750K | | | . | 25.00 | Cpu (2) |
| 3 | TABLE ACCESS FULL | M2 | 759K | 90581 | 20 | +3 | 1 | 750K | 2618 | 3GB | . | 37.50 | Cpu (3) |
==================================================================================================================================================

Hash Joinの場合もSort時と同じように、一時表領域も利用させる程度のデータ量になると、一旦、手動PGA管理で設定可能な最大サイズ程度まで利用したうえでTemp落ちしていることが確認できます。

ORCL@SCOTT> @manual_hashwk2gb
1* alter session set workarea_size_policy = manual

Session altered.

1* alter session set hash_area_size = 2147483647

Session altered.

1 SELECT
2 /*+
3 MONITOR
4 LEADING(m1 m2)
5 USE_HASH(m1 m2)
6 */
7 *
8 FROM
9 m1
10 INNER JOIN m2
11 ON
12 m1.id = m2.id
13* AND m1.rev# = m2.rev#
old 1: select dbms_sqltune.report_sql_monitor(sql_id=>'&1', type=>'text') from dual
new 1: select dbms_sqltune.report_sql_monitor(sql_id=>'', type=>'text') from dual

DBMS_SQLTUNE.REPORT_SQL_MONITOR(SQL_ID=>'',TYPE=>'TEXT')
------------------------------------------------------------------------------------------
SQL Monitoring Report

・・・中略・・・

Global Stats
===========================================================================================
| Elapsed | Cpu | IO | Other | Fetch | Buffer | Read | Read | Write | Write |
| Time(s) | Time(s) | Waits(s) | Waits(s) | Calls | Gets | Reqs | Bytes | Reqs | Bytes |
===========================================================================================
| 12 | 5.68 | 2.17 | 4.59 | 66668 | 706K | 3133 | 3GB | 515 | 511MB |
===========================================================================================

SQL Plan Monitoring Details (Plan Hash Value=1822065247)
=====================================================================================================================================================================================
| Id | Operation | Name | Rows | Cost | Time | Start | Execs | Rows | Read | Read | Write | Write | Mem | Temp | Activity | Activity Detail |
| | | | (Estim) | | Active(s) | Active | | (Actual) | Reqs | Bytes | Reqs | Bytes | (Max) | (Max) | (%) | (# samples) |
=====================================================================================================================================================================================
| 0 | SELECT STATEMENT | | | | 30 | +2 | 1 | 1M | | | | | . | . | 25.00 | Cpu (4) |
| 1 | HASH JOIN | | 1M | 189K | 31 | +1 | 1 | 1M | 515 | 511MB | 515 | 511MB | 2GB | 515MB | 43.75 | Cpu (5) |
| | | | | | | | | | | | | | | | | direct path read temp (1) |
| | | | | | | | | | | | | | | | | direct path write temp (1) |
| 2 | TABLE ACCESS FULL | M1 | 1M | 90822 | 6 | +0 | 1 | 1M | | | | | . | . | 12.50 | Cpu (2) |
| 3 | TABLE ACCESS FULL | M2 | 1M | 90574 | 24 | +5 | 1 | 1M | 2618 | 3GB | | | . | . | 18.75 | Cpu (2) |
| | | | | | | | | | | | | | | | | direct path read (1) |
=====================================================================================================================================================================================

おまけ
1つのSQLの実行で利用されるPGAの作業領域は1つだけではないということも確認しておきましょうかね。(知ってる方はスルーしてよいですよ:)
以下の例では、MERGE JOINさせていますが、表M1と表M2それぞれのSort作業領域は、Merge Join終了時まで保持されることになるため、最大3GBのSort作業領域が利用されています。(SQLモニターの結果ではわかりにくいのですが。。。)
なお、手動PGA管理、自動PGA管理に関係なく、実行される操作により複数の作業領域が同時に確保されることがあります。
(ちなみに、自動PGA管理で利用されるPGA_AGGREGATE_LIMITがPGA_AGGREGATE_TARGETの2倍とされるのも、このような動きが考慮された結果だと知っていると、納得感はあるかもしれません。)

前回使った図で朱色で示したSQL Work Areaが複数ありますが、Hash/Sort/Bitmap系など複数のタイプおよび同一タイプの作業領域が同時に確保されることも意図した図になっているのは、これが理由なんです。


Structure_of_pga

ORCL@SCOTT> @manual_sortwk2gb2_optimal
1* alter session set workarea_size_policy = manual

Session altered.

1* alter session set sort_area_size = 2147483647

Session altered.

1 SELECT
2 /*+
3 MONITOR
4 USE_MERGE(m1 m2)
5 */
6 *
7 FROM
8 m1
9 INNER JOIN m2
10 ON
11 m1.id = m2.id
12 AND m1.rev# = m2.rev#
13 WHERE
14* m1.id <= 'C075000'
old 1: select dbms_sqltune.report_sql_monitor(sql_id=>'&1', type=>'text') from dual
new 1: select dbms_sqltune.report_sql_monitor(sql_id=>'', type=>'text') from dual

DBMS_SQLTUNE.REPORT_SQL_MONITOR(SQL_ID=>'',TYPE=>'TEXT')
-------------------------------------------------------------------------------------------
SQL Monitoring Report

・・・中略・・・

Global Stats
===========================================================================
| Elapsed | Cpu | IO | Other | Fetch | Buffer | Read | Read |
| Time(s) | Time(s) | Waits(s) | Waits(s) | Calls | Gets | Reqs | Bytes |
===========================================================================
| 17 | 10 | 4.75 | 2.19 | 50001 | 667K | 5251 | 5GB |
===========================================================================

SQL Plan Monitoring Details (Plan Hash Value=1391069689)
========================================================================================================================================================
| Id | Operation | Name | Rows | Cost | Time | Start | Execs | Rows | Read | Read | Mem | Activity | Activity Detail |
| | | | (Estim) | | Active(s) | Active | | (Actual) | Reqs | Bytes | (Max) | (%) | (# samples) |
========================================================================================================================================================
| 0 | SELECT STATEMENT | | | | 23 | +10 | 1 | 750K | | | . | 14.29 | Cpu (2) |
| 1 | MERGE JOIN | | 752K | 849K | 23 | +10 | 1 | 750K | | | . | | |
| 2 | SORT JOIN | | 752K | 439K | 32 | +1 | 1 | 750K | | | 2GB | 21.43 | Cpu (3) |
| 3 | TABLE ACCESS FULL | M1 | 752K | 90828 | 8 | +2 | 1 | 750K | 2633 | 3GB | . | 35.71 | Cpu (3) |
| | | | | | | | | | | | | | direct path read (2) |
| 4 | SORT JOIN | | 759K | 410K | 23 | +10 | 750K | 750K | | | 1GB | 14.29 | Cpu (2) |
| 5 | TABLE ACCESS FULL | M2 | 759K | 90581 | 5 | +10 | 1 | 750K | 2618 | 3GB | . | 14.29 | Cpu (2) |
========================================================================================================================================================


SQLモニターの結果ではわかりにくいわけですが、v$sesstatをから眺めれば状況がよくわかります!
2つのソート作業領域が同時に確保されたことで、2GB + 1GB = 3GB程度のサイズにまで達していることが確認できます。

ORCL@SYSTEM> r
1 select
2 vss.value/1024/1024/1024 "GB"
3 ,vsn.name
4 ,vss.sid
5 from
6 v$sesstat vss
7 inner join v$statname vsn
8 on
9 vss.statistic# = vsn.statistic#
10 and vss.con_id = vsn.con_id
11 and vsn.name like '%pga%'
12 where
13 sid IN (select sid from v$session where username='SCOTT')
14 order by
15* sid,name

GB NAME SID
---------- ---------------------------------------------------------------- ----------
3.04611414 session pga memory 203
3.04611414 session pga memory max 203

では、次回はやっとw、真打、自動PGA管理下での確認。(引っ張り過ぎかもしれないw)
つづく。


Temp落ち #1 - "Temp落ち" って?
Temp落ち #2 - PGA (Program Global Area)
Temp落ち #3 - 手動PGA管理で作業領域として指定可能な最大サイズ

| | コメント (0) | トラックバック (0)

2018年2月20日 (火)

Temp落ち #3 - 手動PGA管理で作業領域として指定可能な最大サイズ

自動PGA管理は12cでどうなんだっけ?という確認の前に、
いままで何度か質問されたことがあり、FAQだと思っているので

手動PGA管理で利用する以下パラメータの最大サイズはいくつ? 

HASH_AREA_SIZE
SORT_AREA_SIZE
BITMAP_MERGE_AREA_SIZE
CREATE_BITMAP_AREA_SIZE

ということを書いておきたいと思います。

これからしばらく続く Temp落ち ネタで利用する環境で固定部分は以下のとおり
(初期化パラメータ等は必要に応じて載せるつもりです。)


環境は以下のとおり。
host osとguest osのバージョンやメモリーサイズなど

discus:˜ oracle$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.13.3
BuildVersion: 17D47

discus:˜ oracle$ system_profiler SPHardwareDataType | grep -E 'Processor Name|Cores|Memory'
Processor Name: 6-Core Intel Xeon
Total Number of Cores: 12
Memory: 32 GB

discus:˜ oracle$ VBoxManage -v
5.2.6r120293

discus:˜ oracle$ VBoxManage showvminfo e3d4f948-b2e6-4db3-a89d-df637d87a372 | grep -E 'Memory size|OS type|Number of CPUs'
Memory size: 23569MB
Number of CPUs: 12
OS type: Linux26_64


orcl12c@SYS> select * from v$version;

BANNER CON_ID
-------------------------------------------------------------------------------- ----------
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production 0
PL/SQL Release 12.2.0.1.0 - Production 0
CORE 12.2.0.1.0 Production 0
TNS for Linux: Version 12.2.0.1.0 - Production 0
NLSRTL Version 12.2.0.1.0 - Production 0


orcl12c@SYS> show pdbs

CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 ORCL READ WRITE NO

さて、今日の本題

手動PGA管理で各SQL Work Area Sizeを決定する以下の初期化パラメータの最大サイズは? いくつでしょう? 
すでにご存知のかたはスキップしていいですよ:)

マニュアルを読んでみるときづくのですが、手動PGA管理で各SQL Work Area Sizeを決定する4パラメータとも、「0以上、上限はOS依存」のような記述になっています。

そう、マニュアルを読んだだけではまったく参考にならないわけです。(え〜〜っ!)

そこで、みなさんサポートを頼るなり、ご自分でMOSを検索するなり、そこそこの苦労をして入手することになります。
私みたいな性格だと、どのマニュアルでもいいからまとめて載せてよーめんどくさいから。と、めんどくさい病の発作がでたりしますw

なので、環境があるのなら、you 試しちゃいなよー。が手っ取り早いかなーと(最終的にMOSとかサポートを頼るにしてもw)

上限はOS依存とだけしか記載されていませんが、私の観測範囲では、2GB - 1 が上限 となっています。
以下、Linux/Solaris/Windowsでの検証ログ。

Oracle® Databaseリファレンス 12cリリース2 (12.2) E72905-03より

HASH_AREA_SIZE
https://docs.oracle.com/cd/E82638_01/REFRN/HASH_AREA_SIZE.htm

SORT_AREA_SIZE
https://docs.oracle.com/cd/E82638_01/REFRN/SORT_AREA_SIZE.htm

BITMAP_MERGE_AREA_SIZE
https://docs.oracle.com/cd/E82638_01/REFRN/BITMAP_MERGE_AREA_SIZE.htm

CREATE_BITMAP_AREA_SIZE
https://docs.oracle.com/cd/E82638_01/REFRN/CREATE_BITMAP_AREA_SIZE.htm


Linux

orcl12c@SYS> !uname -r; cat /etc/redhat-release /etc/oracle-release
4.1.12-94.3.6.el7uek.x86_64
Red Hat Enterprise Linux Server release 7.3 (Maipo)
Oracle Linux Server release 7.3

orcl12c@SYS> create pfile from spfile;

File created.

orcl12c@SYS> --2GB
orcl12c@SYS> select 2*1024*1024*1024 from dual;

2*1024*1024*1024
----------------
2147483648

orcl12c@SYS> alter system set hash_area_size = 2147483648 scope=spfile;
alter system set hash_area_size = 2147483648 scope=spfile
*
ERROR at line 1:
ORA-02017: integer value required

orcl12c@SYS> alter system set sort_area_size = 2147483648 scope=spfile;
alter system set sort_area_size = 2147483648 scope=spfile
*
ERROR at line 1:
ORA-02017: integer value required

orcl12c@SYS> alter system set bitmap_merge_area_size = 2147483648 scope=spfile;
alter system set bitmap_merge_area_size = 2147483648 scope=spfile
*
ERROR at line 1:
ORA-02017: integer value required

orcl12c@SYS> alter system set create_bitmap_area_size = 2147483648 scope=spfile;
alter system set create_bitmap_area_size = 2147483648 scope=spfile
*
ERROR at line 1:
ORA-02017: integer value required

orcl12c@SYS> --2GB - 1
orcl12c@SYS> select 2*1024*1024*1024-1 from dual;

2*1024*1024*1024-1
------------------
2147483647

orcl12c@SYS> alter system set hash_area_size = 2147483647 scope=spfile;

System altered.

orcl12c@SYS> alter system set sort_area_size = 2147483647 scope=spfile;

System altered.

orcl12c@SYS> alter system set bitmap_merge_area_size = 2147483647 scope=spfile;

System altered.

orcl12c@SYS> alter system set create_bitmap_area_size = 2147483647 scope=spfile;

System altered.

orcl12c@SYS> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
orcl12c@SYS> create spfile from pfile;

File created.

orcl12c@SYS>


Solaris 11 (x86)

SQL> !uname -r; cat /etc/release
5.11
Oracle Solaris 11.3 X86
Copyright (c) 1983, 2015, Oracle and/or its affiliates. All rights reserved.
Assembled 06 October 2015

SQL>
SQL> create pfile from spfile;

ファイルが作成されました。

SQL> --2GB
SQL> select 2*1024*1024*1024 from dual;

2*1024*1024*1024
----------------
2147483648

SQL> alter system set hash_area_size = 2147483648 scope=spfile;
alter system set hash_area_size = 2147483648 scope=spfile
*
行1でエラーが発生しました。:
ORA-02017: 整数値が必要です。


SQL> alter system set sort_area_size = 2147483648 scope=spfile;
alter system set sort_area_size = 2147483648 scope=spfile
*
行1でエラーが発生しました。:
ORA-02017: 整数値が必要です。


SQL> alter system set bitmap_merge_area_size = 2147483648 scope=spfile;
alter system set bitmap_merge_area_size = 2147483648 scope=spfile
*
行1でエラーが発生しました。:
ORA-02017: 整数値が必要です。


SQL> alter system set create_bitmap_area_size = 2147483648 scope=spfile;
alter system set create_bitmap_area_size = 2147483648 scope=spfile
*
行1でエラーが発生しました。:
ORA-02017: 整数値が必要です。


SQL> --2GB - 1
SQL> select 2*1024*1024*1024-1 from dual;

2*1024*1024*1024-1
------------------
2147483647

SQL> alter system set hash_area_size = 2147483647 scope=spfile;

システムが変更されました。

SQL> alter system set sort_area_size = 2147483647 scope=spfile;

システムが変更されました。

SQL> alter system set bitmap_merge_area_size = 2147483647 scope=spfile;

システムが変更されました。

SQL> alter system set create_bitmap_area_size = 2147483647 scope=spfile;

システムが変更されました。

SQL> shutdown immediate
データベースがクローズされました。
データベースがディスマウントされました。
ORACLEインスタンスがシャットダウンされました。
ERROR:
ORA-12514: TNS:
リスナーは接続記述子でリクエストされたサービスを現在認識していません


警告: Oracleにはもう接続されていません。
SQL> conn sys/oracle@orcl122 as sysdba
ERROR:
ORA-12514: TNS:
リスナーは接続記述子でリクエストされたサービスを現在認識していません


SQL> exit
bash-4.1$ export ORACLE_SID=orcl122
bash-4.1$ sqlplus / as sysdba

SQL*Plus: Release 12.2.0.1.0 Production on 月 2月 19 22:44:47 2018

Copyright (c) 1982, 2016, Oracle. All rights reserved.

アイドル・インスタンスに接続しました。

SQL> startup
ORACLEインスタンスが起動しました。

Total System Global Area 838860800 bytes
Fixed Size 8790120 bytes
Variable Size 356519832 bytes
Database Buffers 465567744 bytes
Redo Buffers 7983104 bytes
データベースがマウントされました。
データベースがオープンされました。
SQL> show parameter _area_size

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
bitmap_merge_area_size integer 2147483647
create_bitmap_area_size integer 2147483647
hash_area_size integer 2147483647
sort_area_size integer 2147483647
workarea_size_policy string AUTO
SQL>
SQL> shutdown immediate
データベースがクローズされました。
データベースがディスマウントされました。
ORACLEインスタンスがシャットダウンされました。
SQL>
SQL> create spfile from pfile;

File created.


Microsoft Windows

Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
に接続されました。
SQL>
SQL> $ver

Microsoft Windows [Version 10.0.16299.125]

SQL> create pfile from spfile;

ファイルが作成されました。

SQL> --2GB
SQL> select 2*1024*1024*1024 from dual;

2*1024*1024*1024
----------------
2147483648

SQL> alter system set hash_area_size = 2147483648 scope=spfile;
alter system set hash_area_size = 2147483648 scope=spfile
*
行1でエラーが発生しました。:
ORA-02017: 整数値が必要です。

SQL> alter system set sort_area_size = 2147483648 scope=spfile;
alter system set sort_area_size = 2147483648 scope=spfile
*
行1でエラーが発生しました。:
ORA-02017: 整数値が必要です。

SQL> alter system set bitmap_merge_area_size = 2147483648 scope=spfile;
alter system set bitmap_merge_area_size = 2147483648 scope=spfile
*
行1でエラーが発生しました。:
ORA-02017: 整数値が必要です。

SQL> alter system set create_bitmap_area_size = 2147483648 scope=spfile;
alter system set create_bitmap_area_size = 2147483648 scope=spfile
*
行1でエラーが発生しました。:
ORA-02017: 整数値が必要です。


SQL> --2GB - 1
SQL> select 2*1024*1024*1024-1 from dual;

2*1024*1024*1024-1
------------------
2147483647

SQL> alter system set hash_area_size = 2147483647 scope=spfile;

システムが変更されました。

SQL> alter system set sort_area_size = 2147483647 scope=spfile;

システムが変更されました。

SQL> alter system set bitmap_merge_area_size = 2147483647 scope=spfile;

システムが変更されました。

SQL> alter system set create_bitmap_area_size = 2147483647 scope=spfile;

システムが変更されました。

SQL> shutdown immediate
データベースがクローズされました。
データベースがディスマウントされました。
ORACLEインスタンスがシャットダウンされました。
ERROR:ORA-12514: TNSリスナーは接続記述子でリクエストされたサービスを現在認識していません
SQL> 警告: Oracleにはもう接続されていません。
SQL> exit
Disconnected
C:\Users\discus>set ORACLE_SID=orcl122SQL>
C:\Users\discus>sqlplus / as sysdba
SQL*Plus: Release 12.2.0.1.0 Production on 月 2月 19 22:28:45 2018
Copyright (c) 1982, 2016, Oracle. All rights reserved.
SQL>
アイドル・インスタンスに接続しました。
SQL> create spfile from pfile;
SQL>
File created.
SQL> exit
Disconnected

C:\Users\discus>


ということで、

手動PGA管理でSQL Work Area Sizeを制御する初期化パラメータで指定可能な最大サイズは

2GB -1

ということになります。(HP-UXやAIXは未確認なので情報いただけたら、ここに追記しまーす。:)

次回へつづく。




Temp落ち #1 - "Temp落ち" って?
Temp落ち #2 - PGA (Program Global Area)

| | コメント (0) | トラックバック (0)

2018年2月18日 (日)

Temp落ち #2 - PGA (Program Global Area)

Previously on Mac De Oracle
”Temp落ち”ってなに? 
という話と、それを確認できるツールをいくつか紹介したところまででした。


余談
このネタを書きながら、"Temp落ち"とは異なる理由で今回ネタにするメモリー領域の事を調べていた事を思い出しました。(懐かしい)
当時、自動PGA管理に関する情報があまりなく、新・ソートに関する検証 その1 ペンネーム グリーンペペを隅から隅まで読み試していました:)。その何年か後に、グリーンペペさんが、だれなのかを知ることに。。業界狭いですw
むか〜し、Windows(32bit)環境のOracleで、」ORA-12518が頻発していたトラブルの原因は今回のネタで取り上げるメモリー領域だった!なんてこともあるので、構造等、知ってて損はないですよ:)

では、今回のお話。

"Hash JoinやSortなどの処理をできる限りメモリー上で行う"という、そのメモリー領域とは???
PGA (Program Global Area)と呼ばれるメモリー領域のSQL Work Areaに確保されます。
また、それらのサイズを制御する初期化パラメータがあります。(後述)
PGAは、おおよそ以下のような構造で、サーバープロセスやバックグランドプロセス毎に確保されます。”ここ大切"
Pga

Pgas_processes2_2

Structure_of_pga




参考)
PGAのメモリーサイズを制御するパラメータは、以下の通り(隠しパラメータもありますが、とりあえずデフォルト前提で:)

以下の4パラメータは、手動PGA管理で利用されるパラメータで、自動PGA管理が主流となった今ではあまり利用されることはありません。(たま〜〜に使いたくなるときはありますが、結局使わなかったり、それは別の機会にでも書くことにします)

HASH_AREA_SIZE
https://docs.oracle.com/cd/E82638_01/REFRN/HASH_AREA_SIZE.htm

SORT_AREA_SIZE
https://docs.oracle.com/cd/E82638_01/REFRN/SORT_AREA_SIZE.htm

BITMAP_MERGE_AREA_SIZE
https://docs.oracle.com/cd/E82638_01/REFRN/BITMAP_MERGE_AREA_SIZE.htm

CREATE_BITMAP_AREA_SIZE
https://docs.oracle.com/cd/E82638_01/REFRN/CREATE_BITMAP_AREA_SIZE.htm

Oracle database 9.2.0以降、自動PGA管理が登場し、上記4パラメータで個別にサイズを管理する必要がなくなりました。
PGA_AGGREGATE_TARGET/PGA_AGGREATE_LIMITの2つのパラメータで自動PGA管理で行う方法に慣れておいた方が良いと思います。

余談
ちなみに、10gR1〜11gR2までは、PGA_AGGREGATE_TARGETパラメータだけだったのですが、その頃、自動PGA管理で割り当てられるサイズを検証していたネタは以下:) pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? Season2 #8 http://discus-hamburg.cocolog-nifty.com/mac_de_oracle/2010/09/pga_aggregate-7.html

ところで、ひさびさに以下マニュアルを読んで見たのですが、何度見てもモヤモヤは消えない感じのままなのがつらいです。もう少しなんとかならんかなー。
と思わなくもないです...w 作業領域の割り当てルールを明記しないのは、何故なんだろうと、ズーーーーっと考えてる。書いてくれてれば楽なのにな〜と。

Oracle® Databaseパフォーマンス・チューニング・ガイド 12cリリース2 (12.2) E72901-03
16 プログラム・グローバル領域のチューニング
https://docs.oracle.com/cd/E82638_01/TGDBA/tuning-program-global-area.htm


Oracle® Databaseリファレンス 12cリリース2 (12.2) E72905-03
PGA_AGGREGATE_LIMIT
https://docs.oracle.com/cd/E82638_01/REFRN/PGA_AGGREGATE_LIMIT.htm

12.2からResource Managerを利用して特定のコンシューマ・グループ内の各セッションに割り当てられるようになったようで、 PGAメモリー使用量に絶対制限を設定し、超過した場合にはORA-10260エラーとさせることができるようになったようですね。(まだ試したことはないのですが)

16.3.2 リソース・マネージャを使用したプログラム・グローバル領域のサイズ設定
https://docs.oracle.com/cd/E82638_01/TGDBA/tuning-program-global-area.htm

PGA_AGGREGATE_TARGET
https://docs.oracle.com/cd/E82638_01/REFRN/PGA_AGGREGATE_TARGET.htm


12cの自動PGA管理について軽く確認した感触だと、12cR2でPDB毎の制御ができるようになった事以外、大きな変化ないんじゃないかと思っているのですが、そういえばちゃんと確認したことないな。。。
次回は、昔試した方法で、12cでもPGA割り当てルールに変化はないのか確認しておきますか。。。18cはどうなるんだろ:)


続く。


Temp落ち #1 - "Temp落ち" って?

| | コメント (0) | トラックバック (0)

2017年12月 4日 (月)

”utl_file I/O” - この症状はあれの可能性が高いですね。

JPOUG Advent Calendar 2017の4日目のエントリーです。

さて、最近あまりお目にかかってなかったUTL_FILEパッケージで表データをcsvに書きだすネタにしました。

先日、UTL_FILEパッケージを利用した処理が想定以上に遅いという相談をうけました。
AWRレポートをみると、上位の待機イベントは、”utl_file I/O"。

!!!!おーーーこれは、珍しいというか、久々にみた病気w

UTL_FILEパッケージを利用したI/Oをグルグルしているとか、でかいファイル読み書きしているかの、どちらかですよねw
ということで、この症状の治療法を考えてみます。


<参考 - 環境>

MacBook:˜ system_profiler SPHardwareDataType | grep -E 'Model|Processor|Cores|Memory'
Model Name: MacBook
Model Identifier: MacBook9,1
Processor Name: Intel Core m5
Processor Speed: 1.2 GHz
Number of Processors: 1
Total Number of Cores: 2
Memory: 8 GB

ホストOS
MacBook:˜ discus$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.13.1
BuildVersion: 17B1003

MacBook:˜ discus$ VBoxManage -version
5.1.30r118389


ゲストOSとOracle Database
orcl@SYS> !uname -a
Linux localhost.localdomain 4.1.12-94.3.6.el7uek.x86_64 #2 SMP Tue May 30 19:25:15 PDT 2017 x86_64 x86_64 x86_64 GNU/Linux

orcl@SYS> !cat /etc/oracle-release
Oracle Linux Server release 7.3

orcl@SYS>
orcl@SYS> select * from v$version;

BANNER CON_ID
-------------------------------------------------------------------------------- ----------
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production 0
PL/SQL Release 12.2.0.1.0 - Production 0
CORE 12.2.0.1.0 Production 0
TNS for Linux: Version 12.2.0.1.0 - Production 0
NLSRTL Version 12.2.0.1.0 - Production 0

UTL_FILEでファイル出力する際、ちょっとした手順の漏れが性能差として現れてしまうことがあります。
表の行長は数百バイト程度ですが、行数は数千万〜数億行なんていう状況だと、性能差が顕著に現れてしまうので注意が必要です。

以下の表、セグメントサイズは1GB程度ですが、行数は1千万行以上あります。
この表データをUTL_FILEパッケージを利用してcsvに出力してみます。

ORCL@SCOTT> select segment_name,sum(bytes)/1024/1024/1024 "GB" from user_segments group by segment_name;

SEGMENT_NAME GB
------------------------------ ----------
ABOUT_100BYTES_ROWS .9140625
PK_ABOUT_100BYTES_ROWS .171875


ORCL@SCOTT> select count(1) from about_100bytes_rows;

COUNT(1)
----------
10737420

表の1行は100bytes(改行コード含)です。

ORCL@SCOTT%gt; r
1 SELECT
2 LENGTH(
3 TO_CHAR(id,'FM000000000000000000000000000009')
4 ||','||FOO
5 ) row_length
6 FROM
7 about_100bytes_rows
8 WHERE
9* rownum <= 1

ROW_LENGTH
----------
99

次の2つのコードの赤太文字部分に着目してください。
その部分が異なるだけで処理時間に大きな差が出ます。

DECLARE
cDIR_NAME CONSTANT VARCHAR2(30) := 'FILES_DIR';
cFILE_NAME CONSTANT VARCHAR2(128) := 'no_writebuffering_'||TO_CHAR(systimestamp, 'rrmmddhh24miss.ff')||'.txt';
cBufferSize CONSTANT BINARY_INTEGER := 32767;
cOpenMode CONSTANT VARCHAR2(2) := 'w';
fileHandle UTL_FILE.FILE_TYPE;

cBulkReadLimit CONSTANT PLS_INTEGER := 324;
TYPE tBulkReadArray IS TABLE OF VARCHAR2(8192) INDEX BY BINARY_INTEGER;
bulkReadArray tBulkReadArray;
CURSOR cur_about100bytesRow IS
SELECT
TO_CHAR(id,'FM000000000000000000000000000009')
||','||FOO
AS csvrow
FROM
about_100bytes_rows
;
BEGIN
OPEN cur_about100bytesRow;
fileHandle := UTL_FILE.FOPEN(cDIR_NAME, cFILE_NAME, cOpenMode, cBufferSize);
LOOP
FETCH cur_about100bytesRow
BULK COLLECT INTO bulkReadArray
LIMIT cBulkReadLimit;

EXIT WHEN bulkReadArray.COUNT = 0;

FOR i IN bulkReadArray.FIRST..bulkReadArray.LAST LOOP
UTL_FILE.PUT_LINE(
file => fileHandle
, buffer => bulkReadArray(i)
, autoflush => true
);
END LOOP;
END LOOP;
UTL_FILE.FFLUSH(fileHandle);
UTL_FILE.FCLOSE(fileHandle);
CLOSE cur_about100bytesRow;
EXCEPTION
WHEN OTHERS THEN
IF UTL_FILE.IS_OPEN(fileHandle) THEN
UTL_FILE.FCLOSE(fileHandle);
END IF;

IF cur_about100bytesRow%ISOPEN THEN
CLOSE cur_about100bytesRow;
END IF;
RAISE;
END;
/


PL/SQLプロシージャが正常に完了しました。

経過: 00:02:27.05


DECLARE
cDIR_NAME CONSTANT VARCHAR2(30) := 'FILES_DIR';
cFILE_NAME CONSTANT VARCHAR2(128) := 'writebuffering_'||TO_CHAR(systimestamp, 'rrmmddhh24miss.ff')||'.txt';
cBufferSize CONSTANT BINARY_INTEGER := 32767;
cOpenMode CONSTANT VARCHAR2(2) := 'w';
fileHandle UTL_FILE.FILE_TYPE;
buffer VARCHAR2(32767);

cBulkReadLimit CONSTANT PLS_INTEGER := 324;
TYPE tBulkReadArray IS TABLE OF VARCHAR2(8192) INDEX BY BINARY_INTEGER;
bulkReadArray tBulkReadArray;
CURSOR cur_about100bytesRow IS
SELECT
TO_CHAR(id,'FM000000000000000000000000000009')
||','||FOO
AS csvrow
FROM
about_100bytes_rows
;
BEGIN
OPEN cur_about100bytesRow;
fileHandle := UTL_FILE.FOPEN(cDIR_NAME, cFILE_NAME, cOpenMode, cBufferSize);
LOOP
FETCH cur_about100bytesRow
BULK COLLECT INTO bulkReadArray
LIMIT cBulkReadLimit;

EXIT WHEN bulkReadArray.COUNT = 0;

buffer := NULL;
FOR i IN bulkReadArray.FIRST..bulkReadArray.LAST LOOP
buffer := buffer || bulkReadArray(i) || UTL_TCP.CRLF;
END LOOP;
UTL_FILE.PUT(fileHandle, buffer);
UTL_FILE.FFLUSH(fileHandle);
END LOOP;
UTL_FILE.FFLUSH(fileHandle);
UTL_FILE.FCLOSE(fileHandle);
CLOSE cur_about100bytesRow;
EXCEPTION
WHEN OTHERS THEN
IF UTL_FILE.IS_OPEN(fileHandle) THEN
UTL_FILE.FCLOSE(fileHandle);
END IF;

IF cur_about100bytesRow%ISOPEN THEN
CLOSE cur_about100bytesRow;
END IF;
RAISE;
END;
/


PL/SQLプロシージャが正常に完了しました。

経過: 00:00:43.96


何が違うかお分ですよね!
UTL_FILE.PUT_LINE/UTL_FILE.PUTが違う!!w
その部分は重要ではなく、100Bytes単位に書き込んでいるか、約32KB単位で書き込んでいるかが重要なんです。

UTL_FILEは最大32767バイトのバッファを利用できますが、前者はバッファを有効利用せず、100Bytes毎に書き出しています。後者は約32KB単位で書き出しています。

その差はAWRレポートからも見えてきます。


AWRレポート(一部抜粋)
UTL_FILEパッケージによるI/Oの待機は、”utl_file I/O”という待機イベントで現れます。

Avg Waitは短いですが、理由は100バイト単位の小さいなサイズの書き込みを繰り返しているわけなので、そんなとこでしょう。

Top 10 Foreground Events by Total Wait Time

Total Wait Avg % DB Wait
Event Waits Time (sec) Wait time Class
------------------------------ ----------- ---------- --------- ------ --------
DB CPU 147.4 99.3
utl_file I/O 32,212,266 49.5 1.54us 33.3 User I/O
direct path read 1,881 1.2 620.61us .8 User I/O
resmgr:cpu quantum 1 .1 85.85ms .1 Schedule
db file sequential read 17 0 .98ms .0 User I/O
PGA memory operation 90 0 35.13us .0 Other
latch: shared pool 1 0 1.05ms .0 Concurre
control file sequential read 80 0 12.83us .0 System I
Disk file operations I/O 6 0 73.67us .0 User I/O
SQL*Net message to client 2 0 9.00us .0 Network


一方、約32KB単位でバッファリングして書き出している場合、Waits回数が激減しています。
Avg Waitsは大きくなっていますが、書き出しサイズにほぼ比例しているので想定通りというところ。

Top 10 Foreground Events by Total Wait Time

Total Wait Avg % DB Wait
Event Waits Time (sec) Wait time Class
------------------------------ ----------- ---------- --------- ------ --------
DB CPU 45 98.5
utl_file I/O 66,288 27.4 413.54us 60.1 User I/O
direct path read 1,881 1 550.71us 2.3 User I/O
db file sequential read 88 0 443.38us .1 User I/O
direct path write 2 0 4.69ms .0 User I/O
control file sequential read 80 0 33.25us .0 System I
latch: shared pool 1 0 2.38ms .0 Concurre
Disk file operations I/O 4 0 323.50us .0 User I/O
PGA memory operation 79 0 15.73us .0 Other
SQL*Net message to client 4 0 20.25us .0 Network

utl_file.put/put_lineでcsvを出力しているdeviceのiostat(util%)
まだまだ余裕があるのでI/Oで詰まっているのではなく、UTL_FILE.PUT/PUT_LINEの使い方の影響が大きいということですね。
20171203_202342


最後に、
UTL_FILEパッケージの入出力時にはバッファの有効利用をお忘れなく。(つい忘れちゃうこともあるので、急いでるときとかw)
扱うデータが多い場合は得に。

そして、みなさま、
メリークリスマス(まだエントリーを書くかもしれませんがw)
#JPOUG

| | コメント (0) | トラックバック (0)

2017年11月 7日 (火)

DBMS_ADVISOR.CREATE_FILE()プロシージャは、Diagnostic/Tuning Pack不要らしいということの確認

Previously on Mac De Oracle



余談

DBMS_ADVISOR.CREATE_FILEとなっているがライセンス上、diagnostic/tuning packライセンスはなくてもアクセスしてできるように読み取れるのだけと、もしかすると、この影響で、DBMS_ADVISOR.CREATE_FILEの存在は知っていても使ってないのかあるのかな??

以下のマニュアルを読む限り、Diagnostic/Tuning Packでは、DBMS_ADVISORパッケージ全体ではなく、Diagnostic/Tuning Packに関連するパラメータを与える必要のある機能についての制限であることしか記載されていない。
つまり、DBMS_ADVISOR.CREATE_FILE()に関して言えば、Diagnostic/Tuning Pack特有の機能ではないから利用可能なはず。 ←間違ってたらツッコミ希望w

Oracle® Databaseライセンス情報 12cリリース1 (12.1) 2 オプションおよびパック
https://docs.oracle.com/cd/E49329_01/license.121/b71334/options.htm



なんてことを書いたところ、

control_management_pack_access=none

でも使えるとなら間違いなくないんじゃないの?
というコメントがあったので試してみました。 マニュアルの通りだと思われます。ということですね。FAQ!

orcl@SYS> show parameter control_management_pack_access

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
control_management_pack_access string NONE
orcl@SYS>
orcl@SYS> l
1 DECLARE
2 reportClob CLOB := EMPTY_CLOB();
3 BEGIN
4 reportClob := 'test test test';
5 DBMS_ADVISOR.CREATE_FILE(
6 buffer => reportClob
7 ,location => 'REP_DIR'
8 ,filename => 'test.txt'
9 );
10* END;
orcl@SYS> /

PL/SQLプロシージャが正常に完了しました。

経過: 00:00:00.23
orcl@SYS> !ls report
test.txt

orcl@SYS> !cat report/test.txt
test test test


DBMS_SQLTUNE.PACK_STGTAB_SQLSETって、例外投げんのかよw
SQL Tuning Setのキャプチャから退避までのスクリプト(やっつけ)
SQL Tuning Set (STS)のフィルタリング
DBMS_SQLTUNE.REPORT_ANALYSIS_TASK()ファンクションで生成されるCLOB型のレポートをファイルに保存する簡単な方法

| | コメント (0) | トラックバック (0)

2017年11月 3日 (金)

DBMS_SQLTUNE.REPORT_ANALYSIS_TASK()ファンクションで生成されるCLOB型のレポートをファイルに保存する簡単な方法

Previously on Mac De Oracle
STSとの格闘というかSPAとの格闘に疲れてきたところw ですが、
SQL Tuning Set (STS)のフィルタリング
などで、SQLSETを程よい大きさに分割するところまでたどり着きましたw

今回は、いくつかある細かい分析方法については、一旦、置いといて、
分析レポートを保存する簡単な方法についての備忘録

分析などにこの記事も参考になると思いますが、紹介している記事でも分析レポートをファイルに保存する方法はSQL*Plusのコマンドを駆使して行われています。
個人的には少々やぼったい方法かなと感じている方法なんですが、以前はこんなやりかたが多かったようにも思います。

var rep CLOB
...略...
EXEC :rep := DBMS_SQLSPA.REPORT_ANALYSIS_TASK('STSNAM','TEXT',...
spo hoge_report.txt
print :rep
spo off

SQL*PlusとPL/SQLが行ったり来たりするところや、ループ制御しにくいので、この方法は避けたい。。。。

かといって、DBMS_OUTPUT.PUT_LINEで行おうとするとset linesize等の制御が面倒くさいし
結局、SQL*Plusの機能にも依存してしまうので、いまひとつ。

PL/SQLだけで行う方法として、UTL_FILEパッケージを利用してファイル出力する方法もありますが、
UTL_FILEパッケージで提供されているAPIはlow levelなものばかりなので、急ぎの時にはめんどくさくて、やだw

もっと簡単なやつないの?????

あります!w

DBMS_ADVISOR.CREATE_FILE(buffer, location, filename)

なぜ、UTL_FILEパッケージに入れてくれないんだw と思いたくなる方もいるかと思いますが、 理由はよくわかりませんw
(UTL_FILEパッケージはlow levelなAPIだけだから入れたくないのかも、かも、かも。と思ってますが、DBMS_ADVISORパッケージに入れるとは。どういうつもりだ!w)

UTL_FILE.CREATE_FILE()ってあったほうが直感的に探しやすくないかw UTL_FILEみて無い!!
となると、他を探すこともあまりなくなって、結局、コード書いてる場面を多く見てる>< 


余談
DBMS_ADVISOR.CREATE_FILEとなっているがライセンス上、diagnostic/tuning packライセンスはなくてもアクセスしてできるように読み取れるのだけと、もしかすると、この影響で、DBMS_ADVISOR.CREATE_FILEの存在は知っていても使ってないのかあるのかな??

以下のマニュアルを読む限り、Diagnostic/Tuning Packでは、DBMS_ADVISORパッケージ全体ではなく、Diagnostic/Tuning Packに関連するパラメータを与える必要のある機能についての制限であることしか記載されていない。
つまり、DBMS_ADVISOR.CREATE_FILE()に関して言えば、Diagnostic/Tuning Pack特有の機能ではないから利用可能なはず。 ←間違ってたらツッコミ希望w

Oracle® Databaseライセンス情報 12cリリース1 (12.1) 2 オプションおよびパック
https://docs.oracle.com/cd/E49329_01/license.121/b71334/options.htm


とりあえず、SQLSETの分析レポートをDBMS_ADVISOR.CREATE_FILE()を利用して保存するやっつけスクリプトを作ってみました
これを元に育てていけるかなw


実行例)

注)STS20171102というSQLSETを事前に作成してあります。


orcl@SYS> select * from v$version;

BANNER CON_ID
-------------------------------------------------------------------------------- ----------
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production 0
PL/SQL Release 12.2.0.1.0 - Production 0
CORE 12.2.0.1.0 Production 0
TNS for Linux: Version 12.2.0.1.0 - Production 0
NLSRTL Version 12.2.0.1.0 - Production 0


orcl@SYS> select owner,name,statement_count,created from dba_sqlset order by name;

OWNER NAME STATEMENT_COUNT CREATED
---------- ------------------------------ --------------- ---------
SPAUSER STS20171102 1003 02-NOV-17


spa.sqlのパラメータは、SQLSETと分析レポートの出力ディレクトリオブジェクトとSQLを実行するスキーマ向けのDBリンクです。

スクリプトの概要
・初回の分析(SQLSETで元のSQLを分析)
・2回目の分析(新環境でSQLを実行して分析)
・初回と2回目の比較レポート作成/保存
・レポートを出力後、分析に利用したタスクを削除



orcl@SYS> @spa STS20171102 rep_dir link_4_target

task name:STS20171102 has been droped.
***END***

PL/SQL procedure successfully completed.

分析レポートは、ディレクトリオブジェクトに対応づけられたパスに保存されます

orcl@SYS> !ls -l report
-rw-r--r-- 1 oracle oinstall 13688 11月 3 02:44 DIFF_STS20171102171103024433.txt

orcl@SYS> !cat report/DIFF_STS20171102171103024433.txt

General Information
---------------------------------------------------------------------------------------------

Task Information: Workload Information:
--------------------------------------------- ---------------------------------------------
Task Name : STS20171102 SQL Tuning Set Name : STS20171102
Task Owner : SYS SQL Tuning Set Owner : SPAUSER
Description : Total SQL Statement Count : 1003

Execution Information:
---------------------------------------------------------------------------------------------
Execution Name : DIFF_STS20171102 Started : 11/03/2017 02:44:26
Execution Type : COMPARE PERFORMANCE Last Updated : 11/03/2017 02:44:29
Description : Global Time Limit : UNLIMITED
Scope : COMPREHENSIVE Per-SQL Time Limit : UNUSED
Status : COMPLETED Number of Errors : 0
Number of Unsupported SQL : 4

Analysis Information:
---------------------------------------------------------------------------------------------
Before Change Execution: After Change Execution:
--------------------------------------------- ---------------------------------------------
Execution Name : SOURCE_STS20171102 Execution Name : TARGET_STS20171102
Execution Type : CONVERT SQLSET Execution Type : TEST EXECUTE REMOTE
Scope : COMPREHENSIVE Database Link : LINK_4_TARGET
Status : COMPLETED Scope : COMPREHENSIVE
Started : 11/03/2017 02:44:04 Status : COMPLETED
Last Updated : 11/03/2017 02:44:04 Started : 11/03/2017 02:44:04
Global Time Limit : UNLIMITED Last Updated : 11/03/2017 02:44:18
Per-SQL Time Limit : UNUSED Global Time Limit : UNLIMITED
Per-SQL Time Limit : UNUSED
Number of Errors : 0

---------------------------------------------
Comparison Metric: ELAPSED_TIME
------------------
Workload Impact Threshold: 1%
--------------------------
SQL Impact Threshold: 1%
----------------------

Report Summary
---------------------------------------------------------------------------------------------

Projected Workload Change Impact:
-------------------------------------------
Overall Impact : 0%
Improvement Impact : 0%
Regression Impact : 0%

SQL Statement Count
-------------------------------------------
SQL Category SQL Count Plan Change Count
Overall 999 490
Unchanged 995 490
Unsupported 4 0

Top 100 SQL Sorted by Absolute Value of Change Impact on the Workload
---------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------
| | | Impact on | Execution | Metric | Metric | Impact | Plan |
| object_id | sql_id | Workload | Frequency | Before | After | on SQL | Change |
-----------------------------------------------------------------------------------------
| 1477 | 7hys3h7ysgf9m | .1% | 1 | 14630 | 33 | 99.77% | n |
| 1811 | cw6vxf0kbz3v1 | .03% | 1 | 3602 | 24 | 99.33% | n |
| 1175 | 2s9mmb6g8kbqb | .01% | 1 | 1537 | 20 | 98.7% | n |

...中略...

| 1691 | az25yp5qunj77 | .01% | 1 | 882 | 20 | 97.73% | n |
| 1896 | faun6bjrjqr17 | .01% | 1 | 881 | 19 | 97.84% | n |
| 1956 | g7a2tmw1nrxbh | .01% | 1 | 881 | 19 | 97.84% | n |
-----------------------------------------------------------------------------------------
Note: time statistics are displayed in microseconds
---------------------------------------------------------------------------------------------


---------------------------------------------------------------------------------------------

スクリプトは以下のとおり、無名PL/SQLブロックにしてあります。
レポートのタイプなどは固定にしてますが、それらも含めてパラメータにしてもいいかも。

ちなみに、このエントリの本題である、DBMS_ADVISOR.CREATE_FILE()は赤字部分です!

orcl@SYS> !cat spa.sql

set serveroutput on
DECLARE
report_clob CLOB;
cSQLSET_OWNER VARCHAR2(30) := 'SPAUSER';
cSQLSET_NAME VARCHAR2(20) := UPPER('&1');
cEXECUTION_NAME_PREFIX_SOURCE VARCHAR2(7) := 'SOURCE_';
cEXECUTION_NAME_PREFIX_TARGET VARCHAR2(7) := 'TARGET_';
cEXECUTION_NAME_PREFIX_DIFF VARCHAR2(5) := 'DIFF_';
cREPORT_TYPE CONSTANT VARCHAR2(4) := 'text';
cFILE_EXTENTION CONSTANT VARCHAR2(5) := '.txt';
cDIRECTORY_NAME CONSTANT VARCHAR2(30) := UPPER('&2');
cDB_LINK_4_PARSING_SCHEMA CONSTANT VARCHAR2(128) := UPPER('&3');
stmt_task VARCHAR2(64);

PROCEDURE drop_task (iTASK_NAME VARCHAR2)
IS
BEGIN
FOR task_rec IN (
SELECT
task_name
FROM
dba_advisor_tasks
WHERE
task_name = iTASK_NAME
AND advisor_name = 'SQL Performance Analyzer'
) LOOP
DBMS_OUTPUT.PUT_LINE(
'task name:'||task_rec.task_name||' has been droped.'
);
DBMS_SQLPA.DROP_ANALYSIS_TASK(
task_name => task_rec.task_name
);
END LOOP;
END drop_task;
BEGIN
--Create analysis task
stmt_task := DBMS_SQLPA.CREATE_ANALYSIS_TASK(
sqlset_name => cSQLSET_NAME
,basic_filter => 'parsing_schema_name in (''SCOTT'')'
,sqlset_owner => cSQLSET_OWNER
,task_name => cSQLSET_NAME
);

--SQL Analysis on Source DB
DBMS_SQLPA.EXECUTE_ANALYSIS_TASK(
task_name => cSQLSET_NAME
,execution_type => 'CONVERT SQLSET'
,execution_name =>
cEXECUTION_NAME_PREFIX_SOURCE
|| cSQLSET_NAME
,execution_params =>
DBMS_ADVISOR.ARGLIST(
'sqlset_name', cSQLSET_NAME
,'sqlset_owner', cSQLSET_OWNER
)
);

--SQL Analysis on Target DB
DBMS_SQLPA.EXECUTE_ANALYSIS_TASK(
task_name => cSQLSET_NAME
,execution_type => 'EXECUTE'
,execution_name =>
cEXECUTION_NAME_PREFIX_TARGET
|| cSQLSET_NAME
,execution_params =>
DBMS_ADVISOR.ARGLIST(
'DATABASE_LINK', cDB_LINK_4_PARSING_SCHEMA
,'EXECUTE_FULLDML', 'TRUE'
)
);

--Comparison Source and Target Analysys
DBMS_SQLPA.EXECUTE_ANALYSIS_TASK(
task_name => cSQLSET_NAME
,execution_type => 'COMPARE'
,execution_name =>
cEXECUTION_NAME_PREFIX_DIFF
|| cSQLSET_NAME
,execution_params =>
DBMS_ADVISOR.ARGLIST(
'PLAN_LINES_COMPARISON','ALWAYS'
)
);

--Make comparison report
report_clob := DBMS_SQLPA.REPORT_ANALYSIS_TASK(
task_name => cSQLSET_NAME
,execution_name =>
cEXECUTION_NAME_PREFIX_DIFF
|| cSQLSET_NAME
,type => cREPORT_TYPE
,level => 'typical'
,section => 'summary'
);

--Save comparison report
DBMS_ADVISOR.CREATE_FILE(
buffer => report_clob
,location => cDIRECTORY_NAME
,filename =>
cEXECUTION_NAME_PREFIX_DIFF
||cSQLSET_NAME
||TO_CHAR(systimestamp, 'RRMMDDHH24MISS')
||cFILE_EXTENTION
);


--Drop Task
drop_task(cSQLSET_NAME);
DBMS_OUTPUT.PUT_LINE('***END***');
EXCEPTION
WHEN OTHERS THEN
drop_task(cSQLSET_NAME);
RAISE;
END;
/


DBMS_SQLTUNE.PACK_STGTAB_SQLSETって、例外投げんのかよw
SQL Tuning Setのキャプチャから退避までのスクリプト(やっつけ)
SQL Tuning Set (STS)のフィルタリング

| | コメント (0) | トラックバック (0)

2017年10月30日 (月)

SQL Tuning Set (STS)のフィルタリング

Previously on Mac De Oracle
前回は、やっつけすくりぷとを書いたところまででした。

ということで、今回のやっつけスクリプトの準備というかアイデア

SQLSET大量のSQL文キャプチャされていて、SQLSETにキャプチャされている大量のSQL文を一括でSPAでまわしたりすることが辛い場合があります。
そんなときはどうすればよいか。。なやみますよね。。。ほんと。。
SQL Performance AnalyzerによるSQLパフォーマンス比較実行例(API)

SQLSETから、より細かなSQLSETにほぼ当分に分割し、新たなSQLSETを作成したいような場合もあるかもしれません。
そんな時はどうするか?

手取りばやくやるなら、ORA_HASH()が便利ですよね。(SQLSETの全表走査はさけられないのですが、Exaならw)

たとえば、以下のSQLSETがあったとして、300件程度に均等に分割したいという場合。
ora_hash()のバケット数はだいたい12ぐらいでできそうですね。

orcl@SYS> select name,statement_count,created from dba_sqlset order by name;

NAME STATEMENT_COUNT CREATED
------------------------------ --------------- ---------
STS20171029 3819 29-OCT-17

orcl@SYS> select statement_count/300 from dba_sqlset where name='STS20171029';

STATEMENT_COUNT/300
-------------------
12.73

いい感じに分割できそうです。

orcl@SYS> r
1 select
2 ora_hash(sql_id,12) as hash#
3 ,count(sql_id)
4 from
5 table(dbms_sqltune.select_sqlset(
6 sqlset_name=>'STS20171029'
7 ,basic_filter=>null
8 ))
9 group by
10 ora_hash(sql_id,12)
11* order by 1

HASH# COUNT(SQL_ID)
---------- -------------
0 289
1 293
2 278
3 296
4 297
5 281
6 282
7 298
8 288
9 304
10 305
11 298
12 310

13 rows selected.


実際に利用するには、basic_filterでwhere句の条件文そのものを書いてあげます。サブクエリも書けますが、データ量が多い場合は性能面に注意しながらいろいろ試してみるといいと思います。
basic_filterでは、SQLSET_ROWオブジェクト・タイプの属性を利用したフィルタリングができるのですが、インジェクションですよね。構文を見ている限り;)
Oracle® Database PL/SQLパッケージおよびタイプ・リファレンス 12c リリース1 (12.1) SQLSET_ROWオブジェクト・タイプ

orcl@SYS> set serveroutput on
orcl@SYS> r
1 begin
2 for i in 0..12 loop
3 for sqlset_rec in
4 (
5 select count(sql_id) as num_sql
6 from
7 table(dbms_sqltune.select_sqlset(
8 sqlset_name=>'STS20171029'
9 ,basic_filter=>'ora_hash(sql_id,12)='||i
10 ))
11 )
12 loop
13 dbms_output.put_line('hash#='||to_char(i,'fm99')||':'||sqlset_rec.num_sql);
14 end loop;
15 end loop;
16* end;
hash#=0:289
hash#=1:293
hash#=2:278
hash#=3:296
hash#=4:297
hash#=5:281
hash#=6:282
hash#=7:298
hash#=8:288
hash#=9:304
hash#=10:305
hash#=11:298
hash#=12:310

PL/SQL procedure successfully completed.

ハッシュ値10でsql_id数をカウント!
うまくできそうですよね。

orcl@SYS> r
1 select
2 count(sql_id)
3 from
4 table(dbms_sqltune.select_sqlset(
5 sqlset_name=>'STS20171029'
6 ,basic_filter=>'ora_hash(sql_id,12) = 10'
7* ))

COUNT(SQL_ID)
-------------
305

参考
Oracle® Database PL/SQLパッケージおよびタイプ・リファレンス 12c リリース1 (12.1) DBMS_SQLTUNE
Oracle® Database SQL言語リファレンス 12cリリース1 (12.1) ORA_HASH


DBMS_SQLTUNE.PACK_STGTAB_SQLSETって、例外投げんのかよw
SQL Tuning Setのキャプチャから退避までのスクリプト(やっつけ)

| | コメント (0) | トラックバック (0)

2017年10月 7日 (土)

SQL Tuning Setのキャプチャから退避までのスクリプト(やっつけ)

Previously on Mac De Oracleは
DBMS_SQLTUNE.PACK_STGTAB_SQLSETって、例外投げんのかよwという備忘録でした、

今回は
以下のURLで紹介されているSTS (SQL Tuning Set)へSQLの性能統計や実行計画をキャプチャしちゃおう!
Oracle DatabaseのSTS(SQL Tuning Set) を活用して、SQLの性能統計や実行計画をキャプチャする。 / ora_gonsuke777

というSTS機能を利用した応用編w (という名のやっつけスクリプト) を書いたので、備忘録

STSでSQLの実行計画や性能統計をキャプチャするのはいいのですが、キャプチャするデータが多い場合、SYSAUX表領域を圧迫したり、拡張したりしてしまうことがあります。
本番環境で表領域サイズにドキドキする日々を送るのも嫌なので、一定期間STSヘキャプチャしたあとSTSを退避、削除したいよね。という方向の話が湧いてきたりしますw

で、書いたやっつけスクリプトが以下。(11g2と12cR1でテスト済み)
STSをキャプチャする時間、インターバル、そして、STSを退避するためのステージング表を作成するスキーマ名と、エクスポートに必要なディレクトリオブジェクト名を
パラメータに取ります。キャプチャする時間とインターバルは秒を指定します。エクスポートは、DBMS_DATAPUMPパッケージを利用しています。
今回利用したパッケージの詳細は以下を参照のこと:)

Oracle® Database PL/SQLパッケージおよびタイプ・リファレンス 11g リリース2(11.2) B56262-06
- DBMS_SQLTUNEサブプログラムの要約
- 46 DBMS_DATAPUMP

なお、本スクリプト実施前に、DataPump Export向けディレクトリオブジェクトを、ステージング表を作成するユーザを作成しておく必要があります。
(後半の実行例は、STS_EXP_DIRディレクトリオブジェクト、STSUSRユーザを事前に作成)
sts_capture.sql

SET SERVEROUTPUT ON
/*
Arguments :
&1 - Schema name for sts staging table
&2 - Directory object name for Data Pump Export
&3 - Duration for SQLSET capturing (sec)
&4 - Sampling interval for SQLSET (sec)
*/
DECLARE
-- for STS capturing and packing
vStsName VARCHAR2(30) := 'STS' || TO_CHAR(SYSDATE, 'YYYYMMDDHH24MISS');
cTimeLimit CONSTANT POSITIVE := &3;
cInterval CONSTANT POSITIVE := &4;
cCaptureOpt CONSTANT VARCHAR2(20) := 'MERGE';
cStagingSchema CONSTANT VARCHAR2(30) := UPPER('&1');
v4Debug VARCHAR2(50);

-- for DataPump Export Job
cDirectory CONSTANT VARCHAR2(20) := UPPER('&2');
IsSkipExport BOOLEAN := false;
i NUMBER;
vDataPumpJobHandle NUMBER;
vProgress_ratio NUMBER;
vJobState VARCHAR2(30);
oLogEntry ku$_LogEntry;
oStatus ku$_Status;
BEGIN
DBMS_OUTPUT.ENABLE;

-- STS名にInstance#を付加
-- (RAC環境での複数ノードでの実行を考慮してインスタンス番号を付加)
v4Debug := 'Build STSNAME';
FOR instance_rec IN (SELECT TO_CHAR(instance_number) AS inum FROM v$instance) LOOP
vStsName := vStsName || instance_rec.inum;
END LOOP;

-- SQLSETの作成
v4Debug := 'CREATE_SQLSET';
DBMS_SQLTUNE.CREATE_SQLSET (
sqlset_name => vStsName
,sqlset_owner => NULL
);

-- カーソルキャッシュからSTSへ定期キャプチャ
v4Debug := 'CAPTURE_CURSOR_CACHE_SQLSET';
DBMS_SQLTUNE.CAPTURE_CURSOR_CACHE_SQLSET (
sqlset_name => vStsName
,time_limit => cTimeLimit
,repeat_interval => cInterval
,capture_option => cCaptureOpt
,capture_mode => DBMS_SQLTUNE.MODE_REPLACE_OLD_STATS
,basic_filter =>
'parsing_schema_name NOT IN (
''SYS'', ''SYSTEM'', ''APEX_050000'', ''APEX_040000'', ''SYSMAN''
)'
,sqlset_owner => NULL
);

-- STSエクスポート向けステージング表の作成
v4Debug := 'CREATE_STGTAB_SQLSET';
DBMS_SQLTUNE.CREATE_STGTAB_SQLSET (
table_name => vStsName
,schema_name => cStagingSchema
,db_version => NULL
);

-- STSをステージング表へパック
v4Debug := 'PACK_STGTAB_SQLSET';
BEGIN
DBMS_SQLTUNE.PACK_STGTAB_SQLSET (
sqlset_name => vStsName
,sqlset_owner => NULL
,staging_table_name => vStsName
,staging_schema_owner => cStagingSchema
,db_version => NULL
);
EXCEPTION
WHEN OTHERS THEN
IF sqlcode = -15701 THEN
IsSkipExport := true;
DBMS_OUTPUT.PUT_LINE('*** Info - No data packed from SQLSET ***');
ELSE
RAISE;
END IF;
END;

IF IsSkipExport = false
THEN
-- ステージング表を表モードでエクスポート
-- エクスポートのモード等の設定
v4Debug := 'OPEN';
vDataPumpJobHandle
:= DBMS_DATAPUMP.OPEN (
operation => 'EXPORT'
,job_mode => 'TABLE'
,remote_link => NULL
,job_name => vStsName
,version => 'LATEST'
);

-- エスポートダンプファイルとログファイルの設定
v4Debug := 'ADD_FILE - dumpfile';
DBMS_DATAPUMP.ADD_FILE (
handle => vDataPumpJobHandle
,filename => vStsName || '.dmp'
,directory => cDirectory
,filetype => DBMS_DATAPUMP.KU$_FILE_TYPE_DUMP_FILE
);

v4Debug := 'ADD_FILE - logfile';
DBMS_DATAPUMP.ADD_FILE (
handle => vDataPumpJobHandle
,filename => vStsName || '.log'
,directory => cDirectory
,filetype => DBMS_DATAPUMP.KU$_FILE_TYPE_LOG_FILE
);

-- メターデータフィルタの設定
-- エクスポート対象表のスキーマ
v4Debug := 'METADATA_FILTER - schema name';
DBMS_DATAPUMP.METADATA_FILTER (
handle => vDataPumpJobHandle
,name => 'SCHEMA_LIST'
,value => '''' || cStagingSchema || ''''
);

-- エクスポート対象表
v4Debug := 'METADATA_FILTER - table name';
DBMS_DATAPUMP.METADATA_FILTER (
handle => vDataPumpJobHandle
,name => 'NAME_LIST'
,value => '''' || vStsName || ''''
);

-- DataPump Exportジョブの実行
v4Debug := 'START_JOB';
DBMS_DATAPUMP.START_JOB (
handle => vDataPumpJobHandle
);

-- DataPump Exportジョブ状況監視と終了判定
-- ジョブ終了または停止されるまでループして待機
v4Debug := 'JOB_STATE';
vProgress_ratio := 0;
vJobState := 'UNDEFINED';
WHILE (vJobState != 'COMPLETED') AND (vJobState != 'STOPPED') LOOP
DBMS_DATAPUMP.GET_STATUS (
vDataPumpJobHandle
,DBMS_DATAPUMP.KU$_STATUS_JOB_ERROR
+ DBMS_DATAPUMP.KU$_STATUS_JOB_STATUS
+ DBMS_DATAPUMP.KU$_STATUS_WIP
,-1
,vJobState
,oStatus
);

-- 処理中(Work-In-Progress : WIP)または、
-- エラーのいずれかのメッセージを受け取ったら表示
IF (BITAND(oStatus.mask, DBMS_DATAPUMP.KU$_STATUS_WIP) != 0)
THEN
oLogEntry := oStatus.wip;
ELSE
IF (BITAND(oStatus.mask, DBMS_DATAPUMP.KU$_STATUS_JOB_ERROR) != 0)
THEN
oLogEntry := oStatus.error;
ELSE
oLogEntry := NULL;
END IF;
END IF;
IF oLogEntry IS NOT NULL
THEN
i := oLogEntry.FIRST;
WHILE i IS NOT NULL LOOP
DBMS_OUTPUT.PUT_LINE(oLogEntry(i).LogText);
i := oLogEntry.NEXT(i);
END LOOP;
END IF;
END LOOP;

-- Data Pump Exportジョブ終了
DBMS_DATAPUMP.DETACH(vDataPumpJobHandle);
END IF;

-- ステージング表の削除
v4Debug := 'Drop staging table';
EXECUTE IMMEDIATE 'DROP TABLE ' || cStagingSchema || '.' || vStsName || ' PURGE';

-- SQLSETの削除
v4Debug := 'DROP_SQLSET';
DBMS_SQLTUNE.DROP_SQLSET (
sqlset_name => vStsName
);

EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(sqlerrm());
DBMS_OUTPUT.PUT_LINE(v4Debug);
RAISE;
END;
/
EXIT


STSが空ではない場合の実行例
キャプチャ処理は600秒実行しキャプチャ間隔は120秒、キャプチャ終了後、STSUSRスキーマにステージング表を作成、STSをステージング表へパック、ステージング表を指定したディレクトリオブジェクト以下にDataPump Exportしています。

[oracle@guppy ˜]$ sqlplus system@orcl @sts_capture stsusr sts_exp_dir 10*60 2*60

SQL*Plus: Release 12.1.0.2.0 Production on Fri Oct 6 15:13:53 2017

Copyright (c) 1982, 2014, Oracle. All rights reserved.

Enter password:

Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options

old 4: cTimeLimit CONSTANT POSITIVE := &3;
new 4: cTimeLimit CONSTANT POSITIVE := 10*60;
old 5: cInterval CONSTANT POSITIVE := &4;
new 5: cInterval CONSTANT POSITIVE := 2*60;
old 7: cStagingSchema CONSTANT VARCHAR2(30) := UPPER('&1');
new 7: cStagingSchema CONSTANT VARCHAR2(30) := UPPER('stsusr');
old 11: cDirectory CONSTANT VARCHAR2(20) := UPPER('&2');
new 11: cDirectory CONSTANT VARCHAR2(20) := UPPER('sts_exp_dir');
Starting "SYS"."STS201710061513571":
Estimate in progress using BLOCKS method...
Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
Total estimation using BLOCKS method: 1.062 MB
Processing object type TABLE_EXPORT/TABLE/TABLE
Processing object type TABLE_EXPORT/TABLE/INDEX/STATISTICS/INDEX_STATISTICS
Processing object type TABLE_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
Processing object type TABLE_EXPORT/TABLE/STATISTICS/MARKER
. . exported "STSUSR"."STS201710061513571" 51.55 KB 1 rows
Master table "SYS"."STS201710061513571" successfully loaded/unloaded
******************************************************************************
Dump file set for SYS.STS201710061513571 is:
/home/oracle/exp/STS201710061513571.dmp
Job "SYS"."STS201710061513571" successfully completed at Fri Oct 6 15:26:50 2017 elapsed 0 00:00:47

PL/SQL procedure successfully completed.

STSが空の場合の例
ステージング表へのSTSのパックやDataPump Exportの実行をパイパス。STSが空であることを表示して終了します。
なお、以下の例ではキャプチャ時間と間隔は意図的に短くしてあります。

[oracle@guppy  ˜]$ sqlplus system@orcl @sts_capture stsusr sts_exp_dir 2*60 60

SQL*Plus: Release 12.1.0.2.0 Production on Fri Oct 6 16:04:55 2017

Copyright (c) 1982, 2014, Oracle. All rights reserved.

Enter password:

Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options

old 4: cTimeLimit CONSTANT POSITIVE := &3;
new 4: cTimeLimit CONSTANT POSITIVE := 2*60;
old 5: cInterval CONSTANT POSITIVE := &4;
new 5: cInterval CONSTANT POSITIVE := 60;
old 7: cStagingSchema CONSTANT VARCHAR2(30) := UPPER('&1');
new 7: cStagingSchema CONSTANT VARCHAR2(30) := UPPER('stsusr');
old 11: cDirectory CONSTANT VARCHAR2(20) := UPPER('&2');
new 11: cDirectory CONSTANT VARCHAR2(20) := UPPER('sts_exp_dir');
*** Info - No data packed from SQLSET ***

PL/SQL procedure successfully completed.


このスクリプトをshellに組み込んでcronでも定期実行したりDBMS_SCHEDULERで定期実行するのも良いかな。
オレオレサンプルなので、より便利に改造して使ってね。v

| | コメント (0) | トラックバック (0)

2017年9月 1日 (金)

ORA-12034 #2

前回の通り、高速リフレッシュの間にdata pump export / importを完了させれば、ORA-12034なんて起きないはず。

VirtualBoxの環境は試験開始前のスナップショットで戻してあります
20170415_14044_2

SQL*Plus: Release 12.1.0.2.0 Production on Mon Aug 28 20:57:49 2017

Copyright (c) 1982, 2014, Oracle. All rights reserved.

Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options

orcl@MVIEW_SCHEMA1> @mview_info_c
Connected.

¥Session altered.

ROWNER RNAME REFGROUP JOB B INTERVAL NEXT_DATE CON_ID
-------------------- -------------------- ---------- ---------- - -------------------- ------------------- ----------
MVIEW_SCHEMA1 MV_MASTER 61 81 N sysdate+5/1440 2017/08/28 21:00:54 3

MVIEW_NAME REFRES REFRESH_ LAST_REF AFTER_FAST_REFRESH COMPILE_STATE
------------------------------ ------ -------- -------- ------------------- -------------------
MV_MASTER DEMAND FAST FAST UNDEFINED VALID

JOB LOG_USER SCHEMA_USER LAST_DATE NEXT_DATE INTERVAL FAILURES WHAT
---------- -------------------- -------------------- ------------------- ------------------- -------------------- ---------- ------------------------------------------------------------
81 MVIEW_SCHEMA1 MVIEW_SCHEMA1 2017/08/28 20:55:54 2017/08/28 21:00:54 sysdate+5/1440 0 dbms_refresh.refresh('"MVIEW_SCHEMA1"."MV_MASTER"');

前回は5分間隔だったので、余裕をもたせて30分にしてあります。
本番環境で5分間隔の高速リフレッシュを30分にしたり、止めたりってことはかなり敷居が高いとは思いますが、そのあたりは空気を読んで対応する必要があるかと。 :)

orcl12c@SYS> conn mview_schema1@orcl
Connected.
orcl@MVIEW_SCHEMA1> alter materialized view mv_master refresh next sysdate+30/1440;

Materialized view altered.

orcl@MVIEW_SCHEMA1> @mview_info_c
Connected.

Session altered.


ROWNER RNAME REFGROUP JOB B INTERVAL NEXT_DATE CON_ID
-------------------- -------------------- ---------- ---------- - -------------------- ------------------- ----------
MVIEW_SCHEMA1 MV_MASTER 61 81 N sysdate+30/1440 2017/08/28 21:30:36 3

MVIEW_NAME REFRES REFRESH_ LAST_REF AFTER_FAST_REFRESH COMPILE_STATE
------------------------------ ------ -------- -------- ------------------- -------------------
MV_MASTER DEMAND FAST FAST UNDEFINED VALID

JOB LOG_USER SCHEMA_USER LAST_DATE NEXT_DATE INTERVAL FAILURES WHAT
---------- -------------------- -------------------- ------------------- ------------------- -------------------- ---------- ------------------------------------------------------------
81 MVIEW_SCHEMA1 MVIEW_SCHEMA1 2017/08/28 20:55:54 2017/08/28 21:30:36 sysdate+30/1440 0 dbms_refresh.refresh('"MVIEW_SCHEMA1"."MV_MASTER"');

準備は整ったので、高速リフレッシュが終わったタイミングでexportからimportまでをやっつけちゃいます!
まずはエクスポート

Connected to: Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
Starting "SYSTEM"."SYS_EXPORT_SCHEMA_01": system/********@orcl directory=workdir dumpfile=mview_schema1.dmp logfile=exp_mview_schema1.log schemas=mview_schema1
Estimate in progress using BLOCKS method...
Processing object type SCHEMA_EXPORT/TABLE/TABLE_DATA
Total estimation using BLOCKS method: 64 KB
Processing object type SCHEMA_EXPORT/USER
Processing object type SCHEMA_EXPORT/SYSTEM_GRANT
Processing object type SCHEMA_EXPORT/DEFAULT_ROLE
Processing object type SCHEMA_EXPORT/TABLESPACE_QUOTA
Processing object type SCHEMA_EXPORT/PRE_SCHEMA/PROCACT_SCHEMA
Processing object type SCHEMA_EXPORT/DB_LINK
Processing object type SCHEMA_EXPORT/TABLE/TABLE
Processing object type SCHEMA_EXPORT/TABLE/COMMENT
Processing object type SCHEMA_EXPORT/TABLE/CONSTRAINT/CONSTRAINT
Processing object type SCHEMA_EXPORT/TABLE/INDEX/STATISTICS/INDEX_STATISTICS
Processing object type SCHEMA_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
Processing object type SCHEMA_EXPORT/STATISTICS/MARKER
Processing object type SCHEMA_EXPORT/MATERIALIZED_VIEW
Processing object type SCHEMA_EXPORT/JOB
Processing object type SCHEMA_EXPORT/REFRESH_GROUP
. . exported "MVIEW_SCHEMA1"."MV_MASTER" 5.5 KB 2 rows
Master table "SYSTEM"."SYS_EXPORT_SCHEMA_01" successfully loaded/unloaded
******************************************************************************
Dump file set for SYSTEM.SYS_EXPORT_SCHEMA_01 is:
/u01/userhome/oracle/mview_schema1.dmp
Job "SYSTEM"."SYS_EXPORT_SCHEMA_01" successfully completed at Mon Aug 28 21:05:00 2017 elapsed 0 00:00:56

[oracle@vbgeneric ˜]$ sqlplus master_schema@orcl

SQL*Plus: Release 12.1.0.2.0 Production on Mon Aug 28 21:05:19 2017

Copyright (c) 1982, 2014, Oracle. All rights reserved.


Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options

orcl@MASTER_SCHEMA> select count(*) from mlog$_master;

COUNT(*)
----------
0

orcl@MASTER_SCHEMA> conn mview_schema1@orcl
Connected.

orcl@MVIEW_SCHEMA1> @mview_info_c
Connected.

Session altered.


ROWNER RNAME REFGROUP JOB B INTERVAL NEXT_DATE CON_ID
-------------------- -------------------- ---------- ---------- - -------------------- ------------------- ----------
MVIEW_SCHEMA1 MV_MASTER 61 81 N sysdate+30/1440 2017/08/28 21:30:36 3

MVIEW_NAME REFRES REFRESH_ LAST_REF AFTER_FAST_REFRESH COMPILE_STATE
------------------------------ ------ -------- -------- ------------------- -------------------
MV_MASTER DEMAND FAST FAST UNDEFINED VALID

JOB LOG_USER SCHEMA_USER LAST_DATE NEXT_DATE INTERVAL FAILURES WHAT
---------- -------------------- -------------------- ------------------- ------------------- -------------------- ---------- ------------------------------------------------------------
81 MVIEW_SCHEMA1 MVIEW_SCHEMA1 2017/08/28 20:55:54 2017/08/28 21:30:36 sysdate+30/1440 0 dbms_refresh.refresh('"MVIEW_SCHEMA1"."MV_MASTER"');

次にインポートしてMviewを複製! 

orcl12c@SYS> conn system@orcl2
Connected.
orcl2@SYSTEM> create directory workdir as '/u01/userhome/oracle';

Directory created.

orcl2@SYSTEM> exit
Disconnected from Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
[oracle@vbgeneric ˜]$ impdp system@orcl2 directory=workdir dumpfile=mview_schema1.dmp logfile=imp_mview_schema1.dmp

Import: Release 12.1.0.2.0 - Production on Mon Aug 28 21:07:13 2017

Copyright (c) 1982, 2014, Oracle and/or its affiliates. All rights reserved.

Connected to: Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
Master table "SYSTEM"."SYS_IMPORT_FULL_01" successfully loaded/unloaded
Starting "SYSTEM"."SYS_IMPORT_FULL_01": system/********@orcl2 directory=workdir dumpfile=mview_schema1.dmp logfile=imp_mview_schema1.dmp
Processing object type SCHEMA_EXPORT/USER
Processing object type SCHEMA_EXPORT/SYSTEM_GRANT
Processing object type SCHEMA_EXPORT/DEFAULT_ROLE
Processing object type SCHEMA_EXPORT/TABLESPACE_QUOTA
Processing object type SCHEMA_EXPORT/PRE_SCHEMA/PROCACT_SCHEMA
Processing object type SCHEMA_EXPORT/DB_LINK
Processing object type SCHEMA_EXPORT/TABLE/TABLE
Processing object type SCHEMA_EXPORT/TABLE/TABLE_DATA
. . imported "MVIEW_SCHEMA1"."MV_MASTER" 5.5 KB 2 rows
Processing object type SCHEMA_EXPORT/TABLE/COMMENT
Processing object type SCHEMA_EXPORT/TABLE/CONSTRAINT/CONSTRAINT
Processing object type SCHEMA_EXPORT/TABLE/INDEX/STATISTICS/INDEX_STATISTICS
Processing object type SCHEMA_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
Processing object type SCHEMA_EXPORT/STATISTICS/MARKER
Processing object type SCHEMA_EXPORT/MATERIALIZED_VIEW
Processing object type SCHEMA_EXPORT/JOB
Processing object type SCHEMA_EXPORT/REFRESH_GROUP
Job "SYSTEM"."SYS_IMPORT_FULL_01" successfully completed at Mon Aug 28 21:07:40 2017 elapsed 0 00:00:23

複製完了!!!!
結果はいかに...

[oracle@vbgeneric ˜]$ sqlplus mview_schema1@orcl2

SQL*Plus: Release 12.1.0.2.0 Production on Mon Aug 28 21:08:09 2017

Copyright (c) 1982, 2014, Oracle. All rights reserved.


Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options

orcl2@MVIEW_SCHEMA1> @mview_info_c
Connected.

Session altered.

ROWNER RNAME REFGROUP JOB B INTERVAL NEXT_DATE CON_ID
-------------------- -------------------- ---------- ---------- - -------------------- ------------------- ----------
MVIEW_SCHEMA1 MV_MASTER 61 81 N sysdate+30/1440 2017/08/28 22:00:46 5
MVIEW_SCHEMA1 MV_MASTER 61 81 N sysdate+30/1440 2017/08/28 22:00:46 3

MVIEW_NAME REFRES REFRESH_ LAST_REF AFTER_FAST_REFRESH COMPILE_STATE
------------------------------ ------ -------- -------- ------------------- -------------------
MV_MASTER DEMAND FAST FAST UNDEFINED VALID
MV_MASTER DEMAND FAST FAST UNDEFINED VALID

JOB LOG_USER SCHEMA_USER LAST_DATE NEXT_DATE INTERVAL FAILURES WHAT
---------- -------------------- -------------------- ------------------- ------------------- -------------------- ---------- ------------------------------------------------------------
81 MVIEW_SCHEMA1 MVIEW_SCHEMA1 2017/08/28 21:30:46 2017/08/28 22:00:46 sysdate+30/1440 0 dbms_refresh.refresh('"MVIEW_SCHEMA1"."MV_MASTER"');
81 MVIEW_SCHEMA1 MVIEW_SCHEMA1 2017/08/28 21:30:46 2017/08/28 22:00:46 sysdate+30/1440 0 dbms_refresh.refresh('"MVIEW_SCHEMA1"."MV_MASTER"');

予想通り成功しました!

エクスポート〜インポートによるMVIEW複製までを高速リフレッシュの間に行うことが可能ならば例のエラーは回避できることが確認できました。
が、
小さなMViewならまだしも、巨大なMView、巨大なMViewが複数あるリフレッシュグループだったりすると、それはもう大変な作業になることは想像できます。
大人の事情でMViewの高速リフレッシュを止められない、とか高速リフレッシュ間隔が非常短い場合には無理しないで、ほかの手を考えた方が良いと思います。
ただし、他の手を進めるにも時間には余裕を持った方がいいですよね。なんでギリギリなんだろうねと、よく思います。
夏休みの最後の1週間で宿題全部やりきるみたいなのは嫌ですよねw
20170802_140801




Data Pumpも癖モノだよね〜w その1 - queryパラメーターの解析タイミング
Data Pumpも癖モノだよね〜w その2 - Materialized ViewをTableとして移行する
Data Pumpも癖モノだよね〜w その3 - dbms_job と dbms_scheduler との複雑な関係
Data Pumpも癖モノだよね〜w その4 - schemaモードでMviewを他のPDBへ複製
Data Pumpも癖モノだよね〜w その4と1/2 - schemaモードでMviewを他のPDBへ複製 (紛らわしいステータスw)
Data Pumpも癖モノだよね〜w その5 - schemaモードでMviewを他のPDBへ複製(オプジェクトパス de 絞り込み)
Data Pumpも癖モノだよね〜w その6 - schemaモードでMviewを他のPDBへ複製(オプジェクトパスが不足すると...)
ORA-12034

| | コメント (0) | トラックバック (0)

2017年8月31日 (木)

ORA-12034

一ヶ月の家庭内、ワンオペも無事終了したので、ブログも今年前半のペースで再開か!?w

ということで、
以前ちょっとだけ書いた高速リフレッシュを止めてないと完全リフレッシュが必要になってしまう。タイミングの問題にフォーカスしてみようと思います。

どのようなタイミングの問題かというと、

ORA-12034: materialized view log on "xxxxxx"."xxxxxxx" younger than last refresh

出会った方も意外と多かったりしてw 

前述のエラーは、materialized view logが絡んいるので、”高速リフレッシュ”時に発生するエラーです!
高速リフレッシュを行なっている環境でこの状態になってしまうと、”高速リフレッシュ”の再開には”完全リフレッシュ”が必須となってしまうところが怖いというか面倒くさいところ。
マスターサイトも含めて同期するサイズが小さければ完全リフレッシュも面倒なことにならない場合もありますが、数十GB以上の巨大なマテビューだったら、どうします???
マテリアライズドビューのリフレッシュ間隔が短いシステムだと、完全リフレッシュに要する時間が大問題になることも... (色々な状況が想定されていない構成だと、そうなりやすい.....なw

もう少し簡単に言うと、
materialized view logの伝播が必要なデータ有無に関係なく、リフレッシュ時刻を跨いてしまうかどうか! なんですよね、これ。

実際にどうなるか、materialized view logは空の状態で、Data Pumpも癖モノだよね〜w その2 - Materialized ViewをTableとして移行する
の環境を利用して再現させてみます。環境の詳細は、Data Pumpも癖モノだよね〜w その4 - schemaモードでMviewを他のPDBへ複製参照のこと。


VirtualBoxのスナップショットから基本レプリケーション環境構築済みの状態(以前いろいろ行った試験前の状態)に戻してあります。
20170415_14044

まず、高速リフレッシュの状態がどうなっているか確認してみると....5分間隔(INTERVAL列)で動作中であることがわかりますよね!(DBMS_JOBのINTERVALの指定方法っ非直感的わかりづらいので早くなくなってほしいw)
直近の高速リフレッシュが終わり、MLOGも0件。つまりマテリアライズドビューに反映する必要のあるデータは存在しない状態にしてあります。


orcl@MVIEW_SCHEMA1> select job,log_user,schema_user,last_date,next_date,interval,failures,what from user_jobs;

JOB LOG_USER SCHEMA_USER LAST_DATE NEXT_DATE INTERVAL FAILURES WHAT
---------- -------------------- -------------------- ------------------- ------------------- -------------------- ---------- ------------------------------------------------------------
81 MVIEW_SCHEMA1 MVIEW_SCHEMA1 2017/08/28 09:00:44 2017/08/28 09:05:44 sysdate+5/1440 0 dbms_refresh.refresh('"MVIEW_SCHEMA1"."MV_MASTER"');

前述の状態(5分間隔の高速リフレッシュが動作中の状態)で、次の高速リフレッシュが実行されるまでの間にマテリアライズドビュー関連オブジェクトを含むschemaを丸ごとエクスポートします(他のデータベースへ複製するために)
エラーを再現するData Pump Export、Importと高速リフレッシュ間隔との間合いは下図の通り
20170802_140338

上図の通りの流れでData Pump ExportからImportまでを行い、ORA-12034の発生状況を確認

Connected to: Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
Starting "SYSTEM"."SYS_EXPORT_SCHEMA_01": system/********@orcl directory=workdir dumpfile=mview_schema1.dmp logfile=exp_mview_schema1.log schemas=mview_schema1
Estimate in progress using BLOCKS method...
Processing object type SCHEMA_EXPORT/TABLE/TABLE_DATA
Total estimation using BLOCKS method: 64 KB
Processing object type SCHEMA_EXPORT/USER
Processing object type SCHEMA_EXPORT/SYSTEM_GRANT
Processing object type SCHEMA_EXPORT/DEFAULT_ROLE
Processing object type SCHEMA_EXPORT/TABLESPACE_QUOTA
Processing object type SCHEMA_EXPORT/PRE_SCHEMA/PROCACT_SCHEMA
Processing object type SCHEMA_EXPORT/DB_LINK
Processing object type SCHEMA_EXPORT/TABLE/TABLE
Processing object type SCHEMA_EXPORT/TABLE/COMMENT
Processing object type SCHEMA_EXPORT/TABLE/CONSTRAINT/CONSTRAINT
Processing object type SCHEMA_EXPORT/TABLE/INDEX/STATISTICS/INDEX_STATISTICS
Processing object type SCHEMA_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
Processing object type SCHEMA_EXPORT/STATISTICS/MARKER
Processing object type SCHEMA_EXPORT/MATERIALIZED_VIEW
Processing object type SCHEMA_EXPORT/JOB
Processing object type SCHEMA_EXPORT/REFRESH_GROUP
. . exported "MVIEW_SCHEMA1"."MV_MASTER" 5.5 KB 2 rows
Master table "SYSTEM"."SYS_EXPORT_SCHEMA_01" successfully loaded/unloaded
******************************************************************************
Dump file set for SYSTEM.SYS_EXPORT_SCHEMA_01 is:
/u01/userhome/oracle/mview_schema1.dmp
Job "SYSTEM"."SYS_EXPORT_SCHEMA_01" successfully completed at Mon Aug 28 09:02:48 2017 elapsed 0 00:00:54


念のためマスターサイトでMLOGの件数を確認しておきます。
マテビューサイトと同期する必要のあるデータはないことが確認できます。

orcl@MASTER_SCHEMA> select count(*) from mlog$_master;

COUNT(*)
----------
0


という確認を行なっている間いに高速リフレッシュが実行されました! (LAST_DATE列、NEXT_DATE列、FAILURES列から正常にリフレッシュされたことを確認できます)

orcl@MVIEW_SCHEMA1> select job,log_user,schema_user,last_date,next_date,interval,failures,what from user_jobs;
JOB LOG_USER SCHEMA_USER LAST_DATE NEXT_DATE INTERVAL FAILURES WHAT
---------- -------------------- -------------------- ------------------- ------------------- -------------------- ---------- ------------------------------------------------------------
81 MVIEW_SCHEMA1 MVIEW_SCHEMA1 2017/08/28 09:05:48 2017/08/28 09:10:48 sysdate+5/1440 0 dbms_refresh.refresh('"MVIEW_SCHEMA1"."MV_MASTER"');

まず、異なるPDBにディレクトリオブジェクトを作成して、schemaごとインポートします。
この時点で以前のエントリにもあるようにORCL:master_schema.masterをマスターサイトするmviewが、ORCL:mview_schema1.mview_masterとORCL2:mview_schema1.mview_masterという構成になります。


orcl2@SYSTEM> create directory workdir as '/u01/userhome/oracle';

Directory created.


Starting "SYSTEM"."SYS_IMPORT_FULL_01": system/********@orcl2 directory=workdir dumpfile=mview_schema1.dmp logfile=imp_mview_schema1.dmp
Processing object type SCHEMA_EXPORT/USER
Processing object type SCHEMA_EXPORT/SYSTEM_GRANT
Processing object type SCHEMA_EXPORT/DEFAULT_ROLE
Processing object type SCHEMA_EXPORT/TABLESPACE_QUOTA
Processing object type SCHEMA_EXPORT/PRE_SCHEMA/PROCACT_SCHEMA
Processing object type SCHEMA_EXPORT/DB_LINK
Processing object type SCHEMA_EXPORT/TABLE/TABLE
Processing object type SCHEMA_EXPORT/TABLE/TABLE_DATA
. . imported "MVIEW_SCHEMA1"."MV_MASTER" 5.5 KB 2 rows
Processing object type SCHEMA_EXPORT/TABLE/COMMENT
Processing object type SCHEMA_EXPORT/TABLE/CONSTRAINT/CONSTRAINT
Processing object type SCHEMA_EXPORT/TABLE/INDEX/STATISTICS/INDEX_STATISTICS
Processing object type SCHEMA_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
Processing object type SCHEMA_EXPORT/STATISTICS/MARKER
Processing object type SCHEMA_EXPORT/MATERIALIZED_VIEW
Processing object type SCHEMA_EXPORT/JOB
Processing object type SCHEMA_EXPORT/REFRESH_GROUP
Job "SYSTEM"."SYS_IMPORT_FULL_01" successfully completed at Mon Aug 28 10:02:09 2017 elapsed 0 00:00:22


インポートが無事終わったので、高速リフレッシュの状態を確認!!

おおおおおおおお〜〜、インポートしたschemaに含まれるMVIEWは高速リフレッシュに失敗しています。
なんということでしょうw(狙い通りなので、わざとらしいですねw)

なお、LAST_REF列がCOMPLETEという完全リフレッシュを示すステータスになっていますが、これはで確認下通り、昔からこんな動作だった曖昧な記憶があるので仕様だと思われますが、
インポート時に完全リフレッシュしているわけでもないのに、完全リフレッシュ扱いとされている紛らわしい状態になります。(このステータスが影響している可能性もありそうな...)

orcl2@MVIEW_SCHEMA1> @mview_info_c
Connected.

Session altered.

ROWNER RNAME REFGROUP JOB B INTERVAL NEXT_DATE CON_ID
-------------------- -------------------- ---------- ---------- - -------------------- ------------------- ----------
MVIEW_SCHEMA1 MV_MASTER 61 81 N sysdate+5/1440 2017/08/28 10:06:46 3
MVIEW_SCHEMA1 MV_MASTER 61 81 N sysdate+5/1440 2017/08/28 10:04:22 5


MVIEW_NAME REFRES REFRESH_ LAST_REF AFTER_FAST_REFRESH COMPILE_STATE
------------------------------ ------ -------- -------- ------------------- -------------------
MV_MASTER DEMAND FAST FAST UNDEFINED VALID
MV_MASTER DEMAND FAST COMPLETE UNDEFINED VALID


JOB LOG_USER SCHEMA_USER LAST_DATE NEXT_DATE INTERVAL FAILURES WHAT
---------- -------------------- -------------------- ------------------- ------------------- -------------------- ---------- ------------------------------------------------------------
81 MVIEW_SCHEMA1 MVIEW_SCHEMA1 2017/08/28 10:01:46 2017/08/28 10:06:46 sysdate+5/1440 0 dbms_refresh.refresh('"MVIEW_SCHEMA1"."MV_MASTER"');
81 MVIEW_SCHEMA1 MVIEW_SCHEMA1 2017/08/28 10:04:22 sysdate+5/1440 1 dbms_refresh.refresh('"MVIEW_SCHEMA1"."MV_MASTER"');


高速リフレッシュのが実行され2度目の失敗、failusers列が2になっています。いずれ高速リフレッシュジョブは自動的に停止されます。
(自動停止される前に問題に対処すればそのまま継続されます)

orcl2@MVIEW_SCHEMA1> @mview_info_c
Connected.

Session altered.

ROWNER RNAME REFGROUP JOB B INTERVAL NEXT_DATE CON_ID
-------------------- -------------------- ---------- ---------- - -------------------- ------------------- ----------
MVIEW_SCHEMA1 MV_MASTER 61 81 N sysdate+5/1440 2017/08/28 10:08:26 5
MVIEW_SCHEMA1 MV_MASTER 61 81 N sysdate+5/1440 2017/08/28 10:06:46 3


MVIEW_NAME REFRES REFRESH_ LAST_REF AFTER_FAST_REFRESH COMPILE_STATE
------------------------------ ------ -------- -------- ------------------- -------------------
MV_MASTER DEMAND FAST FAST UNDEFINED VALID
MV_MASTER DEMAND FAST COMPLETE UNDEFINED VALID


JOB LOG_USER SCHEMA_USER LAST_DATE NEXT_DATE INTERVAL FAILURES WHAT
---------- -------------------- -------------------- ------------------- ------------------- -------------------- ---------- ------------------------------------------------------------
81 MVIEW_SCHEMA1 MVIEW_SCHEMA1 2017/08/28 10:01:46 2017/08/28 10:06:46 sysdate+5/1440 0 dbms_refresh.refresh('"MVIEW_SCHEMA1"."MV_MASTER"');
81 MVIEW_SCHEMA1 MVIEW_SCHEMA1 2017/08/28 10:08:26 sysdate+5/1440 2 dbms_refresh.refresh('"MVIEW_SCHEMA1"."MV_MASTER"');

では、原因を調査してみましょう!


P列(POSSIBLE列)の REFRESH_FAST行がNになっていて高速リフレッシュできない状態になっています。
コメントにはmv log is newer than last full refresh 記載されています。 このメッセージ冒頭で書いたメッセージと微妙に違うのですが、

orcl2@MVIEW_SCHEMA1> @?/rdbms/admin/utlxmv

Table created.

orcl2@MVIEW_SCHEMA1> exec dbms_mview.explain_mview('MV_MASTER','TEST01');

PL/SQL procedure successfully completed.

orcl2@MVIEW_SCHEMA1> SELECT mvname,capability_name,related_text,related_num,msgno,possible,msgtxt,seq FROM mv_capabilities_table;

MVNAME CAPABILITY_NAME RELATED_TEXT RELATED_NUM MSGNO P MSGTXT SEQ
------------------------------ ------------------------------ -------------------- ----------- ---------- - ------------------------------------------------------------------------------------------ ----------
MV_MASTER PCT N 1
MV_MASTER REFRESH_COMPLETE Y 1002
MV_MASTER REFRESH_FAST N 2003
MV_MASTER REWRITE N 3004
MV_MASTER PCT_TABLE MASTER 52 2068 N relation is not a partitioned table 4005
MV_MASTER REFRESH_FAST_AFTER_INSERT MASTER_SCHEMA.MASTER 2077 N mv log is newer than last full refresh 5006
MV_MASTER REFRESH_FAST_AFTER_ONETAB_DML 2146 N see the reason why REFRESH_FAST_AFTER_INSERT is disabled 6007
MV_MASTER REFRESH_FAST_AFTER_ANY_DML 2161 N see the reason why REFRESH_FAST_AFTER_ONETAB_DML is disabled 7008
MV_MASTER REFRESH_FAST_PCT 2197 N PCT FAST REFRESH is not possible if query contains a remote table 8009
MV_MASTER REWRITE_FULL_TEXT_MATCH MASTER 52 2099 N mv references a remote table or view in the FROM list 9010
MV_MASTER REWRITE_FULL_TEXT_MATCH 2159 N query rewrite is disabled on the materialized view 9011
MV_MASTER REWRITE_PARTIAL_TEXT_MATCH 2159 N query rewrite is disabled on the materialized view 10012
MV_MASTER REWRITE_GENERAL 2159 N query rewrite is disabled on the materialized view 11013
MV_MASTER REWRITE_PCT 2158 N general rewrite is not possible or PCT is not possible on any of the detail tables 12014
MV_MASTER PCT_TABLE_REWRITE MASTER 52 2068 N relation is not a partitioned table 13015

15 rows selected.


試しに手動で高速リフレッシュさせてみます。

orcl2@MVIEW_SCHEMA1> exec dbms_refresh.refresh('"MVIEW_SCHEMA1"."MV_MASTER"');
BEGIN dbms_refresh.refresh('"MVIEW_SCHEMA1"."MV_MASTER"'); END;

*
ERROR at line 1:
ORA-12034: materialized view log on "MASTER_SCHEMA"."MASTER" younger than last refresh
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2821
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 3058
ORA-06512: at "SYS.DBMS_IREFRESH", line 687
ORA-06512: at "SYS.DBMS_REFRESH", line 195
ORA-06512: at line 1


冒頭で説明した高速リフレッシュ時のエラーが発生していることがわかります。
そして、.......
このエラーが発生してしまうと、完全リフレッシュで回復させるしかありません!!!!! 


参考:
新規マテリアライズド・ビュー・サイトでの高速リフレッシュ・エラー

"新規マテリアライズド・ビュー・サイトでマテリアライズド・ビュー作成中に、マスター表またはマスター・マテリアライズド・ビューのマテリアライズド・ビュー・ログがパージされる場合があります。これが発生すると、次のエラーが検出される場合があります。

ORA-12004 REFRESH FAST cannot be used for materialized view materialized_view_name
ORA-12034 materialized view log on materialized_view_name younger than last refresh"


回避策として使えそうな方法は....
高速リフレッシュを停止して行う方法もあります(止められないシステムもあるので大人の事情しだいでしょうけど)
デプロイメントテンプレートで対応できそうな要件か十分検討、検証した上でやる必要があると思います。(完全リフレッシュするマテビューが巨大すぎて完全リフレッシュだけで作業時間オーバーなんてこともありえますから)

マニュアルに記載されている回避方法ってのもあるけど、手順がめんどくさい>< な。 可能なら止めちゃった方が楽そうだが、大人の事情が絡んでるとそうもいかないだろうし、結局めんどくさいw
めんどくさいの嫌いなので試したこともないんだけど、時間があったら回避できるか試してみるか....な。

新規マテリアライズド・ビュー・サイトを追加するときの問題の回避


次回は、高速リフレッシュを跨がないように、したら回避できるよね。と言うお話へつづく
リフレッシュの間に終わらないとNGだけどw 、高速リフレッシュの間にexport/importが終わればこの問題は発生しない。。わけで。
次回のネタのイメージ(リフレッシュをまた跨らなければ例のエラーは発生しないという確認:)
20170802_140351




Data Pumpも癖モノだよね〜w その1 - queryパラメーターの解析タイミング

Data Pumpも癖モノだよね〜w その2 - Materialized ViewをTableとして移行する

Data Pumpも癖モノだよね〜w その3 - dbms_job と dbms_scheduler との複雑な関係

Data Pumpも癖モノだよね〜w その4 - schemaモードでMviewを他のPDBへ複製

Data Pumpも癖モノだよね〜w その4と1/2 - schemaモードでMviewを他のPDBへ複製 (紛らわしいステータスw)

Data Pumpも癖モノだよね〜w その5 - schemaモードでMviewを他のPDBへ複製(オプジェクトパス de 絞り込み)

Data Pumpも癖モノだよね〜w その6 - schemaモードでMviewを他のPDBへ複製(オプジェクトパスが不足すると...)

| | コメント (0) | トラックバック (0)

2017年5月 2日 (火)

あまりにもネタになってないので、少しだけ sysresv のことを書いといた

共有メモリやセマフォセットの数などの確認は、ipcsでほぼ足りてるわけですが。(複数インスタンスが起動している場合を除く)
あまりにもネタになってないので、少しだけ sysresvのことを書いといた:)

[oracle@vbgeneric ˜]$ sysresv

IPC Resources for ORACLE_SID "orcl12c" :
Maximum shared memory segment size (shmmax): 4398046511104 bytes
Total system shared memory (shmall): 4398046511104 bytes
Total system shared memory count (shmmni): 4096
*********************** Dumping ipcs output ********************

------ Message Queues --------
key msqid owner perms used-bytes messages

------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 0 oracle 600 8802304 173
0x00000000 32769 oracle 600 822083584 87
0x00000000 65538 oracle 600 7974912 87
0x21485470 98307 oracle 600 16384 87
0x00000000 262148 oracle 600 524288 2 dest
0x00000000 294917 oracle 600 4194304 2 dest
0x00000000 393222 oracle 600 33554432 2 dest
0x00000000 491527 oracle 600 4194304 2 dest
0x00000000 524296 oracle 600 1048576 2 dest

------ Semaphore Arrays --------
key semid owner perms nsems
0x245b195c 163840 oracle 600 152
0x245b195d 196609 oracle 600 152
0x245b195e 229378 oracle 600 152

*********************** End of ipcs command dump **************


***************** Dumping Resource Limits(s/h) *****************
core file size 0 KB/UNLIMITED
data seg size UNLIMITED/UNLIMITED
scheduling priority 0 KB/0 KB
file size UNLIMITED/UNLIMITED
pending signals 30 KB/30 KB
max locked memory 128 GB/128 GB
max memory size UNLIMITED/UNLIMITED
open files 64 KB/64 KB
POSIX message queues 800 KB/800 KB
real-time priority 0 KB/0 KB
stack size 32 MB/32 MB
cpu time UNLIMITED/UNLIMITED
max user processes 16 KB/16 KB
virtual memory UNLIMITED/UNLIMITED
file locks UNLIMITED/UNLIMITED

***************** End of Resource Limits Dump ******************
Maximum map count configured per process: 65530
Total /dev/shm size: 4050014208 bytes, used: 98304 bytes
Shared Memory:
ID KEY
32769 0x00000000
65538 0x00000000
0 0x00000000
98307 0x21485470
Semaphores:
ID KEY
163840 0x245b195c
196609 0x245b195d
229378 0x245b195e
Oracle Instance alive for sid "orcl12c"
[oracle@vbgeneric ˜]$
[oracle@vbgeneric ˜]$  ipcs -sb

------ Semaphore Arrays --------
key semid owner perms nsems
0x245b195c 163840 oracle 600 152
0x245b195d 196609 oracle 600 152
0x245b195e 229378 oracle 600 152
[oracle@vbgeneric ˜]$  ipcs -st

------ Semaphore Operation/Change Times --------
semid owner last-op last-changed
163840 oracle Tue May 2 01:35:32 2017 Tue May 2 01:26:30 2017
196609 oracle Not set Tue May 2 01:26:30 2017
229378 oracle Tue May 2 01:26:35 2017 Tue May 2 01:26:30 2017

| | コメント (0) | トラックバック (0)

2014年8月19日 (火)

pivotとSQL*PlusとSETコマンドと #2

昨日の続きですw

v$sys_time_modelの列データを行データへpivotで変換し、かつシェルで定期的に取得してみたものの、出力形式は今ひとつ。 iostatやvmstatのように出力したい。

前回のエントリーの出力結果は以下の通りでした。

[oracle ˜]$ ./sample.sh

SQL*Plus: Release 12.1.0.2.0 Production on 日 8月 17 21:10:47 2014

Copyright (c) 1982, 2014, Oracle. All rights reserved.


Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
に接続されました。
21:10:48 SCOTT>
DB_TIME DB_CPU BG_TIME BG_CPU
------------------------------- ------------------------------- ------------------------------- -------------------------------
66172667 7714783 127809578 27114874

経過: 00:00:00.02
21:10:48 SCOTT>
DB_TIME DB_CPU BG_TIME BG_CPU
------------------------------- ------------------------------- ------------------------------- -------------------------------
66179178 7720782 128085853 27160868

経過: 00:00:00.01
21:10:57 SCOTT>
DB_TIME DB_CPU BG_TIME BG_CPU
------------------------------- ------------------------------- ------------------------------- -------------------------------
66180864 7723782 128249102 27197862

経過: 00:00:00.00

じゃまな出力は、以下の通り

  • SQL*Plusのプロンプト
  • ヘッダー行
  • 経過時間
  • 出力の状態から見て、余分な改行

そして、不足している出力はメトリックのログ取得時のタイムスタンプ


以下のSQL*Plusシステム変数を調整追加すればなんとかなりそうな感じ。。。。

  • SQL*Plusのプロンプトは、 set sqlp "" で抑止。
  • ヘッダー行は、 set head off で抑止
  • 経過時間は、 set timi off で抑止
  • 余分な改行は、 たぶん、 set newp none で抑止
  • 直接関係ないけど、Excelにコピペするときにじゃまになるので set tab offでタブの混入抑止


不足しているログ取得時のタイムスタンプは、シェルのdateコマンドで取得した日時をSQL文に埋め込むことでなんとかなりそうな気がします。

と頭に浮かんだら忘れないうちに試してみますよ〜

★横に長くてごめんなさい。時間取れたらSyntaxHighlighterとか入れます詐欺 m(_ _)m

#!/bin/bash
#
(
echo "conn scott/tiger"
echo "set timi off time off tab off sqlp \"\" head off newp none"
echo "col db_time for 999999999999999999999999999999"
echo "col db_cpu for 999999999999999999999999999999"
echo "col bg_time for 999999999999999999999999999999"
echo "col bg_cpu for 999999999999999999999999999999"
while [ 1 ]
do
echo "SELECT db_time,db_cpu,bg_time,bg_cpu FROM (SELECT stat_name,value FROM v\$sys_time_model) PIVOT (MAX(value) FOR stat_name IN ('DB time' AS db_time,'DB CPU' AS db_cpu,'background elapsed time' AS bg_time,'background cpu time' AS bg_cpu));"
sleep 10
done
) | sqlplus /nolog


ん〜〜〜〜〜、なんか、惜しい!!!!  いい感じにななったのに。... しばし考える。。。。

[oracle ˜]$ ./sample.sh

SQL*Plus: Release 12.1.0.2.0 Production on 日 8月 17 21:45:43 2014

Copyright (c) 1982, 2014, Oracle. All rights reserved.

21:45:43 > 接続されました。
21:45:44 SCOTT> 67126005 8476651 182158980 37408311

67129138 8479651 182310474 37445305


きた〜〜〜、神が降りてきたのでちょっと書き換えた

#!/bin/bash
#
(
echo "conn scott/tiger"
echo "set timi off time off sqlp \"\""
echo "col db_time for 999999999999999999999999999999"
echo "col db_cpu for 999999999999999999999999999999"
echo "col bg_time for 999999999999999999999999999999"
echo "col bg_cpu for 999999999999999999999999999999"
while [ 1 ]
do
t=`date +'%DT%T'`
echo "SELECT SUBSTR('${t}',1,INSTR('${t}','T')-1) as logged_date,SUBSTR('${t}',INSTR('${t}','T')+1) as logged_time,db_time,db_cpu,bg_time,bg_cpu FROM (SELECT stat_name,value FROM v\$sys_time_model) PIVOT (MAX(value) FOR stat_name IN ('DB time' AS db_time,'DB CPU' AS db_cpu,'background elapsed time' AS bg_time,'background cpu time' AS bg_cpu));"
echo "set head off newp none"
sleep 10
done
) | sqlplus /nolog


ん〜〜〜、まだ余計な改行というか空行がある。。。なんだこれ。。。。再び、考え中........ あ、あれだ! 出力行数を返すやつ!

SQL*Plus: Release 12.1.0.2.0 Production on 日 8月 17 21:56:21 2014

Copyright (c) 1982, 2014, Oracle. All rights reserved.

21:56:21 > 接続されました。
21:56:22 SCOTT>
LOGGED_D LOGGED_T DB_TIME DB_CPU BG_TIME BG_CPU
-------- -------- ------------------------------- ------------------------------- ------------------------------- -------------------------------
08/17/14 21:56:21 67688748 8937570 198751230 40650823

08/17/14 21:56:31 67695983 8945569 199012673 40699815


で、できたのがこれ。

#!/bin/bash
#
(
echo "conn scott/tiger"
echo "set timi off time off sqlp \"\" feed off"
echo "col db_time for 999999999999999999999999999999"
echo "col db_cpu for 999999999999999999999999999999"
echo "col bg_time for 999999999999999999999999999999"
echo "col bg_cpu for 999999999999999999999999999999"
while [ 1 ]
do
t=`date +'%DT%T'`
echo "SELECT SUBSTR('${t}',1,INSTR('${t}','T')-1) as logged_date,SUBSTR('${t}',INSTR('${t}','T')+1) as logged_time,db_time,db_cpu,bg_time,bg_cpu FROM (SELECT stat_name,value FROM v\$sys_time_model) PIVOT (MAX(value) FOR stat_name IN ('DB time' AS db_time,'DB CPU' AS db_cpu,'background elapsed time' AS bg_time,'background cpu time' AS bg_cpu));"
echo "set head off newp none"
sleep 10
done

) | sqlplus /nolog

出力結果は以下のようになり、 iostatやvmstat風にヘッダー行は一度だけ、その後、定期的に取得されるメトリックが出力されていくイメージに! :)

[oracle ˜]$ ./sample.sh

SQL*Plus: Release 12.1.0.2.0 Production on 日 8月 17 22:02:59 2014

Copyright (c) 1982, 2014, Oracle. All rights reserved.

22:02:59 > 接続されました。
22:02:59 SCOTT>
LOGGED_D LOGGED_T DB_TIME DB_CPU BG_TIME BG_CPU
-------- -------- ------------------------------- ------------------------------- ------------------------------- -------------------------------
08/17/14 22:02:59 68026469 9252517 211057107 42641516
08/17/14 22:03:09 68034074 9261515 211217278 42686507
08/17/14 22:03:19 68039874 9267514 211414489 42730501
08/17/14 22:03:29 68045221 9272514 211576132 42769498
08/17/14 22:03:39 68051396 9276513 211844118 42862480
^C
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing optionsとの接続が切断されました。


Enjoy!


pivotとSQL*PlusとSETコマンドと

| | コメント (0) | トラックバック (0)

2014年8月18日 (月)

pivotとSQL*PlusとSETコマンドと

Oracle Databaseの性能試験で以下のようなメトリックを定期取得して、分析やビジュアライズに利用している方も多いと思います。(思ってます。)
でも、ですねぇ。
以下のv$sys_time_model動的パフォーマンスビューも典型例なのですが、列持ちのメトリックが多いので集計にはかなり苦労します。というか、してます。

v$sys_time_model動的パフォーマンスビューの出力例)

SCOTT> SELECT stat_name, value from v$sys_time_model;

STAT_NAME VALUE
---------------------------------------------------------------- ----------
DB time 64073868
DB CPU 6549986
background elapsed time 42988476
background cpu time 11080311

・・・以下略・・・

列持ちなんですよね、 列持ち!(しつこいw

行持ちにしたいですよね。 どう料理しましょう。 まさか、手作業ではやってないですよね。

SQL文でやってますよね! 私もそうです。
ちなみに、UNION連打はしてませんからね!(キリっ!

昔はほかに手がなかったのですが、Oracle11gから便利で比較的読みやすい構文がサポートされています。

列持ちを行持ちにするといえば....そうです、あれです。 pivot

ということで、

pivotを使って、v$sys_time_modelを例にオレオレv$sys_time_modelを作り出してみます。
(これができれば、数あるオラクルの動的パフォーマンスビューをもっと好きになれるんじゃないかなぁ。と思います。)

では、早速

v$sys_time_modelの stat_name列の列値が、'DB time'、'DB CPU'、 'background elapsed time'、'background cpu time'の4つのメトリックを列持ちから行持ちに変え、オレオレv$sys_time_model作り出すSQL文です。
ビューは作りませんけど (^^;;;

SELECT 
db_time
,db_cpu
,bg_time
,bg_cpu
FROM
(
SELECT
stat_name
,value
FROM
v$sys_time_model
)
PIVOT
(
MAX(value)
FOR stat_name IN
(
'DB time' AS db_time
,'DB CPU' AS db_cpu
,'background elapsed time' AS bg_time
,'background cpu time' AS bg_cpu
)
)
;


これを実行すると以下のような結果になります。本来4行なのですが、1行にできるんです! 便利ですね。 pivot (pivotの逆の操作をする unpivotもあります)

   DB_TIME     DB_CPU    BG_TIME     BG_CPU
---------- ---------- ---------- ----------
63895360 6364016 32965031 8718671

いい感じになってきました。


しかし、まだ物足りないですよね。 そう!
取得時のタイムスタンプとか、例えば iostat や vmstatのように定期的に取得したくなってきます!!!!

「門外不出のOracle現場ワザ」 第5章 DBアクセスの空白地帯 コネクションプーリングを極めるの定期的にSQLを発行するシェルを作成するには? でも解説されているのでこの方法で取得されている方も多いと思います。:)

ただ、そのまんまだと以下のような出力になってしまいます。 iostatやvmstatの出力をイメージしちゃうと余分な表示が多いわけです。

[oracle ˜]$ ./sample.sh

SQL*Plus: Release 12.1.0.2.0 Production on 日 8月 17 21:10:47 2014

Copyright (c) 1982, 2014, Oracle. All rights reserved.


Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
に接続されました。
21:10:48 SCOTT>
DB_TIME DB_CPU BG_TIME BG_CPU
------------------------------- ------------------------------- ------------------------------- -------------------------------
66172667 7714783 127809578 27114874

経過: 00:00:00.02
21:10:48 SCOTT>
DB_TIME DB_CPU BG_TIME BG_CPU
------------------------------- ------------------------------- ------------------------------- -------------------------------
66179178 7720782 128085853 27160868

経過: 00:00:00.01
21:10:57 SCOTT>
DB_TIME DB_CPU BG_TIME BG_CPU
------------------------------- ------------------------------- ------------------------------- -------------------------------
66180864 7723782 128249102 27197862

経過: 00:00:00.00

前述の出力は以下のコードで取得したのですが、実はそんなに手を加えなくても vmstatやiostatのような出力形式で、みなさんの大好きなExcelで集計しやすくすることができるんですよ。
どこを変更すればよいか分かった人、手を挙げて〜〜〜〜っ!

注)scottユーザにselect any dictionaryシステム権限付けてます。

#!/bin/bash
#
(
echo "conn scott/tiger"
echo "set timi on time on"
echo "col db_time for 999999999999999999999999999999"
echo "col db_cpu for 999999999999999999999999999999"
echo "col bg_time for 999999999999999999999999999999"
echo "col bg_cpu for 999999999999999999999999999999"
while [ 1 ]
do
echo "SELECT db_time,db_cpu,bg_time,bg_cpu FROM (SELECT stat_name,value FROM v\$sys_time_model) PIVOT (MAX(value) FOR stat_name IN ('DB time' AS db_time,'DB CPU' AS db_cpu,'background elapsed time' AS bg_time,'background cpu time' AS bg_cpu));"
sleep 10
done
) | sqlplus /nolog


つづきは、次のエントリーで :)

| | コメント (0) | トラックバック (0)

2014年8月 4日 (月)

Difference of Initialization Parameters between 11g and 12c #2

以前、11gと12cの初期化パラメータ数を比較したエントリーを書いたのですが、12c R1も 12.1.0.1.0と12.1.0.2.0でまたまた大きく変わっているようだったので調べてみた。

Oracle Database 11g R1 11.1.0.6.0
Oracle Database 11g R2 11.2.0.1.0
Oracle Database 12c R1 12.1.0.1.0
上記に加え、先日リリースされた Oracle database 12c R1 12.1.0.2.0 を加え、とりあえずパラメータ数だけを比較しました。 (差分はまた別途 TODO)

今回も隠しパラメータの増加が目立ちます。(@@)

20140804_03958


11.1.0.6.0から11.2.0.1.0で302個の隠しパラメータが増加、
11.2.0.1.0から12.1.0.1.0で926個の隠しパラメータが増加、
そして今回、 12.1.0.1.0から12.1.0.2.0で612個の隠しパラメータが増加し、
11g R2と 12c R1の単純な比較では1500個以上の隠しパラメータが増加している。

これらの隠しパラメータの中で、有名人になるパラメータは登場するのかしないのか...
今後のお楽しみは尽きないわけですが。。。それにしてもすごい増加量、ですよね。


20140804_04007



Difference of Initialization Parameters between 11g r1 (11.1.0.6.0) and 12c r1 (12.1.0.1.0) - including hidden params

| | コメント (0) | トラックバック (0)

2014年4月20日 (日)

シーケンス.NEXTVALが使えないからぐるぐる〜〜〜っとしていいですか? (30歳 エンジニア 男性)

CREATE TABLE 〜 AS SELECT文でシーケンス.NEXTVALって使えないからぐるぐる〜〜〜っとしたループ処理しないといけないですよね〜。

と質問されたのですが、1文で書けますからね!
(SQL文でワンライナーって言いそうになったけど、飲み込んだw)


準備

SCOTT> l
1 CREATE TABLE table_foobar
2 (
3 id NUMBER PRIMARY KEY
4 ,data VARCHAR2(10)
5* )
SCOTT> /

表が作成されました。

SCOTT> l
1 INSERT INTO table_foobar
2 SELECT
3 LEVEL
4 ,'D'||TO_CHAR(LEVEL,'FM099999999')
5 FROM
6 dual
7 CONNECT BY
8* LEVEL <= 100.
SCOTT> /

100行が作成されました。

SCOTT> commit;

コミットが完了しました。

SCOTT> SELECT * FROM table_foobar ORDER BY id;

ID DATA
---------- ----------
1 D000000001
2 D000000002
3 D000000003
4 D000000004
5 D000000005
6 D000000006
7 D000000007
8 D000000008
9 D000000009
10 D000000010

   ...中略...

90 D000000090
91 D000000091
92 D000000092
93 D000000093
94 D000000094
95 D000000095
96 D000000096
97 D000000097
98 D000000098
99 D000000099
100 D000000100

100行が選択されました。


前述のデータを複製しtable_foobar_tmp表を作成するとします。
なお、DATA列はそのままで、ID列は、次のシーケンスを利用してID = 1..100の順にシーケンスから採番しなおしたい。
(以下のシーケンスの定義からすると、 ID=1 は、1000、 ID=2は、1001にしたい。)

SCOTT> CREATE SEQUENCE seq_foobar start with 1000 maxvalue 999999999;

順序が作成されました。

1文で書けますよね!

SCOTT> l
1 CREATE TABLE table_foobar_tmp
2 AS
3 SELECT
4 seq_foobar.NEXTVAL AS id
5 ,t01.data
6 FROM
7 (
8 SELECT
9 id
10 ,data
11 FROM
12 table_foobar
13 ORDER BY
14 id
15* ) t01
SCOTT> /

表が作成されました。

SCOTT> SELECT * FROM table_foobar_tmp ORDER BY ID;

ID DATA
---------- ----------
1000 D000000001
1001 D000000002
1002 D000000003
1003 D000000004
1004 D000000005
1005 D000000006
1006 D000000007
1007 D000000008
1008 D000000009
1009 D000000010
1010 D000000011

   ...中略...

1090 D000000091
1091 D000000092
1092 D000000093
1093 D000000094
1094 D000000095
1095 D000000096
1096 D000000097
1097 D000000098
1098 D000000099
1099 D000000100

100行が選択されました。

はい、できました!


マニュアルには、「NEXTVALへの参照が含まれる単一のSQL文の中では、Oracleは、次の各行につき1回順序を増加させます。」
と記載されているので、質問してきた方は、マニュアルを読んでいないか、マニュアル読んでなくても実際に試していない食わず嫌い状態だったか、
以下のようなシーケンスの制限に遭遇して、できないんだ!と思い込んでしまった。

病は気からという状態だったのでしょうね。:)


SCOTT> l
1 CREATE TABLE table_foobar_tmp_NG
2 AS
3 SELECT
4 seq_foobar.NEXTVAL AS ID
5 ,t01.data
6 FROM
7 table_foobar t01
8 ORDER BY
9* t01.id
SCOTT> /
seq_foobar.NEXTVAL AS ID
*
行4でエラーが発生しました。:
ORA-02287: ここでは順序番号は使用できません。

エラーメッセージを見ても、Action がRemove the sequence numberだけですからね....

SCOTT> !oerr ORA 2287
02287, 00000, "sequence number not allowed here"
// *Cause: The specified sequence number (CURRVAL or NEXTVAL) is inappropriate
// here in the statement.
// *Action: Remove the sequence number.

そんな時はマニュアルを..
Oracle® Database SQL言語リファレンス 11gリリース2 (11.2) 順序疑似列

順序値の使用方法には、CREATE TABLE ... AS SELECTで使用できると書いてるのに。なんでだろう?
と,、なるかもしれないですが、よ〜〜〜くマニュアルを読んでくださいよ〜っ。

順序値の制限事項にGROUP BY句やORDER BY句を持つSELECT文では使用できないとも書かれているところにちゅうも〜〜〜〜く!

ORDER BY句を含んでいるのでORA-02287回避のために、サブクエリにして別クエリブロック化、シーケンスを利用しているクエリブロックにはORDER BY句を含まないようにしているところがポイント :)

テストデータ作るときとか、知ってると便利ですよ〜と。

SCOTT> l
1 CREATE TABLE table_foobar_tmp
2 AS
3 SELECT
4 seq_foobar.NEXTVAL AS id
5 ,t01.data
6 FROM
7 (
8 SELECT
9 id
10 ,data
11 FROM
12 table_foobar
13 ORDER BY
14 id
15* ) t01
SCOTT> /

Enjoy SQL!

| | コメント (0) | トラックバック (0)

2014年1月 6日 (月)

SELECT ~ FOR UPDATE SKIP LOCKED その4 - もしもITL不足だったら...

skip lockedのつづきです。

ITLエントリー不足時のskip lockedの動きを確認してみるか....


100行が1ブロックに収まるような表を作成しておく...計算上、ITLエントリーは最大で4エントリー程度になるように....したつもり....
(ASSMで、INITRANSはデフォルト、ブロックサイズは8KB、PCTFREEは0%)

SCOTT@pdborcl> r
1 select
2 objectid
3 ,file#
4 ,block#
5 ,count(id) as num_of_rows
6 from
7 (
8 select
9 dbms_rowid.rowid_object(rowid) as objectid
10 ,dbms_rowid.rowid_relative_fno(rowid) as file#
11 ,dbms_rowid.rowid_block_number(rowid) as block#
12 ,id
13 from
14 q
15 )
16 group by
17 objectid
18 ,file#
19 ,block#
20 order by
21 objectid
22 ,file#
23* ,block#

OBJECTID FILE# BLOCK# NUM_OF_ROWS
---------- ---------- ---------- -----------
93077 9 972461 100

※セッション1 - lockできた

SESSION1@pdborcl> select * from q where id = '0001' for update;

ID
----
TEXT_STRING
----------------------------------------------------------------------
0001
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

※セッション2 - lockできた。 この時点で 1 + 1 = 2 のITLエントリは使い切っている。

SESSION2@pdborcl> select * from q where id = '0002' for update;

ID
----
TEXT_STRING
---------------------------------------------------------------------
0002
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

※セッション3 - lockできた。 ITLがブロック内の空きスペースに作れたため :)

SESSION3@pdborcl> select * from q where id = '0003' for update;

ID
----
TEXT_STRING
---------------------------------------------------------------------
0003
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

※セッション4 - 計算上のITLエントリー数の上限値. 問題なくlockできた。

SESSION4@pdborcl> select * from q where id = '0004' for update;

ID
----
TEXT_STRING
---------------------------------------------------------------------
0004
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

※セッション5 - 狙い通り! 5つめのITLエントリーを作成するだけの空きがブロック内にない状況なので待機しちゃう :)

SESSION5@pdborcl> select * from q where id = '0005' for update;


待機イベント見れば一目瞭然、ITLエントリー不足で待機してますね!

SYS@pdborcl> select username,event from v$session where username = 'SCOTT'

USERNAME EVENT
---------- ----------------------------------------
SCOTT SQL*Net message from client
SCOTT SQL*Net message from client
SCOTT enq: TX - allocate ITL entry
SCOTT SQL*Net message from client
SCOTT SQL*Net message from client

ここまでは、ITL不足な状況のfor update文ではよく見かける光景ですよね :)


for update skip lockedにすると.....

※セッション1 - locked!

SESSION1@pdborcl> select * from q where id = '0001' for update skip locked;

ID
----
TEXT_STRING
---------------------------------------------------------------------
0001
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

※セッション2 - locked!!

SESSION2@pdborcl> select * from q where id = '0002' for update skip locked;

ID
----
TEXT_STRING
---------------------------------------------------------------------
0002
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

※セッション3 - locked!!!

SESSON3@pdborcl> select * from q where id = '0003' for update skip locked;

ID
----
TEXT_STRING
---------------------------------------------------------------------
0003
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

※セッション4 - locked!!!!

SESSION4@pdborcl> select * from q where id = '0004' for update skip locked;

ID
----
TEXT_STRING
---------------------------------------------------------------------
0004
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

※セッション5(ITLエントリーが確保できず id = '0005'の行をlockすることができないので空振りします。興味深い動きですよね。)

SESSION5@pdborcl> select * from q where id = '0005' for update skip locked;

レコードが選択されませんでした。


次回へつづく.....かもしれない。



SELECT ~ FOR UPDATE SKIP LOCKED その1 - @sh2ndさんエントリの復習など
SELECT ~ FOR UPDATE SKIP LOCKED その2
SELECT ~ FOR UPDATE SKIP LOCKED その3

| | コメント (0) | トラックバック (0)

2014年1月 5日 (日)

SELECT ~ FOR UPDATE SKIP LOCKED その3

skip lockedのつづきです。

skip lockedの特徴を確認しておきますか!

skip lockedはロックの獲得ができた行だけをロック待機なしで返してくれる :)
IDが'0001', '0002', '0003', '0005'の行をロックしておく。

SESSION1@pdborcl> select id from q where id in ('0001', '0002', '0003', '0005') for update skip locked;

ID
----
0001
0002
0003
0005

IDが '0001','0002','0003'の行は先行のトランザクションで既にロックされているため、ロックできた行だけがロック待機なしで返される。

SESSION2@pdborcl> select id from q where id in ('0001', '0002', '0003', '0004', '0005', '0006') for update skip locked;

ID
----
0004
0006

もちろん、ロックできる行が1行もなければロックを待機せず空振!

SESSION3@pdborcl> select id from q where id in ('0001', '0002', '0003') for update skip locked;

レコードが選択されませんでした。


つづく。


SELECT ~ FOR UPDATE SKIP LOCKED その1 - @sh2ndさんエントリの復習など
SELECT ~ FOR UPDATE SKIP LOCKED その2

| | コメント (0) | トラックバック (0)

2013年12月31日 (火)

SELECT ~ FOR UPDATE SKIP LOCKED その2

つづきです。


そういえば、skip lockedって構文がマニュアルでは解説されていないリリースでふつーーーーに、使われててビビったことあったな。
(マニュアルに書かれていないリリースでは、自己責任使ってねw)


Oracle12c R1 - SKIP LOCKED
http://docs.oracle.com/cd/E49329_01/server.121/b71278/statements_10002.htm#SQLRF55374


Oracle11g R2 - (skip locked、推奨事項などが追記された)
http://docs.oracle.com/cd/E16338_01/server.112/b56299/statements_10002.htm#i2126016


Oracle11g R1 - (skip locked登場)
http://otndnld.oracle.co.jp/document/products/oracle11g/111/doc_dvd/server.111/E05750-03/statements_10.htm#7292


Oracle10g R2 (ここまでのマニュアルにはskip lookedは記載されていない。AQがらみで使われていたのは確かだ....)
http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/server.102/B19201-02/statements_10.html#6799


どのあたりのバージョンから登場していたのかはJonathan Lewisさんのブログからたどれば分かると思うよ...
http://jonathanlewis.wordpress.com/2010/05/31/skip-locked/


Oracle11g R2のドキュメントからは以下のような追記されている。


「この機能は、Oracle Streams Advanced Queuingなどのマルチコンシューマ・キュー環境で使用するために設計されています。
 キュー・コンシューマは、他のコンシューマによってロックされた行はスキップして未ロックの行を取得できるので、
 他のコンシューマの操作が終了するまで待つ必要はなくなります。
 SKIP LOCKED機能を直接使用するかわりに、Oracle Streams Advanced Queuing APIを使用することをお薦めします。」

と。

以下のリリースで確認したが skip lockedに関して動作の差は無いようだ。
2013/1/5追記
動作の差は無いようだ、とは書いたが、結果オーライってことでございます。内部動作までは見えないので(キリつ

・Oracle11g R1 11.1.0.7.0
・Oracle11g R2 11.2.0.1.0
・Oracle11g R2 11.2.0.2.0
・Oracle12c R1 12.1.0.1.0


※セッション1
SESSION1> select * from q order by id;

ID DATA
---------- ----------
1 a
2 b
3 c

※セッション1
SESSION1> SELECT id, data FROM q WHERE id = (SELECT MIN(id) FROM q) FOR UPDATE SKIP LOCKED;

ID DATA
---------- ----------
1 a

※セッション2
SKIP LOCKEDなのでしようとしていたレコードがロックできなければ空振りし、ロック獲得を待機しません
SESSION2> SELECT id, data FROM q WHERE id = (SELECT MIN(id) FROM q) FOR UPDATE SKIP LOCKED;

レコードが選択されませんでした。


※セッション1
SESSION1> DELETE FROM q WHERE id = 1;

1行が削除されました。

※セッション2
何度やっても同じですよね :)
SESSION2> SELECT id, data FROM q WHERE id = (SELECT MIN(id) FROM q) FOR UPDATE SKIP LOCKED;

レコードが選択されませんでした。


※セッション1
SESSION1> COMMIT;

コミットが完了しました。

SESSION1>

※セッション2
ここで初めて、対象レコードがロックできます!
マルチコンシューマ・キュー環境向けって意味がよ〜〜〜〜く分かる動きだと思います
SESSION2> SELECT id, data FROM q WHERE id = (SELECT MIN(id) FROM q) FOR UPDATE SKIP LOCKED;

ID DATA
---------- ----------
2 b


skip lockedって面白いよね。

skip lockedの特徴について、もう少し書く予定、多分、来年へつづく。。。。。


みなさま、良いお年を!



SELECT ~ FOR UPDATE SKIP LOCKED その1 - @sh2ndさんエントリの復習など

| | コメント (0) | トラックバック (0)

SELECT ~ FOR UPDATE SKIP LOCKED その1 - @sh2ndさんのエントリの復習など

JPOUT Advent Calender 2013の@sh2ndさんのエントリーが面白かったので大晦日に酒飲みながら... :)
まずは twitterでのやり取りなど....


20131231_113305


20131231_163205

イケテナイとか、良いとか、自由に言えるのはユーザーだからこそだと思うんだ。
セールストークじゃない生の情報って大切だ。


ということで、skip locked へ行く前に、Oracle11g R1 11.1.0.7.0 および、Oracle12c R1 12.1.0.1.0 で @sh2ndさんのエントリーの復習から :)

※セッション1
SESSION1> select * from q order by id;

ID DATA
---------- ----------
1 a
2 b
3 c

※セッション1
SESSION1> SELECT id, data FROM q WHERE id = (SELECT MIN(id) FROM q) FOR UPDATE;

ID DATA
---------- ----------
1 a

※セッション2
SESSION2> SELECT id, data FROM q WHERE id = (SELECT MIN(id) FROM q) FOR UPDATE;
(ここで待たされる。待つことは正しい動き)

※セッション1
SESSION1> DELETE FROM q WHERE id = 1;

1行が削除されました。

※セッション1
SESSION1> commit;

コミットが完了しました。

SESSION1>

※セッション2はここでロックを獲得できる。
ID DATA
---------- ----------
2 b

SESSION2>


Oracle11g R2 11.2.0.1.0とOracle11g R2 11.2.0.2.0は、Wrong Resultだったんだと思うが...

※セッション1
SESSION1> select * from q order by id;

ID DATA
---------- ----------
1 a
2 b
3 c

※セッション1
SESSION1> SELECT id, data FROM q WHERE id = (SELECT MIN(id) FROM q) FOR UPDATE;

ID DATA
---------- ----------
1 a

※セッション2
SESSION2> SELECT id, data FROM q WHERE id = (SELECT MIN(id) FROM q) FOR UPDATE;
(ここで待たされる。というところまでは同じ)


※セッション1
SESSION1> DELETE FROM q WHERE id = 1;

1行が削除されました。

※セッション1
SESSION1> COMMIT;

コミットが完了しました。

SESSION1>

※セッション2 (注1
(しか〜〜〜し、なんとレコードが選択されませんでした!!!!!)
レコードが選択されませんでした。

SESSION2>

結果
OracleREAD COMMITTED
11.1.0.7.0ID=2を取得
11.2.0.1.0空振り
11.2.0.2.0空振り
12.1.0.1.0ID=2を取得


注1)
Oracle11g 11.2.0.3.0以降では修正されているとのこと...(私は手持ちのが無かったので未確認...だれか書いてw)

SELECT ~ FOR UPDATE SKIP LOCKEDへつづく...

| | コメント (0) | トラックバック (0)

2013年11月17日 (日)

db tech showcase tokyo 2013 - A35 - JPOUG特濃:潮溜まりでジャブジャブ、SQLチューニング

11/13〜15に開催されたdb tech showcase tokyo 2013 の最終日、午後の4枠で特濃JPOUGとてセッションを行いました。

貴重な機会を提供いただいたインサイトテクノロジーの皆様ありがとうございました。
また、お忙しい中、セッションに参加してくださった皆様、ありがとうございました。

A35
15:00-15:45 / 「JPOUG特濃:潮溜まりでジャブジャブ、SQLチューニング」 のセッション資料を公開しました。

塩分濃いめの潮溜まりで釣り上げたSQLは治療できるかどうかもわからない病になっていました….
治療できたか、できなかったのか……

曲者すぎる難病もありますが、何かの機会に思い出していただければと思います。

みなさん、楽しい時間をありがとう。

| | コメント (0) | トラックバック (0)

2012年5月 1日 (火)

オプティマイザをだましちゃお! (マジック・ザ・ギャザリング風w かも)

ということで、準備から。なにやら索引がいるのか怪しい列にまでBツリー索引を作成しちゃってます ;)

23:34:03 SYS> conn scott/tiger
接続されました。
23:36:01 SCOTT>
23:36:01 SCOTT>
23:36:01 SCOTT> create table deluding_tab (id number not null, status number(2) not null, data varchar2(500)) nologging;

表が作成されました。

23:50:47 SCOTT> begin for i in 1..100000 loop insert into deluding_tab values(i,0,lpad(i,500,'*')); end loop; end;
23:55:22 2 /

PL/SQLプロシージャが正常に完了しました。

23:55:27 SCOTT> commit;

コミットが完了しました。

23:55:31 SCOTT> alter table deluding_tab add constraint pk_deluding_tab primary key (id) using index nologging;

表が変更されました。

23:56:07 SCOTT> create index ix_deluding_tab on deluding_tab(status) nologging;

索引が作成されました。

23:58:26 SCOTT> exec dbms_stats.gather_table_stats(ownname=>'SCOTT',tabname=>'DELUDING_TAB', -
23:58:34 > no_invalidate=>false,cascade=>true,method_opt=>'FOR ALL COLUMNS SIZE AUTO');

PL/SQLプロシージャが正常に完了しました。

ヒストグラムの状態も見ておきましょ。

TABLE_NAME                     COLUMN_NAME                    NUM_BUCKETS HISTOGRAM
------------------------------ ------------------------------ ----------- ---------------
DELUDING_TAB ID 1 NONE
DELUDING_TAB STATUS 1 NONE
DELUDING_TAB DATA 1 NONE

登録したデータ件数も見ておきましょうか。

00:03:27 SCOTT> 
00:08:41 SCOTT> select count(1) from deluding_tab;

COUNT(1)
----------
100000

では、オプティマイザとデュエル!


アンタップ、アップキープ、ドロー! 

00:03:54 SCOTT> select * from deluding_tab where status = 1;

レコードが選択されませんでした。

経過: 00:00:00.01

実行計画
----------------------------------------------------------
Plan hash value: 1226994206

------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU) | Time |
------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 508 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| DELUDING_TAB | 1 | 508 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | IX_DELUDING_TAB | 1 | | 1 (0)| 00:00:01 |
------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - access("STATUS"=1)


統計
----------------------------------------------------------
1 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
487 bytes sent via SQL*Net to client
509 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed

データはヒットしていないですね。索引レンジスキャンは妥当な実行計画:)

お〜〜っと、ここで、インスタント! 全データをヒント無しで、索引レンジスキャン!

ちなみに、遊戯王ばかりで、マジック・ザ・ギャザリングをしらない、最近の子の為に解説しておくと、フラッシュタイミングで使うカードと似たような使い方をするカードのことだぉ


00:07:27 SCOTT> select * from deluding_tab where status = 2;

100000行が選択されました。

経過: 00:00:02.32

実行計画
----------------------------------------------------------
Plan hash value: 1226994206

------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU) | Time |
------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 508 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| DELUDING_TAB | 1 | 508 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | IX_DELUDING_TAB | 1 | | 1 (0)| 00:00:01 |
------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - access("STATUS"=2)


統計
----------------------------------------------------------
1 recursive calls
0 db block gets
20166 consistent gets
0 physical reads
0 redo size
53229491 bytes sent via SQL*Net to client
73846 bytes received via SQL*Net from client
6668 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
100000 rows processed


ターンエンド。

リテラル値指定、かつ、全件ヒットするからTABLE FULL SCANになるはずなのに、何故、INDEX RANGE SCANしてすげ〜時間かかっているんだ〜〜〜〜というマジックの秘密は次回。

バインド変数使ってなくてもオプティマイザをだませるんだぉ

つづく。

| | コメント (0) | トラックバック (0)

2012年4月28日 (土)

述語のつづきの続き。

前回の続きです。


今回の例も今ひとつといえばそうなのだけど、述語プッシュで索引が利用されることを期待した書き方なのに残念な結果になっている以下のようなパターン、意外と見かけるんですよー
オプティマイザが進化して今以上に賢くなったら気にしなくても最適化してくれるかもしれないけど………

11:28:59 SCOTT> l   
1 select
2 v1.id
3 ,v1.data
4 from
5 (
6 select
7 to_char(id) as id
8 ,data
9 from
10 push_pred_test1
11 union
12 select
13 to_char(id) as id
14 ,data
15 from
16 push_pred_test2
17 ) v1
18 where
19* v1.id = 10
11:30:40 SCOTT> /

11行が選択されました。

経過: 00:00:01.58

実行計画
----------------------------------------------------------
Plan hash value: 2712236156

------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU) | Time |
------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 11 | 814 | 4857 (1)| 00:00:59 |
| 1 | VIEW | | 11 | 814 | 4857 (1)| 00:00:59 |
| 2 | SORT UNIQUE | | 11 | 1166 | 4857 (91)| 00:00:59 |
| 3 | UNION-ALL | | | | | |
|* 4 | TABLE ACCESS FULL| PUSH_PRED_TEST1 | 1 | 106 | 445 (1)| 00:00:06 |
|* 5 | TABLE ACCESS FULL| PUSH_PRED_TEST2 | 10 | 1060 | 4410 (1)| 00:00:53 |
------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

4 - filter(TO_NUMBER(TO_CHAR("ID"))=10)
5 - filter(TO_NUMBER(TO_CHAR("ID"))=10)


統計
----------------------------------------------------------
0 recursive calls
0 db block gets
17554 consistent gets
15960 physical reads
0 redo size
1819 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
11 rows processed

11:30:43 SCOTT>


こんな実行計画を期待して書いたはず (^^)

11:31:49 SCOTT> l
1 select
2 to_char(v1.id) as id
3 ,v1.data
4 from
5 (
6 select
7 id
8 ,data
9 from
10 push_pred_test1
11 union
12 select
13 id
14 ,data
15 from
16 push_pred_test2
17 ) v1
18 where
19* v1.id = 10
11:31:50 SCOTT> /

11行が選択されました。

経過: 00:00:00.00

実行計画
----------------------------------------------------------
Plan hash value: 2774814350

--------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU) | Time |
--------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 11 | 715 | 8 (25)| 00:00:01 |
| 1 | VIEW | | 11 | 715 | 8 (25)| 00:00:01 |
| 2 | SORT UNIQUE | | 11 | 1166 | 8 (75)| 00:00:01 |
| 3 | UNION-ALL | | | | | |
| 4 | TABLE ACCESS BY INDEX ROWID| PUSH_PRED_TEST1 | 1 | 106 | 2 (0)| 00:00:01 |
|* 5 | INDEX UNIQUE SCAN | PK_PUSH_PRED_TEST1 | 1 | | 1 (0)| 00:00:01 |
| 6 | TABLE ACCESS BY INDEX ROWID| PUSH_PRED_TEST2 | 10 | 1060 | 4 (0)| 00:00:01 |
|* 7 | INDEX RANGE SCAN | PK_PUSH_PRED_TEST2 | 10 | | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

5 - access("ID"=10)
7 - access("ID"=10)


統計
----------------------------------------------------------
0 recursive calls
0 db block gets
7 consistent gets
0 physical reads
0 redo size
1819 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
11 rows processed

11:31:51 SCOTT>




ここまでのあらすじ

述語 ;)
述語 ;) のつづき

| | コメント (0) | トラックバック (0)

2012年4月 8日 (日)

いん!、イン!、Index どっぷり Inde Only Access生活w - Oracle OpenWorld Unconference presented by JPOUG

Oracle OpenWorld Unconference presented by JPOUG
とこかで聞いたようなタイトルを"インデックス"に置換えた「いん!、イン!、Index どっぷり Inde Only Scan生活w」のセッション資料を公開します。
(相変わらず文才ないな〜〜と落ち込む....作文嫌いは死ぬまで治らないと思ってるが、がんばって書くw)

デモ内容とデモ環境情報を追加予定です。 2012/4/15デモとデモ環境情報追加しました)

直前にデモ環境のOracle11gR2が起動しないという想定外のトラブルを乗り越えw かなりイッパイ、イッパイの状態でしたが楽しい時間を過ごさせていただきました。

関係者の皆様、ご来場の皆様、ありがとうございました。

Safari以外のブラウザではアニメーション効果はありませんが、Safari (Mac/iPad/iPhone)ではKeynote風(但し、ページ間のトランジッションなし)に表示されます。

いん!、イン!、IndexどっぷりIndes Only Scan生活w


(2012/4/10追加)
セッションで利用したデモ環境の情報を載せておきます。

MacBook Air late 2010 13inch 2GB (MacOS X Lion)
VirtualBox4.1.10 for MacOS X
GuestOS:CentOS5.8 x86 
DB : Oracle11g R2 11.2.0.1.0 EE for Linux x86

VMの設定は以下のようになってます。
仮想ディスクはほかにもいろいろやるので合計で21GBほどにしてあります :)

20120410_13346_2

(2012/4/15)host i/o cacheはオフにしてあります。
Vbox_no_hostio_cache

late2010のMBAはメモリが2GBなので、VMには1GBのメモリを割り当ててます。
(オラクルのmemory_targetなどの値も書いたほうがいいのかな〜)

(2012/4/15追記)
メモリサイズがギリギリなのでOracleのメモリ関連初期化パラメータも以下の通りで少なめです。

memory_max_target                    big integer 404M
memory_target big integer 404M
sga_max_size big integer 404M
sga_target big integer 0
pga_aggregate_target big integer 0

(2012/4/15追記)
・デモで使った表これ。

13:56:52 SCOTT> desc tab1
名前 NULL? 型
----------------------------- -------- --------------------
UNIQUE_ID NOT NULL NUMBER
NON_UNIQUE_ID NUMBER(10)
NON_UNIQUE_ID2 NUMBER(5)
DATA VARCHAR2(500)
IS_DELETE NUMBER(1)
STATUS_CODE CHAR(2)

13:56:55 SCOTT> desc tab2
名前 NULL? 型
----------------------------- -------- --------------------
UNIQUE_ID2 NOT NULL NUMBER(5)
DATA VARCHAR2(500)
IS_DELETE NUMBER(1)


こんなデータを登録して...

13:56:58 SCOTT> 
15:01:15 SCOTT> begin for i in 1..100000 loop insert into tab1 values(i,ora_hash(i,999),ora_hash(i,99),lpad(i,500,'*'),0,'00'); end loop; end;
15:01:17 SCOTT> /

PL/SQLプロシージャが正常に完了しました。

経過: 00:00:25.46
15:01:44 SCOTT> commit;

コミットが完了しました。

経過: 00:00:00.01
15:01:59 SCOTT> exec dbms_stats.gather_table_stats(ownname=>'SCOTT',tabname=>'TAB1',no_invalidate=>false,cascade=>true);

PL/SQLプロシージャが正常に完了しました。

経過: 00:00:08.50
15:09:43 SCOTT> begin for i in 1..200 loop insert into tab2 values(i,lpad(i,500,'*'),0); end loop; end;
15:10:12 2 /

PL/SQLプロシージャが正常に完了しました。

経過: 00:00:00.05
15:10:13 SCOTT> commit;

コミットが完了しました。

経過: 00:00:00.08
15:10:16 SCOTT> exec dbms_stats.gather_table_stats(ownname=>'SCOTT',tabname=>'TAB2',no_invalidate=>false,cascade=>true);

PL/SQLプロシージャが正常に完了しました。

経過: 00:00:00.99
15:10:50 SCOTT>


データ件数、データのカーディナリティは以下のようになってます。

15:10:50 SCOTT> @show_tab_info
tabnameに値を入力してください: tab1

SEGMENT_NAME SEGMENT_TYPE SEGMENT_SU MB NUM_ROWS DISTINCT_KEYS CLUSTERING_FACTOR VISIBLE
------------------------------ ------------------ ---------- ---------- ---------- ------------- ----------------- -------
TAB1 TABLE ASSM 62 100000 YES
TAB1_IX1 INDEX ASSM 3 100000 1000 99400 YES
TAB1_IX2 INDEX ASSM 3 100000 100 94181 YES
TAB1_PK INDEX ASSM 2 100000 100000 7693 YES

経過: 00:00:00.78

TABLE_NAME INDEX_NAME COLUMN_NAME DESC DATA_TYPE NUM_NULLS DENSITY NUM_DISTINCT HI_VALUE LO_VALUE HISTOGRAM
------------------------------ ------------------------------ -------------------- ---- ------------ ---------- ---------- ------------ ------------- ------------- ---------------
TAB1 TAB1_IX1 NON_UNIQUE_ID ASC NUMBER 0 .001 1000 999 0 NONE

TAB1_IX2 NON_UNIQUE_ID2 ASC NUMBER 0 5.0182E-06 100 99 0 FREQUENCY

TAB1_PK UNIQUE_ID ASC NUMBER 0 .00001 100000 100000 1 NONE


経過: 00:00:02.51
15:17:47 SCOTT> @show_tab_info
tabnameに値を入力してください: tab2

SEGMENT_NAME SEGMENT_TYPE SEGMENT_SU MB NUM_ROWS DISTINCT_KEYS CLUSTERING_FACTOR VISIBLE
------------------------------ ------------------ ---------- ---------- ---------- ------------- ----------------- -------
TAB2 TABLE ASSM 1 200 YES
TAB2_PK INDEX ASSM 1 200 200 15 YES

経過: 00:00:00.78

TABLE_NAME INDEX_NAME COLUMN_NAME DESC DATA_TYPE NUM_NULLS DENSITY NUM_DISTINCT HI_VALUE LO_VALUE HISTOGRAM
------------------------------ ------------------------------ -------------------- ---- ------------ ---------- ---------- ------------ ------------- ------------- ---------------
TAB2 TAB2_PK UNIQUE_ID2 ASC NUMBER 0 .005 200 200 1 NONE


経過: 00:00:02.55
15:18:03 SCOTT>


注)毎回buffer cacheをクリア、かつ、ソフトパース時の結果を載せています。

・demo1

通常ならこの実行計画であればなにもしないですよね...

こんな良さげな実行計画でもSQL文と実行計画それに表定義をじ〜〜〜〜〜〜っと見ていると解決策が見えてきますよね。そうindex only accessならね。

14:45:34 SCOTT> 
14:45:34 SCOTT> set autot trace exp stat
14:45:34 SCOTT> @demo1

システムが変更されました。

経過: 00:00:00.03
1 select
2 unique_id
3 ,status_code
4 from
5 tab1
6 where
7 unique_id between 1 and 1000
8* and is_delete = 0

998行が選択されました。

経過: 00:00:00.07

実行計画
----------------------------------------------------------
Plan hash value: 1911646434

---------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 999 | 10989 | 81 (0)| 00:00:01 |
|* 1 | TABLE ACCESS BY INDEX ROWID| TAB1 | 999 | 10989 | 81 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | TAB1_PK | 1000 | | 4 (0)| 00:00:01 |
---------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - filter("IS_DELETE"=0)
2 - access("UNIQUE_ID">=1 AND "UNIQUE_ID"<=1000)


統計
----------------------------------------------------------
0 recursive calls
0 db block gets
210 consistent gets
80 physical reads
0 redo size
19586 bytes sent via SQL*Net to client
1142 bytes received via SQL*Net from client
68 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
998 rows processed


is_deleteなんて列を参照するためにだけに行長の長い行を持つ表を、しかも、レンジスキャンしているのでデータアクセス量が多くなっているんですよね。
そこで、index only access

index only accessするための索引を作成してしまえばそれを回避できますよね.

14:45:36 SCOTT> @demo1_ix
create index tab1_ix_demo1 on tab1(unique_id,is_delete,status_code) nologging invisible

索引が作成されました。

経過: 00:00:00.80
alter session set optimizer_use_invisible_indexes=true

セッションが変更されました。

経過: 00:00:00.01


TABLE ACCESSが消えました!
consistent getsは、1/3に減少しましたよね :) 時間も 70msから10ms程度に改善してます。

14:46:05 SCOTT> @demo1

システムが変更されました。

経過: 00:00:00.04
1 select
2 unique_id
3 ,status_code
4 from
5 tab1
6 where
7 unique_id between 1 and 1000
8* and is_delete = 0

998行が選択されました。

経過: 00:00:00.01

実行計画
----------------------------------------------------------
Plan hash value: 327556384

----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 999 | 10989 | 4 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| TAB1_IX_DEMO1 | 999 | 10989 | 4 (0)| 00:00:01 |
----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - access("UNIQUE_ID">=1 AND "IS_DELETE"=0 AND "UNIQUE_ID"<=1000)
filter("IS_DELETE"=0)


統計
----------------------------------------------------------
0 recursive calls
0 db block gets
70 consistent gets
4 physical reads
0 redo size
19586 bytes sent via SQL*Net to client
1142 bytes received via SQL*Net from client
68 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
998 rows processed


次のデモのために作成した索引を削除しておきます。

14:46:13 SCOTT> @drop_demo1_ix
drop index tab1_ix_demo1

索引が削除されました。

経過: 00:00:00.61
alter session set optimizer_use_invisible_indexes=false

セッションが変更されました。

経過: 00:00:00.00

・demo2

demo1同様に行長の長い行をある程度の範囲でレンジスキャンかつ、group/order by句があるのでソート処理が行われています。

これも通常ならチューニングなんてしないのですが、大人の事情で何かできないか? 

と聞かれればindex only accessにして表をアクセスしない+ソート処理も省略しましょうか! と返してあげることが多いです。

14:47:05 SCOTT> @demo2

システムが変更されました。

経過: 00:00:00.02
1 select
2 non_unique_id2
3 ,count(1)
4 from
5 tab1
6 where
7 non_unique_id = 70
8 and is_delete = 0
9 group by
10 non_unique_id2
11 order by
12* non_unique_id2

経過: 00:00:00.06

実行計画
----------------------------------------------------------
Plan hash value: 1524069294

-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 63 | 630 | 102 (1)| 00:00:02 |
| 1 | SORT GROUP BY | | 63 | 630 | 102 (1)| 00:00:02 |
|* 2 | TABLE ACCESS BY INDEX ROWID| TAB1 | 100 | 1000 | 101 (0)| 00:00:02 |
|* 3 | INDEX RANGE SCAN | TAB1_IX1 | 100 | | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - filter("IS_DELETE"=0)
3 - access("NON_UNIQUE_ID"=70)


統計
----------------------------------------------------------
0 recursive calls
0 db block gets
103 consistent gets
103 physical reads
0 redo size
517 bytes sent via SQL*Net to client
416 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
1 rows processed


index only scanにしてソート処理も省略するための索引を作成します。

ではどのような索引を作成すればよいのでしょう?

実行計画のPredicate Informationセクションにはどのような索引を作成するかを決定するための重要な情報がリストされています。

気づきましたか?

以下の2行が重要。

2 - filter("IS_DELETE"=0)
3 - access("NON_UNIQUE_ID"=70)

NON_UNIQUE_ID列に作成されている索引を利用して行を取得し、IS_DELETE=0 でフィルタ処理を実施していることがわかります。

ということは、 NON_UNIQUE_ID,IS_DELETEの2列(つまりWHERE句に記述されている検索条件)がアクセスパスですよね。

次に、選択リスト/GROUP BY句/ORDER BY句を見ると NON_UNIQUE_ID2毎のCOUNT()を取りNON_UNIQUE_ID2を昇順にソートしていることがわかります。

NON_UNIQUE_ID,IS_DELETE列アクセスして、NON_UNIQUE_ID2が昇順にソート済みとなっている索引があればindex only accessになるはず!

14:47:14 SCOTT> @demo2_ix
create index tab1_ix_demo2 on tab1(non_unique_id,is_delete,non_unique_id2) logging invisible

索引が作成されました。

経過: 00:00:00.63
alter session set optimizer_use_invisible_indexes=true

セッションが変更されました。

経過: 00:00:00.01


結果は...

index range scanのみになり、SORT GROUP BY NOSORTというオペレーションからもわかるように、ソート処理が省略されています。;)

consistent getsは約1/50、処理時間は60msから10msまで改善しました。

14:47:28 SCOTT> @demo2

システムが変更されました。

経過: 00:00:00.03
1 select
2 non_unique_id2
3 ,count(1)
4 from
5 tab1
6 where
7 non_unique_id = 70
8 and is_delete = 0
9 group by
10 non_unique_id2
11 order by
12* non_unique_id2

経過: 00:00:00.01

実行計画
----------------------------------------------------------
Plan hash value: 2668135026

--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 63 | 630 | 1 (0)| 00:00:01 |
| 1 | SORT GROUP BY NOSORT| | 63 | 630 | 1 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | TAB1_IX_DEMO2 | 100 | 1000 | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - access("NON_UNIQUE_ID"=70 AND "IS_DELETE"=0)


統計
----------------------------------------------------------
0 recursive calls
0 db block gets
2 consistent gets
2 physical reads
0 redo size
517 bytes sent via SQL*Net to client
416 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed

作成した索引を削除して次のデモへ。

14:47:33 SCOTT> @drop_demo2_ix
drop index tab1_ix_demo2

索引が削除されました。

経過: 00:00:00.10
alter session set optimizer_use_invisible_indexes=false

セッションが変更されました。

経過: 00:00:00.00

・demo3

これdemo2の応用編です. 行長の長い行をある程度の範囲でレンジ検索し、最小値(min)を取得するものです。最大値(max)でも考え方は同じ。

14:47:49 SCOTT> @demo3

システムが変更されました。

経過: 00:00:00.04
1 select
2 min(non_unique_id2)
3 from
4 tab1
5 where
6 non_unique_id = 70
7* and is_delete = 0

経過: 00:00:00.05

実行計画
----------------------------------------------------------
Plan hash value: 255634452

-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 10 | 101 (0)| 00:00:02 |
| 1 | SORT AGGREGATE | | 1 | 10 | | |
|* 2 | TABLE ACCESS BY INDEX ROWID| TAB1 | 100 | 1000 | 101 (0)| 00:00:02 |
|* 3 | INDEX RANGE SCAN | TAB1_IX1 | 100 | | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - filter("IS_DELETE"=0)
3 - access("NON_UNIQUE_ID"=70)


統計
----------------------------------------------------------
0 recursive calls
0 db block gets
103 consistent gets
103 physical reads
0 redo size
456 bytes sent via SQL*Net to client
416 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed


demo2と同様に、WHERE句で参照されている検索条件列がアクセスパスになるような索引に、選択リスト中のmin()関数で参照されている列を追加した索引でindex only accessになりそうですよね。

14:47:51 SCOTT> @demo3_ix
create index tab1_ix_demo3 on tab1(non_unique_id, is_delete, non_unique_id2) nologging invisible

索引が作成されました。

経過: 00:00:00.65
alter session set optimizer_use_invisible_indexes=true

セッションが変更されました。

経過: 00:00:00.00


結果は、狙い通りになりました!

処理時間は40msから10msへ。consistent getsは約1/50に改善しました。

実行計画のINDEX RANGE SCAN (MIN/MAX) 〜 FIRST ROWSという素敵なオペレーションが現れています。

Rowsを見ると索引作成前は 100行選択して1行返すという無駄の多い(99行は捨てている)操作から1行とってきて1行返すというエコな動きをしていることが確認できます! 素敵ですね。

14:48:05 SCOTT> @demo3

システムが変更されました。

経過: 00:00:00.04
1 select
2 min(non_unique_id2)
3 from
4 tab1
5 where
6 non_unique_id = 70
7* and is_delete = 0

経過: 00:00:00.01

実行計画
----------------------------------------------------------
Plan hash value: 3012701563

----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 10 | 2 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 10 | | |
| 2 | FIRST ROW | | 1 | 10 | 2 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN (MIN/MAX)| TAB1_IX_DEMO3 | 1 | 10 | 2 (0)| 00:00:01 |
----------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

3 - access("NON_UNIQUE_ID"=70 AND "IS_DELETE"=0)


統計
----------------------------------------------------------
0 recursive calls
0 db block gets
2 consistent gets
2 physical reads
0 redo size
456 bytes sent via SQL*Net to client
416 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed

作詞絵作成した索引を削除して次のデモへ...

14:48:09 SCOTT> @drop_demo3_ix
drop index tab1_ix_demo3

索引が削除されました。

経過: 00:00:00.09
alter session set optimizer_use_invisible_indexes=false

セッションが変更されました。

経過: 00:00:00.01


・demo4

大人の事情で実行計画だけみてるとチューニングなんて不要でしょ! という感じのクエリをチューニングできないか?

と依頼されたら・・・

2つの表を結合した結果でgorup/order byしているのでソート処理のバイパスはできせんが、index only accessを使ってNested Loop結合でアクセスされるブロック数を最小化することはできますよね。

14:48:26 SCOTT> @demo4

システムが変更されました。

経過: 00:00:00.12
1 select
2 d.non_unique_id
3 ,m.unique_id2
4 ,count(1)
5 from
6 tab2 m join tab1 d
7 on m.unique_id2 = d.non_unique_id2
8 and m.is_delete = 0
9 and d.is_delete = 0
10 where
11 m.unique_id2 between 1 and 10
12 group by
13 d.non_unique_id
14 ,m.unique_id2
15 order by
16 d.non_unique_id
17* ,m.unique_id2

100行が選択されました。

経過: 00:00:01.71

実行計画
----------------------------------------------------------
Plan hash value: 1194523033

-------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1034 | 16544 | 539 (1)| 00:00:07 |
| 1 | SORT GROUP BY | | 1034 | 16544 | 539 (1)| 00:00:07 |
| 2 | NESTED LOOPS | | | | | |
| 3 | NESTED LOOPS | | 1034 | 16544 | 537 (0)| 00:00:07 |
|* 4 | TABLE ACCESS BY INDEX ROWID| TAB2 | 10 | 60 | 2 (0)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | TAB2_PK | 10 | | 1 (0)| 00:00:01 |
|* 6 | INDEX RANGE SCAN | TAB1_IX2 | 111 | | 1 (0)| 00:00:01 |
|* 7 | TABLE ACCESS BY INDEX ROWID | TAB1 | 103 | 1030 | 106 (0)| 00:00:02 |
-------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

4 - filter("M"."IS_DELETE"=0)
5 - access("M"."UNIQUE_ID2">=1 AND "M"."UNIQUE_ID2"<=10)
6 - access("M"."UNIQUE_ID2"="D"."NON_UNIQUE_ID2")
filter("D"."NON_UNIQUE_ID2"<=10 AND "D"."NON_UNIQUE_ID2">=1)
7 - filter("D"."IS_DELETE"=0)


統計
----------------------------------------------------------
0 recursive calls
0 db block gets
9604 consistent gets
5793 physical reads
0 redo size
2588 bytes sent via SQL*Net to client
482 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
100 rows processed


WHERE句やPredicate Informationからも駆動表(TAB2)と内部表(TAB1)は判断できると思います。

駆動表(TAB2)はWHERE句の検索条件および結合条件でアクセスパスとなる列が参照されています。
内部表(TAB1)はWHERE句では参照されておらず、結合条件でのみアクセスパスとなる列が参照されていることがわかります。

選択リストやGROUP/ORDER BY句から、内部表(TAB1)のNON_UNIQUE_ID列も索引に含める必要があるとわかるはずです。

既に気づいた方も多いと思うのですが、index only access化に必要な索引列候補はSQL文だけでも見つけることができるんですよ。

ただ、複雑な結合などが含まれる場合は、実行計画計画やPredicate Informationに有益な情報が載っているので、できれば合わせて見ておくと吉ですね。  

Truth is out there! :) って場合もあるってことで。

14:48:31 SCOTT> @demo4_ix
create index tab2_ix_demo4 on tab2(unique_id2,is_delete) nologging invisible

索引が作成されました。

経過: 00:00:00.06
create index tab1_ix_demo4 on tab1(non_unique_id2, is_delete, non_unique_id) nologging invisible

索引が作成されました。

経過: 00:00:01.21
alter session set optimizer_use_invisible_indexes=true

セッションが変更されました。

経過: 00:00:00.00


大きなクエリほど効果は絶大ということで。

1710msから50msに改善してます。consistents getsは、1/291に :)

14:49:04 SCOTT> @demo4

システムが変更されました。

経過: 00:00:00.05
1 select
2 d.non_unique_id
3 ,m.unique_id2
4 ,count(1)
5 from
6 tab2 m join tab1 d
7 on m.unique_id2 = d.non_unique_id2
8 and m.is_delete = 0
9 and d.is_delete = 0
10 where
11 m.unique_id2 between 1 and 10
12 group by
13 d.non_unique_id
14 ,m.unique_id2
15 order by
16 d.non_unique_id
17* ,m.unique_id2

100行が選択されました。

経過: 00:00:00.04

実行計画
----------------------------------------------------------
Plan hash value: 1672990879

------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1034 | 16544 | 31 (4)| 00:00:01 |
| 1 | SORT GROUP BY | | 1034 | 16544 | 31 (4)| 00:00:01 |
| 2 | NESTED LOOPS | | 1034 | 16544 | 30 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN| TAB1_IX_DEMO4 | 10314 | 100K| 30 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN| TAB2_IX_DEMO4 | 1 | 6 | 0 (0)| 00:00:01 |
------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

3 - access("D"."NON_UNIQUE_ID2">=1 AND "D"."IS_DELETE"=0 AND
"D"."NON_UNIQUE_ID2"<=10)
filter("D"."IS_DELETE"=0)
4 - access("M"."UNIQUE_ID2"="D"."NON_UNIQUE_ID2" AND "M"."IS_DELETE"=0)
filter("M"."UNIQUE_ID2"<=10 AND "M"."UNIQUE_ID2">=1)


統計
----------------------------------------------------------
0 recursive calls
0 db block gets
33 consistent gets
31 physical reads
0 redo size
2588 bytes sent via SQL*Net to client
482 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
100 rows processed

14:49:09 SCOTT> @drop_demo4_ix
drop index tab1_ix_demo4

索引が削除されました。

経過: 00:00:00.11
drop index tab2_ix_demo4

索引が削除されました。

経過: 00:00:00.04
alter session set optimizer_use_invisible_indexes=false

セッションが変更されました。

経過: 00:00:00.00


Enjoy!



Index Only Access (Index Only Scan) っていいよね(デメリットもあるけどさ) #1
Index Only Access (Index Only Scan) っていいよね(デメリットもあるけどさ) #2

Index Only Scan, JPOUG, OOW, Oracle Database 11g, SQL, VirtualBox, チューニング | | コメント (1) | トラックバック (0)

2012年1月30日 (月)

AWRレポート、AWR SQLレポート一括取得スクリプトを作ったよ。

Statspackレポートもそうなのですが、AWRレポート/AWR SQLレポートも個別に取得していると凄ーく辛いんですよね。一日分出力するとか、AWRレポートで処理時間の長いSQL文のAWR SQLレポートを個別に取得しようとなると...

ただでさえ忙しいのに、AWRレポート取得するのに時間掛けたくないですよね。

ということで、やっつけで作ったのですが、そのまま載せるのもあれなんで、やっつけで作った感じを多少減らしてgithubに公開しました。;)

https://github.com/discus/Oracle-AWR-batch-generation-script/blob/master/awrreport_batch.sql


もっといい感じに改造してくれるといいな〜とかとか... :)

Oracle11g R1/R2 Enterprise Edition、HTML形式で出力します。(RAC環境では試してないので多分だめかと。)。
AWRを利用するには追加ライセンスが必要なのでご注意を


使い方は・・

SQL*plusを起動し、select any dictionaryシステム権限、dbms_repositoryパッケージの実行権限が付与されたユーザで接続して実行するだけ。
SYSTEMユーザでやる事が多いけど、所変わればなんとやらなので・・・そこんとこよろしく。(w


一括取得なので実行当日を含めてn日分のAWRレポートを取得し、同時に処理時間の長いTop20のAWR SQLレポートも取得します。
レポートは各スナップショット間(今のところ固定)で取得します。

指定するパラメータは、以下の3つ。

Enter snap_id for starting AWR report generation. [NULL] : 
AWRレポートを取得する最初のSNAP_IDを指定します。 NULLがデフォルトでほとんどの場合デフォルトのままで事足りると思います。


Enter number of days for reporting period. [1] : 

一括取得する日数を指定します。当日を含みます。
当日分のAWRレポートを出力するのであれば、デフォルト値の1のままでOKです。


Enter suffix for AWR reports filename. [NULL] : test

保存するAWRレポートのファイル名に付加するsuffixを指定します。
試験名とか設定するといいですよね。

"test"と指定した場合

awrrpt_nnnn_nnnn_test.htmlや
awrsqrpt_nnnn_nnnn_test_sqlid.html

の形式で保存します。(nnnnはSNAP_ID)


実行例1)当日分の全レポートを取得する例

SYSTEM> 
SYSTEM> !ls -l awr*.sql
-rw-r--r-- 1 oracle oinstall 6065 1月 29 18:23 awrreport_batch.sql

SYSTEM> @awrreport_batch
--
-- Oracle AWR and AWR SQL report batch generation script
--
-- ***** This script always generate html format AWR reports. *****
--
Enter snap_id for starting AWR report generation. [NULL] :
Enter number of days for reporting period. [1] :
Enter suffix for AWR reports filename. [NULL] : test
--
--
--
clear break compute;
repfooter off;
ttitle off;
btitle off;

・・・中略・・・

<p />
<br /><a class="awr" href="#top">Back to Top</a><p />
</body></html>

SYSTEM>


実行例2)当日分かつsnap_id=291以降で一括取得。(事前にsnap_idを調べておいてね)

SYSTEM> 
SYSTEM> @awrreport_batch
--
-- Oracle AWR and AWR SQL report batch generation script
--
-- ***** This script always generate html format AWR reports. *****
--
Enter snap_id for starting AWR report generation. [NULL] : 291
Enter number of days for reporting period. [1] :
Enter suffix for AWR reports filename. [NULL] : test
--
--
--
clear break compute;
repfooter off;
ttitle off;
btitle off;

・・・中略・・・

<p />
<br /><a class="awr" href="#top">Back to Top</a><p />
</body></html>

SYSTEM>
SYSTEM>
SYSTEM> !ls -l *.html
-rw-r--r-- 1 oracle oinstall 379083 1月 29 22:23 awrrpt_291_292_test.html
-rw-r--r-- 1 oracle oinstall 11899 1月 29 22:23 awrsqrpt_291_292_test_0c83z9rqx45hu.html
-rw-r--r-- 1 oracle oinstall 11899 1月 29 22:23 awrsqrpt_291_292_test_0h3mfbzk6uyw0.html
-rw-r--r-- 1 oracle oinstall 11897 1月 29 22:23 awrsqrpt_291_292_test_2p7t0mw7zvu5z.html

・・・中略・・・

-rw-r--r-- 1 oracle oinstall 11899 1月 29 22:23 awrsqrpt_291_292_test_bhtycgwkxhfj9.html
-rw-r--r-- 1 oracle oinstall 11900 1月 29 22:23 awrsqrpt_291_292_test_bpaggvtfkar9k.html
-rw-r--r-- 1 oracle oinstall 11899 1月 29 22:23 awrsqrpt_291_292_test_c50hdbyuwhfn6.html
-rw-r--r-- 1 oracle oinstall 11892 1月 29 22:23 awrsqrpt_291_292_test_g3f3cw3zy5aat.html

SYSTEM>

なお、Oracleインスタンスが再起動された期間でawrrpt.sqlなどを実行すると、レポートが作成できずエラーでSQL*Plusも終了してしまいますが、本スクリプトでは該当部分のレポートはスキップするようにしてあります。:)

Instance     DB Name      Snap Id   Snap Started       Level
------------ ------------ --------- ------------------ -----
lampeye LAMPEYE 274 29 1月 2012 09:33 1
275 29 1月 2012 10:00 1
276 29 1月 2012 10:30 1
277 29 1月 2012 11:00 1
278 29 1月 2012 11:30 1
279 29 1月 2012 12:00 1
280 29 1月 2012 12:30 1
281 29 1月 2012 13:00 1
282 29 1月 2012 13:30 1
283 29 1月 2012 14:00 1
284 29 1月 2012 14:30 1
285 29 1月 2012 15:00 1
286 29 1月 2012 15:30 1
287 29 1月 2012 16:00 1
288 29 1月 2012 16:30 1
289 29 1月 2012 17:00 1
290 29 1月 2012 17:30 1

291 29 1月 2012 18:31 1 ←再起動されてる
292 29 1月 2012 18:34 1

293 29 1月 2012 22:26 1 ←再起動されてる


Enjoy!

| | コメント (2) | トラックバック (0)

2012年1月14日 (土)

shutdown immeidateしない、ほかの理由に遭遇! (FYI)


ず〜〜〜〜っと、追記しようと思ってたんだけど書いてなかったので、徹夜明けで早起きした次いでなんで書いておきます。

もう一年近く前のネタなんだけどね。「shutdown immeidateしない、ほかの理由に遭遇!」

> yoheia-a さんありがとう :)

私か書いた記事がキッカケで調べなきゃいけなくなったらしいんだけどね。 ;)

http://d.hatena.ne.jp/yohei-a/20110627/1309180675




shutdown immeidateしない、ほかの理由に遭遇!
shutdown immeidateしない、ほかの理由に遭遇! #2
shutdown immeidateしない、ほかの理由に遭遇! #3
shutdown immeidateしない、ほかの理由に遭遇! おまけ
shutdown immeidateしない、ほかの理由に遭遇! おまけのおまけ(でた〜最近、よくあるパターンw)

| | コメント (0) | トラックバック (0)

2012年1月 6日 (金)

Index Only Access (Index Only Scan) っていいよね(デメリットもあるけどさ) #2

Index Only Accessのいいとこ、紹介しちゃいますの続きです。

前回は、索引しかアクセスしない(Index Only Access)場合と、索引+表データもアクセスしちゃう場合の実行計画上の違いを確認しましたよね。


今回は、Index Only Accessで得られる改善効果の1つであるソート処理の回避について簡単な例で確認してみます。

※VISIBLE/INVISIBLEにしている索引の詳細は前回の記事を参照してくださいね。

Now Playing ♪ - ハイスクールララバイ / イモ欽トリオ - 1981

まず、最初は、悪い子の例から。

索引を全表走査した上で order by seq# でソート処理が実行されます。酷いですね。検索条件列に適切な索引を作れよ〜〜〜っ。という状態ですね。

SQL> alter index tab10_i01 invisible;

索引が変更されました。

SQL> alter index tab10_i02 invisible;

索引が変更されました。

SQL> select seq# from tab10 where non_unique_key = '0000000001' order by seq#;

10行が選択されました。

経過: 00:00:04.99

実行計画
----------------------------------------------------------
Plan hash value: 2100371779

----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 10 | 160 | 16788 (1)| 00:03:22 |
| 1 | SORT ORDER BY | | 10 | 160 | 16788 (1)| 00:03:22 |
|* 2 | TABLE ACCESS FULL | TAB10 | 10 | 160 | 16787 (1)| 00:03:22 |
----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - filter("NON_UNIQUE_KEY"='0000000001')


統計
----------------------------------------------------------
0 recursive calls
0 db block gets
61544 consistent gets
61540 physical reads
0 redo size
655 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
10 rows processed

次に、普通の子の例。

検索条件であるnon_unique_keyに定義された索引を使いIndex range scanかつ、seq#をアクセスするために表データをrowidでアクセス。その後にソート処理が行われています。

普通の子らしい、よい実行計画ですね。 :)

SQL> alter index tab10_i01 visible;

索引が変更されました。

SQL> alter index tab10_i02 invisible;

索引が変更されました。

SQL> select seq# from tab10 where non_unique_key = '0000000001' order by seq#;

10行が選択されました。

経過: 00:00:00.08

実行計画
----------------------------------------------------------
Plan hash value: 1783972576

------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 10 | 160 | 5 (20)| 00:00:01 |
| 1 | SORT ORDER BY | | 10 | 160 | 5 (20)| 00:00:01 |
| 2 | TABLE ACCESS BY INDEX ROWID| TAB10 | 10 | 160 | 4 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | TAB10_I01 | 10 | | 3 (0)| 00:00:01 |
------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

3 - access("NON_UNIQUE_KEY"='0000000001')


統計
----------------------------------------------------------
0 recursive calls
0 db block gets
4 consistent gets
17 physical reads
0 redo size
655 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
10 rows processed

そして、最後は、良い子の登場。

この子、データ量が多くなった場合、ソート処理も足枷になると考えたようで Index only accessを利用したソート処理回避作戦を取ったようです。 
実行計画をみればわかりますが、索引しかアクセスしておらず、SORT ORDER BY というオペレーションも消えています!

検索条件である、non_unique_key列とソート対象のseq#列の2列からなる複合索引を利用するIndex only accessを狙ったようですね。

ただし、これには order by seq# [asc]であるという大前提があります。
order by seq# desc というソートも考慮する必要がある場合には、non_unique_key [asc]とseq# desc とした別の複合索引必要になります。(デメリットといえばデメリットですかね、)

order by seq# descというソート条件が仕様上無い事を事前に確認しておけば、なお完璧ですよね〜。 良い子。流石です。 :)

SQL> alter index tab10_i01 invisible;

索引が変更されました。

SQL> alter index tab10_i02 visible;

索引が変更されました。

SQL> select seq# from tab10 where non_unique_key = '0000000001' order by seq#;

10行が選択されました。

経過: 00:00:00.01

実行計画
----------------------------------------------------------
Plan hash value: 489654843

------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 10 | 160 | 3 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| TAB10_I02 | 10 | 160 | 3 (0)| 00:00:01 |
------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - access("NON_UNIQUE_KEY"='0000000001')


統計
----------------------------------------------------------
0 recursive calls
0 db block gets
4 consistent gets
16 physical reads
0 redo size
655 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
10 rows processed


次回へつづく。(他のソート回避の例も紹介しちゃうか、考えちう)


Index Only Access (Index Only Scan) っていいよね(デメリットもあるけどさ) #1

いん!、イン!、Index どっぷり Inde Only Access生活w - Oracle OpenWorld Unconference presented by JPOUG

| | コメント (0) | トラックバック (0)

2012年1月 4日 (水)

Index Only Access (Index Only Scan) っていいよね(デメリットもあるけどさ) #1

さて、OracleさんがAppleさんのOSで楽しいことしてくれないから最近つまんなくなりつつあるので、普通にSQL文のチューニングネタです。


鬼熱かった、鬼熱かった! :: Insight out 2011- DB tech showcaseでもかなり触れていた、Index Only Scan日本ではこの表現が割合的に多いようなのですが、Index Only Accessって言ってましたね、トムカイトさんも。英語では後者のほうが一般的なのかもしれません。ここではIndex Only Accessってことにしておきます。;)


デメリットもあるけど、Index Only Accessのいいとこばかりを中心に、書いちゃうよ〜w


まず、前提から。

TAB10表は以下のように定義してあります。意図的に表データが大きくなるようにしてあります :)

 名前                NULL?    型
------------------ -------- --------------
SEQ# NOT NULL NUMBER
NON_UNIQUE_KEY NOT NULL CHAR(10)
DATA VARCHAR2(500)

また、以下のような索引を事前に索引しているが、PK_TAB10という主キー索引以外はINVISIBLEとして作成してある。
INVISIBLEで作成しておくと、索引は通常通りメンテナンスされるが、オプティマイザは実行計画作成時にINVISIBLEな索引を利用しないというOracle11gから登場した便利な機能

また前述の表には以下のような主キー(PK_TAB10)と非ユニークな索引が2つ作成してあります。(あまり良い例ではないですがご勘弁を)
但し、TAB10_I01、TAB10_I02の2索引は、INVISIBLEで作成してあります。効果確認時など便利ですよね。
(不可視索引の詳細はマニュアル「Oracle Database 管理者ガイド 11gリリース1(11.1)不可視索引の作成」を参照のこと。


INDEX_NAME COLUMN_NAME
------------ -------------------
PK_TAB10 SEQ#

TAB10_I01 NON_UNIQUE_KEY

TAB10_I02 NON_UNIQUE_KEY
SEQ#

検証時の処理時間及び、実行統計は、各クエリを2回実行し2回目の処理時間及び、実行統計を載せてあります。
(2回目の実行前にバッファキャッシュをクリアしてあるので、ソフトパース+キャッシュミスほぼ100%という状況の処理時間及び実行統計情報です。)

テストデータは以下件数で、non_unique_keyは偏りはなく均一に分布させあります。
実際のはなし、均等になることの方が稀ではあると思いますけど、Index Only Accessの効果を見る事ができればそれでOKなので。

COUNT(1)
----------
800000


COUNT(DISTINCTNON_UNIQUE_KEY)
-----------------------------
80000


NON_UNIQUE COUNT(1)
---------- ----------
0000000001 10
0000000002 10
0000000003 10
0000000004 10
0000000005 10
0000000006 10
0000000007 10
0000000008 10
0000000009 10
0000000010 10
0000000011 10
0000000012 10
0000000013 10
0000000014 10
0000000015 10
0000000016 10
0000000017 10
0000000018 10
0000000019 10
0000000020 10

・・・以下略・・・

まず最初は一番分かりやすい、Index Only Accessの例から。

non_unique_key列に、TAB10_I01という非ユニーク索引を作成してありますが、現状、INVISIBLE状態にしてあるため索引が無く全表走査となっていますよね。

SQL> set autot trace exp stat
SQL>
SQL> select count(non_unique_key) from tab10 where non_unique_key between '0000000001' and '0000000010';

経過: 00:00:04.32

実行計画
----------------------------------------------------------
Plan hash value: 1584905094

----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 11 | 16787 (1)| 00:03:22 |
| 1 | SORT AGGREGATE | | 1 | 11 | | |
|* 2 | TABLE ACCESS FULL| TAB10 | 100 | 1100 | 16787 (1)| 00:03:22 |
----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - filter("NON_UNIQUE_KEY"<='0000000010' AND
"NON_UNIQUE_KEY">='0000000001')


統計
----------------------------------------------------------
0 recursive calls
0 db block gets
61544 consistent gets
61539 physical reads
0 redo size
562 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed

ここで、TAB10_I01索引をVISIBLEへ変更して同一クエリを実行してみると……
TAB10_I01索引を利用した実行計画はIndex Range Scanに変化します。しかも、表データはアクセスしていません。これがIndex Only Accessの典型的な例です。アクセスブロック数も処理時間も大きく改善していますよね。

ただ、Index only scanにはデメリットもあります。

それは、索引が多くなればなるほどDML文には足枷になり遅くなるため点です。参照と更新、挿入、削除のバランスを取るのが大切ですが、
とにかく参照を速くする、更新、挿入、削除の処理性能などは少々犠牲にしても問題ないのであれば、どんどんやっちゃいます!(ご利用は計画的にw)

SQL> alter index tab10_i01 visible;
SQL>
SQL> select count(non_unique_key) from tab10 where non_unique_key between '0000000001' and '0000000010';

経過: 00:00:00.02

実行計画
----------------------------------------------------------
Plan hash value: 3770330610

-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU) | Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 11 | 3 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 11 | | |
|* 2 | INDEX RANGE SCAN| TAB10_I01 | 100 | 1100 | 3 (0)| 00:00:01 |
-------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - access("NON_UNIQUE_KEY">='0000000001' AND
"NON_UNIQUE_KEY"<='0000000010')


統計
----------------------------------------------------------
0 recursive calls
0 db block gets
3 consistent gets
3 physical reads
0 redo size
562 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed

ちなみに、クエリは少々違うのですが、Index only accessで無い場合は、index range scan+table access by index rowidとなり以下のような実行計画になっちゃいます。
(こちらの方がよく目にする実行計画じゃないでしょうかね。私も性能的な問題等なければ以下のような実行計画であれば良しとしておくことが多いのも事実です。。)

実行計画
----------------------------------------------------------
Plan hash value: 1097902029

------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 100 | 51700 | 11 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID | TAB10 | 100 | 51700 | 11 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | TAB10_I02 | 100 | | 3 (0)| 00:00:01 |
------------------------------------------------------------------------------------------

次回へつづく。(忙しくてなかなか書けないかもw)

| | コメント (0) | トラックバック (0)

2011年12月14日 (水)

PL/SQL de Conditional Compile #6

随分前にPL/SQL de Conditional Compile #5ってエントリ書いてたのを思い出して、11g R1/R2用のを見てみたらソースに丁寧なコメント(マニュアルよりいいんじゃね?w )が書かれていてうれしくなった。

オラクルさんとして見せたくない部分は見えないようになっているけど、見せても問題ないところはコードが見える(all_sourceビュー)わけで、それはそれでうれしいわけです。はい。マニュアルが意外に不親切だったりするので。

(マニュアル、良くなりましたよ。昔より。 > 褒めておかないとね、だれとなくw。)...文字サイズも多くしておきましたw

● Oracle11g R1 11.1 の DBMS_DB_VERSION

package dbms_db_version is
version constant pls_integer := 11; -- RDBMS version number
release constant pls_integer := 1; -- RDBMS release number

/* The following boolean constants follow a naming convention. Each
constant gives a name for a boolean expression. For example,
ver_le_9_1 represents version <= 9 and release <= 1
ver_le_10_2 represents version <= 10 and release <= 2
ver_le_10 represents version <= 10

A typical usage of these boolean constants is

$if dbms_db_version.ver_le_10 $then
version 10 and ealier code
$elsif dbms_db_version.ver_le_11 $then
version 11 code
$else
version 12 and later code
$end

This code structure will protect any reference to the code
for version 12. It also prevents the controlling package
constant dbms_db_version.ver_le_11 from being referenced
when the program is compiled under version 10. A similar
observation applies to version 11. This scheme works even
though the static constant ver_le_11 is not defined in
version 10 database because conditional compilation protects
the $elsif from evaluation if the dbms_db_version.ver_le_10 is
TRUE.
*/

ver_le_9_1 constant boolean := FALSE;
ver_le_9_2 constant boolean := FALSE;
ver_le_9 constant boolean := FALSE;
ver_le_10_1 constant boolean := FALSE;
ver_le_10_2 constant boolean := FALSE;
ver_le_10 constant boolean := FALSE;
ver_le_11_1 constant boolean := TRUE;
ver_le_11 constant boolean := TRUE;

end dbms_db_version;


● Oracle11g R2 11.2 の DBMS_DB_VERSION

package dbms_db_version is
version constant pls_integer := 11; -- RDBMS version number
release constant pls_integer := 2; -- RDBMS release number

/* The following boolean constants follow a naming convention. Each
constant gives a name for a boolean expression. For example,
ver_le_9_1 represents version <= 9 and release <= 1
ver_le_10_2 represents version <= 10 and release <= 2
ver_le_10 represents version <= 10

A typical usage of these boolean constants is

$if dbms_db_version.ver_le_10 $then
version 10 and ealier code
$elsif dbms_db_version.ver_le_11 $then
version 11 code
$else
version 12 and later code
$end

This code structure will protect any reference to the code
for version 12. It also prevents the controlling package
constant dbms_db_version.ver_le_11 from being referenced
when the program is compiled under version 10. A similar
observation applies to version 11. This scheme works even
though the static constant ver_le_11 is not defined in
version 10 database because conditional compilation protects
the $elsif from evaluation if the dbms_db_version.ver_le_10 is
TRUE.
*/

ver_le_9_1 constant boolean := FALSE;
ver_le_9_2 constant boolean := FALSE;
ver_le_9 constant boolean := FALSE;
ver_le_10_1 constant boolean := FALSE;
ver_le_10_2 constant boolean := FALSE;
ver_le_10 constant boolean := FALSE;
ver_le_11_1 constant boolean := FALSE;
ver_le_11_2 constant boolean := TRUE;
ver_le_11 constant boolean := TRUE;

end dbms_db_version;

version 12 and later codeなんて箇所、いいですね〜w


PL/SQL de Conditional Compile #1
PL/SQL de Conditional Compile #2
PL/SQL de Conditional Compile #3
PL/SQL de Conditional Compile #4
PL/SQL de Conditional Compile #5

| | コメント (0) | トラックバック (0)

2011年12月 5日 (月)

Oracle11g R1のAWRレポートでは%idleと%iowaitが逆なのな。

Oracle11g R1のAWRって仕事でも使うこともそれなりにあるわけですが、なんと、いままで気づかなかったAWRレポートのバグみつけ〜ということで(とっくに気づいていた人はいたはずだけど、基本、11g R1だと修正する気はナッシングと思われw)。メモ代わり。
(でも、リリースされてからづ〜〜と気づかなかったということは私はOperating System Statisticsセクションはスルーしてて見てなかったということなんだろーなー多分)


以下、AWRレポートを出力した時間帯のsarの結果、どう見ても暇な状況なわけですよ。

02時33分37秒       CPU     %user     %nice   %system   %iowait    %steal     %idle
02時33分47秒 all 0.29 0.00 0.13 0.14 0.00 99.44
02時33分57秒 all 0.10 0.00 0.08 0.01 0.00 99.81
02時34分07秒 all 0.20 0.00 0.10 0.02 0.00 99.68
02時34分17秒 all 0.04 0.00 0.02 0.08 0.00 99.86
02時34分27秒 all 0.14 0.00 0.03 0.03 0.00 99.80
02時34分37秒 all 0.13 0.00 0.03 0.03 0.00 99.82
02時34分47秒 all 0.14 0.00 0.02 0.01 0.00 99.83
02時34分57秒 all 0.03 0.00 0.01 0.00 0.00 99.97
02時35分07秒 all 0.11 0.00 0.02 0.03 0.00 99.84
02時35分17秒 all 0.08 0.00 0.03 0.01 0.00 99.88

AWRレポートのHost CPUセクションを見るとまあ、そんな感じなわけです。はい。


20111205_23655

でも、Operating SYstem Statistics - Detailセクションを見ると、%iowaitが99.77で、%idleが0.12となっていて、ここだけみるとびっくり〜しちゃうわけですよ〜。

20111205_23726


Oracle11g R1 11.1.0.x.xのAWRレポートは皆こんな状態でリストされるので、Operating System Statistics - Detailセクション見る場合は%ildeと%iowaitの値は脳内で入れ替えてね :) というお話でした。

ちなみに、Oracle11g R2ではしっかり修正されていますね。Oracle11g R1のAWRレポート見て驚かないためのメモw でした。

| | コメント (0) | トラックバック (0)

2011年9月13日 (火)

オラクルは会議室で動いてんじゃな〜〜イ。統計情報で動いてんだ!

と少々無理矢理なタイトル付けてみました:) 今回はチューニングはチューニングでも、statspack.snap()のチューニングのお話。

注)表現はそれなりに脚色してありますw


ある日のこと。

大トラブルなんです〜(こういう人、うまくいってないプロジェクトにはよくいます。全然”大”じゃないのに、もう口癖なんでしょうねw)

statspack.snap()がものすごく遅いんです! なんとかなりませんか?

ん〜〜〜、で、状況を教えてください。

PERFSTAT> 
PERFSTAT> exec statspack.snap(i_snap_level=>7,i_executions_th=>0);

PL/SQLプロシージャが正常に完了しました。

経過: 00:00:31.46

・・・・中略・・・・

PERFSTAT> exec statspack.snap(i_snap_level=>7,i_executions_th=>0);

PL/SQLプロシージャが正常に完了しました。

経過: 00:06:28.02

説明によると、こんな状況になっていたらしい。最初は30秒ぐらいで終わっていたのに、ここ最近は5分以上になり今日はついに6分超えたとか。

で……statspack.snap()の時間がかかってて試験の消化に支障でてんですよね…とか、

マシン貧弱だからな…とか、

と打ち合わせでも話題になることしばしば…


で、この状態になってからやっと、訪ねてきたわけね.

・・・・マシン環境について、しばし歓談タイム〜・・・・

話していて気づいた!

あ!、その試験環境って、統計情報の自動収集は止められてますよね。しかも試験する時に取得している統計情報って試験用のユーザだけ統計情報収集していますよね〜。

あれだ!、  感のいいかあなたなら気づきましたよね。ね。ね。:)

次のディクショナリを見れば一目瞭然! :)

PERFSTAT> select table_name,num_rows,stale_stats,last_analyzed from user_tab_statistics;

TABLE_NAME NUM_ROWS STA LAST_ANA
------------------------------ ---------- --- --------
STATS$BUFFERED_QUEUES
STATS$BUFFERED_SUBSCRIBERS
STATS$BUFFER_POOL_STATISTICS
STATS$CR_BLOCK_SERVER
STATS$CURRENT_BLOCK_SERVER
STATS$DATABASE_INSTANCE
STATS$DB_CACHE_ADVICE
STATS$DLM_MISC
STATS$DYNAMIC_REMASTER_STATS
STATS$ENQUEUE_STATISTICS
STATS$EVENT_HISTOGRAM

・・・・中略・・・・

STATS$STREAMS_POOL_ADVICE
STATS$SYSSTAT
STATS$SYSTEM_EVENT
STATS$SYS_TIME_MODEL
STATS$TEMPSTATXS
STATS$TEMP_SQLSTATS
STATS$THREAD
STATS$TIME_MODEL_STATNAME
STATS$UNDOSTAT
STATS$WAITSTAT

72行が選択されました。


じゃ〜、統計情報収集しましょーよー、ちゃんと! 

23:58:46 PERFSTAT> execdbms_stats.gather_schema_stats(ownname=>'PERFSTAT',no_invalidate=>false,cascade=>true);

PL/SQLプロシージャが正常に完了しました。

経過: 00:00:04.02

試してみて!、 staspack.snap()を!  ね!  前よりすげー速くなった!

23:58:50 PERFSTAT> exec statspack.snap(i_snap_level=>7,i_executions_th=>0);

PL/SQLプロシージャが正常に完了しました。

経過: 00:00:01.38


STATSPACK.SNAP()内で実行されてるSQL文にも統計情報は必要ですよーーーーーーーーーーーーと。

ごれぐらい”ー”付けてればわかってくれるかなー:)


一発ネタは、これにて FIN

| | コメント (0) | トラックバック (0)

2011年9月 8日 (木)

悩ませ過ぎは及ばざるがごとし #7 - おまけ

最近、おまけ付けるの好きなので:)

コストベースオプティマイザがどんだけ考えているか、チューニング前とチューニング後(案1と案2)でトレースファイルサイズで比較してみることに(本来それだけで比較できるものではないとは思いますが、あまりにも差があるのでw)


コストベースオプティマイザのトレースは次のようにして取得できますよね(詳細はググってね)

SCOTT> alter session set events='10053 trace name context forever, level 1';

セッションが変更されました。

経過: 00:00:00.00
SCOTT> SELECT …… 

・・・仲略・・・

5999行が選択されました。

経過: 00:00:53.48

SCOTT> alter session set events='10053 trace name context off';

セッションが変更されました。

経過: 00:00:00.00

SCOTT>

オプティマイザトレースファイルのサイズを比較すると以下のようになります:) 
オプティマイザを悩ますクエリ、ヒントで考えるな!感じろ!にしたクエリ(考えてますけど〜〜〜w)、最後が、相関副問合せに書き換えたクエリの順となっています。

[oracle@lampeye trace]$ ll
合計 59088
-rw-r----- 1 oracle oinstall 54431 9月 8 22:14 alert_lampeye2.log
-rw-r----- 1 oracle oinstall 54294792 9月 8 22:16 lampeye2_ora_5913.trc
-rw-r----- 1 oracle oinstall 5154103 9月 8 22:17 lampeye2_ora_5969.trc
-rw-r----- 1 oracle oinstall 898699 9月 8 22:19 lampeye2_ora_5981.trc
[oracle@lampeye trace]$

最初のトレースファイル(.trc),54294792バイトもありますよーw このオプティマイザトレースファイルがハードパースで48秒も考え込んでた時のものです。
(対象クエリも合わせて載せてみました)

-rw-r----- 1 oracle oinstall 54294792  9月  8 22:16 lampeye2_ora_5913.trc

こんなにオプティマイザを考えさせちゃうクエリ↓

SELECT
T1.surro_id,
T1.name,
T1.modified
FROM
test T1 JOIN (
SELECT DISTINCT
surro_id,
surro_bcd
FROM
test
) T2
ON
T1.surro_id = T2.surro_id AND
T1.surro_bcd = T2.surro_bcd
JOIN test T3
ON
T1.surro_id = T3.surro_id AND
T1.surro_acd= T3.surro_acd
WHERE
T1.surro_id IN (リテラル,....限界まで)
OR T1.surro_id IN (リテラル,....限界まで

.....以下....すきなだけ繰り返しw

/


2つめのトレースファイル、5154103バイトで、1/10程度になりましたーでも大きいですよね。これはヒントを付加して悩まないようにしてあげたものですが、それでもこんなサイズになってます!

-rw-r----- 1 oracle oinstall  5154103  9月  8 22:17 lampeye2_ora_5969.trc

案2、ヒントを付加したクエリでもこんなにでるのね。

SELECT   
/*+
LEADING(T1 T2 T3)
USE_HASH(T1 T2)
USE_HASH(T1 T3)
INDEX(T1 IX01_TEST)
INDEX(T3 IX01_TEST)
*/
T1.surro_id,
T1.name,
T1.modified
FROM
test T1 JOIN (
SELECT
/*+
MERGE
INDEX(test IX02_TEST)
*/
DISTINCT
surro_id,
surro_bcd
FROM
test
) T2
ON
T1.surro_id = T2.surro_id AND
T1.surro_bcd = T2.surro_bcd
JOIN test T3
ON
T1.surro_id = T3.surro_id AND
T1.surro_acd= T3.surro_acd
WHERE
T1.surro_id IN (リテラル,....限界まで)
OR T1.surro_id IN (リテラル,....限界まで)

.....以下....すきなだけ繰り返しw

/


最後のトレースファイルが(案1)、相関副問合せを利用して改善したクエリをハードパースした際に出力されたトレースファイルです。随分違うもんですねー

-rw-r----- 1 oracle oinstall   898699  9月  8 22:19 lampeye2_ora_5981.trc

案1、処理時間も短いけど、ほんと決断はやって感じですね。

SELECT
T1.surro_id
,T1.name
,T1.modified
FROM
test T1 JOIN (
SELECT DISTINCT
surro_id
,surro_bcd
FROM
test
) T2
ON
T1.surro_id = T2.surro_id AND
T1.surro_bcd = T2.surro_bcd
JOIN test T3
ON
T1.surro_id = T3.surro_id AND
T1.surro_acd= T3.surro_acd
WHERE
EXISTS (
SELECT
1
FROM
test_keys
WHERE
surro_id BETWEEN 1000000001 AND 1000005999
AND surro_id = T1.surro_id
)
/




ここまでのあらずじ

悩ませ過ぎは及ばざるがごとし #1
悩ませ過ぎは及ばざるがごとし #2
悩ませ過ぎは及ばざるがごとし #3
悩ませ過ぎは及ばざるがごとし #4
悩ませ過ぎは及ばざるがごとし #5
悩ませ過ぎは及ばざるがごとし #6

| | コメント (0) | トラックバック (0)

2011年9月 7日 (水)

悩ませ過ぎは及ばざるがごとし #6

前回のつづきです。

ヒントを使ってコストベースオプティマイザを悩ませないという方法で、40秒台っだった処理時間を1秒台にすることに成功しました。

これでも解決は解決なのですが、SQL文単体としては。ただ、インスタンスレベルて考えた場合無駄なメモリ使い過ぎだろという点が気がかり。コストベースオプティマイザが悩まなくなったことでCPUリソースの無駄遣いは回避できましたが、メモリリソースの無駄遣いが凄い。

ということで、どちらの無駄も減らす効果が期待できる案1を…

案1で書き換えるとヒントなしでも随分スッキリしちゃいます。
リテラル値が6000個近くありましたが、その部分を相関副問合せにしてあります。リテラル値の箇所はバインド変数化しちゃえばいいっすね。

SELECT
T1.surro_id
,T1.name
,T1.modified
FROM
test T1 JOIN (
SELECT DISTINCT
surro_id
,surro_bcd
FROM
test
) T2
ON
T1.surro_id = T2.surro_id AND
T1.surro_bcd = T2.surro_bcd
JOIN test T3
ON
T1.surro_id = T3.surro_id AND
T1.surro_acd= T3.surro_acd
WHERE
EXISTS (
SELECT
1
FROM
test_keys
WHERE
surro_id BETWEEN 1000000001 AND 1000005999
AND surro_id = T1.surro_id
)
/

実行してみると… (以下、SQL*Plusで set autot trace exp statコマンド叩いて実行した結果です。なお事前に共有プールはクリアしてあります。)

5999行が選択されました。

経過: 00:00:00.07

実行計画
----------------------------------------------------------
Plan hash value: 3724917145

-------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5997 | 468K| 144 (3)| 00:00:02 |
| 1 | VIEW | VM_NWVW_1 | 5997 | 468K| 144 (3)| 00:00:02 |
| 2 | HASH UNIQUE | | 5997 | 491K| 144 (3)| 00:00:02 |
|* 3 | HASH JOIN RIGHT SEMI | | 5997 | 491K| 143 (2)| 00:00:02 |
|* 4 | INDEX RANGE SCAN | PK_TEST_KEYS | 5999 | 41993 | 17 (0)| 00:00:01 |
|* 5 | HASH JOIN | | 5997 | 450K| 125 (1)| 00:00:02 |
|* 6 | INDEX RANGE SCAN | IX01_TEST | 5999 | 128K| 20 (0)| 00:00:01 |
|* 7 | HASH JOIN | | 5998 | 322K| 105 (1)| 00:00:02 |
|* 8 | INDEX RANGE SCAN | IX02_TEST | 5999 | 53991 | 19 (0)| 00:00:01 |
| 9 | TABLE ACCESS BY INDEX ROWID| TEST | 5999 | 269K| 85 (0)| 00:00:02 |
|* 10 | INDEX RANGE SCAN | IX02_TEST | 5999 | | 19 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------


SQL_ID        SHARABLE_MEM PERSISTENT_MEM RUNTIME_MEM SQL_TEXT
------------- ------------ -------------- ----------- ------------------------------
52gaz3tjd90dh 43446 15648 14504 SELECT T1.surro_id, T1.name,
T1.modified FROM test T1 jo
in ( SELECT DISTINCT s
urro_id, surro_bcd FROM
test ) T2 ON T1.surro_id
= T2.surro_id AND T1.surro
_bcd = T2.surro_bcd JO
IN test T3 ON T1.sur
ro_id = T3.surro_id AND T1.s
urro_acd= T3.surro_acd WHERE
EXISTS ( SELECT 1 FROM
test_keys WHERE surro_
id BETWEEN 1000000001 AND 1000
005999 AND T1.surro_id = su
rro_id )

きゃほーーーーーーっ。 最高〜〜〜〜っ! :) 言うことナッシングw  

処理時間が、48.83秒 から 0.07秒へ、SHARABLE_MEMが、3318142バイト から 43446バイトに。 でバインド変数化しちゃえば〜〜〜、

同時に多数のセッションから集中して発行されても耐えられそうな〜

最後に、ドヤ顔(キリっ

ほんとうにヤバそうなところはキッチリ潰しておきましょ!

OLTP系で実行計画はよいけど、コストベースオプティマイザを悩ませ過ぎて遅延してたら本末転倒ですよー。と。

ーーーー完ーーーーー


ここまでのあらずじ

悩ませ過ぎは及ばざるがごとし #1
悩ませ過ぎは及ばざるがごとし #2
悩ませ過ぎは及ばざるがごとし #3
悩ませ過ぎは及ばざるがごとし #4
悩ませ過ぎは及ばざるがごとし #5

| | コメント (0) | トラックバック (0)

2011年9月 6日 (火)

悩ませ過ぎは及ばざるがごとし #5

前回のつづきです。

前回は改善案を2つ提示しました。

まず、最初は案2のヒントを使って、コストベースオプティマイザに、「考えるな! 感じろ!」作戦w

元のクエリに次のようにヒントを書き加えちゃいます。
どの索引使えとか、結合方法はハッシュとか、とか、よく見かけるヒントだけです。

SELECT   
/*+
LEADING(T1 T2 T3)
USE_HASH(T1 T2)
USE_HASH(T1 T3)
INDEX(T1 IX01_TEST)
INDEX(T3 IX01_TEST)
*/
T1.surro_id,
T1.name,
T1.modified
FROM
test T1 JOIN (
SELECT
/*+
MERGE
INDEX(test IX02_TEST)
*/
DISTINCT
surro_id,
surro_bcd
FROM
test
) T2
ON
T1.surro_id = T2.surro_id AND
T1.surro_bcd = T2.surro_bcd
JOIN test T3
ON
T1.surro_id = T3.surro_id AND
T1.surro_acd= T3.surro_acd
WHERE
T1.surro_id IN (リテラル,....限界まで)
OR T1.surro_id IN (リテラル,....限界まで)

.....以下....すきなだけ繰り返しw

/

では実行してみると… (以下、SQL*Plusで set autot trace exp statコマンド叩いて実行した結果です。なお事前に共有プールはクリアしてあります。)

経過: 00:00:01.32

実行計画
----------------------------------------------------------
Plan hash value: 3720374973

----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5999 | 456K| 5796 (1)| 00:01:10 |
| 1 | VIEW | VM_NWVW_1 | 5999 | 456K| 5796 (1)| 00:01:10 |
| 2 | HASH UNIQUE | | 5999 | 451K| 5796 (1)| 00:01:10 |
|* 3 | HASH JOIN | | 5999 | 451K| 5795 (1)| 00:01:10 |
| 4 | INLIST ITERATOR | | | | | |
|* 5 | INDEX RANGE SCAN | IX01_TEST | 5999 | 128K| 1935 (1)| 00:00:24 |
|* 6 | HASH JOIN | | 5999 | 322K| 3859 (1)| 00:00:47 |
| 7 | INLIST ITERATOR | | | | | |
| 8 | TABLE ACCESS BY INDEX ROWID| TEST | 5999 | 269K| 2001 (1)| 00:00:25 |
|* 9 | INDEX RANGE SCAN | IX01_TEST | 5999 | | 1935 (1)| 00:00:24 |
| 10 | INLIST ITERATOR | | | | | |
|* 11 | INDEX RANGE SCAN | IX02_TEST | 5999 | 53991 | 1857 (1)| 00:00:23 |
----------------------------------------------------------------------------------------------

やたーーーーーーーーーーーーっ! :) 目標の3秒を下回りましたよー :)

コストベースオプティマイザの悩みを解消してあげることができました…が、例のSHARABLE_MEMが3MB超えちゃってる問題はまだ抱えたままです。><

SQL_ID        SHARABLE_MEM PERSISTENT_MEM RUNTIME_MEM SQL_TEXT
------------- ------------ -------------- ----------- ------------------------------
fbjw4wjdma4f7 3318142 396808 395664 SELECT /*+ LEADING(T1 T2 T3
) USE_HASH(T1 T2) USE_HASH
(T1 T3) INDEX(T1 IX01_TEST)
INDEX(T3 IX01_TEST) */ T1.
surro_id, T1.name, T1.modifi
ed FROM test T1 join ( SELE
CT /*+ MERGE INDEX(
test IX02_TEST) */ DISTI
NCT surro_id, surro_bcd

今回はここまで、次回へつづく。


ここまでのあらずじ

悩ませ過ぎは及ばざるがごとし #1
悩ませ過ぎは及ばざるがごとし #2
悩ませ過ぎは及ばざるがごとし #3
悩ませ過ぎは及ばざるがごとし #4

| | コメント (0) | トラックバック (0)

2011年9月 4日 (日)

悩ませ過ぎは及ばざるがごとし #4

さて、さて、前回のつづきです。

意識的に間を取ったんですが、ちょいと長過ぎたかw


前回、ハードパースに時間がかかってるねーってとこまで確認しましたよね〜

20110824_23733


・1回目のSQLトレース

call     count       cpu    elapsed       disk      query    current        rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 45.18 45.15 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 401 0.04 0.05 0 1897 0 5999
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 403 45.23 45.21 0 1897 0 5999


・2回目のSQLトレース

call     count       cpu    elapsed       disk      query    current        rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 401 0.04 0.04 0 1897 0 5999
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 403 0.04 0.04 0 1897 0 5999


ということでした。

じゃ、こんなにコストペースオプティマイザに考えさせちゃうSQL文でどんなのよー。と。 OLTPなのに分析系のすげー難しそーなSQL文なげてるとか??? 想像しているより現物見た方が早いですw

こんな感じのクエリだんたんよー。

SELECT
T1.surro_id,
T1.name,
T1.modified
FROM
test T1 JOIN (
SELECT DISTINCT
surro_id,
surro_bcd
FROM
test
) T2
ON
T1.surro_id = T2.surro_id AND
T1.surro_bcd = T2.surro_bcd
JOIN test T3
ON
T1.surro_id = T3.surro_id AND
T1.surro_acd= T3.surro_acd
WHERE
T1.surro_id IN (リテラル,....限界まで)
OR T1.surro_id IN (リテラル,....限界まで

.....以下....すきなだけ繰り返しw

/


え、え〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜っ、リテラル値が〜〜〜〜すげ〜〜〜〜〜〜〜ぞ〜〜〜〜〜〜。
クエリ自体はたいしたことないw あの人達がすきそーな自己結合だー。(失礼w)

このクエリを見て、解決策2つをすぐに思いついたあたなあなた!、 そう、あなた、凄いです!
INリストには上限あるからね:)- Oracle® Database SQL言語リファレンス11gリリース2(11.2)式のリスト

このクエリの解決策。

解決案1
一番効果のありそうなの、リテラルを排除して、その部分を副問合せにしちゃう!。

解決案2
コストベースオプティマイザを悩ませない方法って、ありますよね、そう、ヒントを使って、「こんな感じにうごいて!」作戦。

このクエリの一番の問題点は、リテラル値が山ほどあって、似たような索引が沢山あって、しかも、リテラル値だから毎回値が異なる。結果として毎回ハードパースになるので、毎回コストベースオプティマイザが考え過ぎちゃうこと。

解決策は前述の2案のうちいずれか一つなんだけど、おすすめは案1のほう。

その訳は、でかいんです、なにが?

以下を見れば、なに? が でかいかよーくわかりますw

23:49:06 SYS> SELECT SQL_ID,SHARABLE_MEM,PERSISTENT_MEM,RUNTIME_MEM,SQL_TEXT FROM v$sql WHERE SQL_TEXT LIKE '%/*TEST*/%';

SQL_ID SHARABLE_MEM PERSISTENT_MEM RUNTIME_MEM SQL_TEXT
------------- ------------ -------------- ----------- ------------------------------
82q8wxz56y357 3317991 396816 395672 SELECT /*TEST*/ T1.surro_id,
T1.name, T1.modified FROM t
est T1 join ( SELECT DISTIN
CT surro_id, surro_bcd
FROM test ) T2 ON T1.s
urro_id = T2.surro_id AND T
1.surro_bcd = T2.surro_bcd
JOIN test T3 ON

ね、でかいでしょ。SHARABLE_MEMなんて3MBいっちゃってるし、この程度のことするにしてはデカ過ぎw
これって、直ちには影響はないのですが…(どっかで聞いた事ある言い回し><  やはり同じ事するセッション多いとさーボディーブローよ。全部ハードパースだしw


今回はここまで、次回へつづく。


ここまでのあらずじ

悩ませ過ぎは及ばざるがごとし #1
悩ませ過ぎは及ばざるがごとし #2
悩ませ過ぎは及ばざるがごとし #3

| | コメント (0) | トラックバック (0)

2011年8月25日 (木)

悩ませ過ぎは及ばざるがごとし #3

前回の続きだす。(まだGANTZ語が抜けてないw)


前回は状況証拠固めでした。

で、以下のような状況証拠は確認済み。

  • 1回目だけ処理時間が異常に長い。
  • 実行統計(consistent getsなど)から実行時のアクセスブロック数の差異はない。かつ、ブロック数も少ない。
  • 物理読み込みは処理時間には影響していない。

という状況証拠を踏まえ、SQL文の処理フェーズを頭に浮かべて、順序よく考えていくと……

consitents getsの量や処理時間からexecutionフェーズ以降で時間を要しているわけではない……
また、
1回目だけ処理時間が長いが、物理読み込みが影響しているわけではない…

20110824_23033


ということは、1回目だけ実行されるといえばハードパース……この部分の処理時間が長いってことですよね!

20110824_23733

だんだん近づいてきましたね。というこで、次はパース時間が長いという証拠固めを。

パース時間を比較する方法はいくつかあります…。 SQL*Plusのset autot trace exp を使って実行計画だけを確認する方法とか、Explain plan文使うとか、SQLトレースを取るとか。
ようするに、パース時間が確認できる方法であればどんな方法でもOKなんです。


今回は結果の比較もしやすい、SQLトレースで証拠固をしてみます。SQLトレースを取得する方法はdbms_monitorパッケージを利用する方法が簡単ですかね。(他にもありますが)

SCOTT> exec dbms_monitor.session_trace_enable(null,null,true,false,'ALL_EXECUTIONS');

PL/SQLプロシージャが正常に完了しました。

SCOTT> SELECT

・・・中略・・・

5999行が選択されました。

経過: 00:00:48.37

SCOTT> exec dbms_monitor.session_trace_disable(null,null);

PL/SQLプロシージャが正常に完了しました。

こんな感じでセッション単位でSQLトレースを取得してtkprofで整形するというおなじみのスタイル。


・1回目のSQLトレース

call     count       cpu    elapsed       disk      query    current        rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 45.18 45.15 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 401 0.04 0.05 0 1897 0 5999
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 403 45.23 45.21 0 1897 0 5999


・2回目のSQLトレース

call     count       cpu    elapsed       disk      query    current        rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 401 0.04 0.04 0 1897 0 5999
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 403 0.04 0.04 0 1897 0 5999


予想的中!。 パースに時間を要しているのは明らかですね。

最近のコストベースオプティマイザは賢いです。賢いのでいろいろと考えさせすぎると時間がかかります。(将棋でも相手の手数を読み過ぎなんて…ことありますよね。そんな状況に近いです。)。DWH系のクエリならそんなこともあるでしょうけど、今回問題になっているのはOLTPです、しかも、3秒程度で結果を返してほしいらしいし…

で、どのようにしたらコストベースオプティマイザを"悩ませずに”済むか、そこが今回のポイント。

思い切って、ルールベースにしちゃおーか?。それはNG。確かにパース時間は短くなるでしょうけど…


解決方法を見つけるには問題のクエリがどんなものか見極める必要がありそうですね〜…。どんな方法があるだろー。


今日はここまで、次回へつづく。


ここまでのあらずじ

悩ませ過ぎは及ばざるがごとし #1
悩ませ過ぎは及ばざるがごとし #2

| | コメント (0) | トラックバック (0)

2011年8月24日 (水)

悩ませ過ぎは及ばざるがごとし #2

「一緒に考えてみてくらちい」タイポじゃないだすw GANTZ見てたんでつい。:)

ということで前回のつづきです。

1回目だけ異常に処理時間を要するクエリがあると相談を受けたという前振り覚えてますか?

実行計画
----------------------------------------------------------
Plan hash value: 1865103575

--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5999 | 351K| 5718 (1)| 00:01:09 |
|* 1 | HASH JOIN | | 5999 | 351K| 5718 (1)| 00:01:09 |
| 2 | INLIST ITERATOR | | | | | |
|* 3 | INDEX RANGE SCAN | IX01_TEST | 5999 | 59990 | 1935 (1)| 00:00:24 |
|* 4 | HASH JOIN | | 5999 | 292K| 3782 (1)| 00:00:46 |
| 5 | VIEW | | 5999 | 95984 | 1858 (1)| 00:00:23 |
| 6 | HASH UNIQUE | | 5999 | 53991 | 1858 (1)| 00:00:23 |
| 7 | INLIST ITERATOR | | | | | |
|* 8 | INDEX RANGE SCAN | IX02_TEST | 5999 | 53991 | 1857 (1)| 00:00:23 |
| 9 | INLIST ITERATOR | | | | | |
| 10 | TABLE ACCESS BY INDEX ROWID| TEST | 5999 | 199K| 1923 (1)| 00:00:24 |
|* 11 | INDEX RANGE SCAN | IX02_TEST | 5999 | | 1857 (1)| 00:00:23 |
--------------------------------------------------------------------------------------------

・・・中略・・・

統計
----------------------------------------------------------
1 recursive calls
0 db block gets
1897 consistent gets
0 physical reads
0 redo size
247808 bytes sent via SQL*Net to client
69769 bytes received via SQL*Net from client
401 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
5999 rows processed


1回目とそれ以降で実行計画の差異はありません。実行統計上はrecursive callが1から0になっている程度の変化しかありません。

ですが……………………

1回目は、48.83秒なのに、2回目以降は、0.08秒…

1回目の処理時間 (SQL*Plusのset timiing on 及び、set autot trace exp statにて計測)


5999行が選択されました。

経過: 00:00:48.83

2回目以降〜


5999行が選択されました。

経過: 00:00:00.08

実行統計を見ると、consistent gets 1897もそれほど多くないのに1回目だけ処理時間が長い、その差はどこに……


SQL文がどのような順序で処理されるのか、よーーーーーく思い出してください;)

リンク先にあるオラクルのマニュアルの図をざっくりまとめちゃうと以下のような感じ(BINDや、FETCHフェーズが書かれている図もよく見かけますね)


20110823_142232



となっています。


この辺りも一緒に読むといいですよね。わかりやすいです。無料だし:)
門外不出のOracle現場ワザ - 第4章 Oracleデータベースの頭脳 「オプティマイザ」徹底研究
SQL文の処理におけるオプティマイザの役割
Part2 CBOは何を見てどう判断するのか

これまでに確認できた状況証拠

  • 1回目だけ処理時間が異常に長い。
  • 実行統計(consistent getsなど)から実行時のアクセスブロック数の差異はない。かつ、ブロック数も少ない。
  • 物理読み込みは処理時間には影響していない。

これらの状況証拠とSQL文の処理フェーズから導きだせますよね。どこに処理時間を要しているか…………

ほーら、ほら。見えてきました…………………よね? (ヒントだしてますから〜〜:)


ということで、今日はここまで、次回へつづく。




ここまでのあらずじ

悩ませ過ぎは及ばざるがごとし #1

| | コメント (0) | トラックバック (0)

2011年8月23日 (火)

悩ませ過ぎは及ばざるがごとし #1

あるクエリを実行していて、目標時間は3秒程度のオンライン処理向けクエリ、初回だけ異常に遅いんですけど……。 と再び、大人の事情に縛られて心が痣だらけ(どんなだ)な人達からお呼びがかかりました。

こんな感じの表(索引は似たようなのが数多くありそれもイケてないといえばイケテてないが)を自己結合しているだけ(イケてるクエリとか、イケてないクエリだというのは置いといて)で実行計画もそんなに悪くないし、実行統計を見る限り
初回とそれ以降で大きく乖離しているようにも見えません。

表は次のように定義されています。

SCOTT> desc test
名前 NULL? 型
----------------------------------------- -------- ----------------------------
ID NOT NULL NUMBER(10)
SURRO_ID NOT NULL NUMBER(10)
SURRO_ACD NOT NULL CHAR(2)
SURRO_BCD NOT NULL CHAR(1)
SURRO_CCD NOT NULL CHAR(3)
SURRO_DCD NOT NULL CHAR(5)
NAME NOT NULL VARCHAR2(100)
DESCRIPTION VARCHAR2(300)
CREATED NOT NULL TIMESTAMP(6)
MODIFIED NOT NULL TIMESTAMP(6)

索引は以下のようになってます。

INDEX_NAME                     COLUMN_NAME
------------------------------ ------------------------------
IX01_TEST SURRO_ID
SURRO_ACD

IX02_TEST SURRO_ID
SURRO_BCD

IX03_TEST SURRO_ID
SURRO_CCD

IX04_TEST SURRO_ID
SURRO_DCD

PK_TEST ID

なんだか、どれも似たような索引がならんでいます。

INDEX_NAME                     INDEX_TYPE                    NUM_ROWS DISTINCT_KEYS CLUSTERING_FACTOR
------------------------------ --------------------------- ---------- ------------- -----------------
IX04_TEST NORMAL 700000 700000 7653
IX03_TEST NORMAL 700000 700000 7653
IX02_TEST NORMAL 700000 700000 7653
IX01_TEST NORMAL 700000 700000 7653
PK_TEST NORMAL 700000 700000 7653





どーーーーーーーしてでしょう。

このつづきは次回のお楽しみ。

一緒に考えてみてくらちい ;)


1回目の処理行数、処理時間、実行計画及び実行統計。


・・・中略・・・

5999行が選択されました。

経過: 00:00:48.83

実行計画
----------------------------------------------------------
Plan hash value: 1865103575

--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5999 | 351K| 5718 (1)| 00:01:09 |
|* 1 | HASH JOIN | | 5999 | 351K| 5718 (1)| 00:01:09 |
| 2 | INLIST ITERATOR | | | | | |
|* 3 | INDEX RANGE SCAN | IX01_TEST | 5999 | 59990 | 1935 (1)| 00:00:24 |
|* 4 | HASH JOIN | | 5999 | 292K| 3782 (1)| 00:00:46 |
| 5 | VIEW | | 5999 | 95984 | 1858 (1)| 00:00:23 |
| 6 | HASH UNIQUE | | 5999 | 53991 | 1858 (1)| 00:00:23 |
| 7 | INLIST ITERATOR | | | | | |
|* 8 | INDEX RANGE SCAN | IX02_TEST | 5999 | 53991 | 1857 (1)| 00:00:23 |
| 9 | INLIST ITERATOR | | | | | |
| 10 | TABLE ACCESS BY INDEX ROWID| TEST | 5999 | 199K| 1923 (1)| 00:00:24 |
|* 11 | INDEX RANGE SCAN | IX02_TEST | 5999 | | 1857 (1)| 00:00:23 |
--------------------------------------------------------------------------------------------

・・・中略・・・

統計
----------------------------------------------------------
1 recursive calls
0 db block gets
1897 consistent gets
0 physical reads
0 redo size
247808 bytes sent via SQL*Net to client
69769 bytes received via SQL*Net from client
401 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
5999 rows processed



2回目の処理行数、処理時間、実行計画及び実行統計。

1回目とくらべて随分処理時間が短いです。。。。

・・・中略・・・

5999行が選択されました。

経過: 00:00:00.08

実行計画
----------------------------------------------------------
Plan hash value: 1865103575

--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5999 | 351K| 5718 (1)| 00:01:09 |
|* 1 | HASH JOIN | | 5999 | 351K| 5718 (1)| 00:01:09 |
| 2 | INLIST ITERATOR | | | | | |
|* 3 | INDEX RANGE SCAN | IX01_TEST | 5999 | 59990 | 1935 (1)| 00:00:24 |
|* 4 | HASH JOIN | | 5999 | 292K| 3782 (1)| 00:00:46 |
| 5 | VIEW | | 5999 | 95984 | 1858 (1)| 00:00:23 |
| 6 | HASH UNIQUE | | 5999 | 53991 | 1858 (1)| 00:00:23 |
| 7 | INLIST ITERATOR | | | | | |
|* 8 | INDEX RANGE SCAN | IX02_TEST | 5999 | 53991 | 1857 (1)| 00:00:23 |
| 9 | INLIST ITERATOR | | | | | |
| 10 | TABLE ACCESS BY INDEX ROWID| TEST | 5999 | 199K| 1923 (1)| 00:00:24 |
|* 11 | INDEX RANGE SCAN | IX02_TEST | 5999 | | 1857 (1)| 00:00:23 |
--------------------------------------------------------------------------------------------

・・・中略・・・

統計
----------------------------------------------------------
0 recursive calls
0 db block gets
1897 consistent gets
0 physical reads
0 redo size
247808 bytes sent via SQL*Net to client
69766 bytes received via SQL*Net from client
401 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
5999 rows processed


3回目の処理行数、処理時間、実行計画及び実行統計。

3回目も2回目と同じようです。1回目だけなぜか異常に遅い。ちなみに、Oracle11g R2 11.2.0.1.0 for Linux x86_64です。


・・・中略・・・

5999行が選択されました。

経過: 00:00:00.08

実行計画
----------------------------------------------------------
Plan hash value: 1865103575

--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5999 | 351K| 5718 (1)| 00:01:09 |
|* 1 | HASH JOIN | | 5999 | 351K| 5718 (1)| 00:01:09 |
| 2 | INLIST ITERATOR | | | | | |
|* 3 | INDEX RANGE SCAN | IX01_TEST | 5999 | 59990 | 1935 (1)| 00:00:24 |
|* 4 | HASH JOIN | | 5999 | 292K| 3782 (1)| 00:00:46 |
| 5 | VIEW | | 5999 | 95984 | 1858 (1)| 00:00:23 |
| 6 | HASH UNIQUE | | 5999 | 53991 | 1858 (1)| 00:00:23 |
| 7 | INLIST ITERATOR | | | | | |
|* 8 | INDEX RANGE SCAN | IX02_TEST | 5999 | 53991 | 1857 (1)| 00:00:23 |
| 9 | INLIST ITERATOR | | | | | |
| 10 | TABLE ACCESS BY INDEX ROWID| TEST | 5999 | 199K| 1923 (1)| 00:00:24 |
|* 11 | INDEX RANGE SCAN | IX02_TEST | 5999 | | 1857 (1)| 00:00:23 |
--------------------------------------------------------------------------------------------

・・・中略・・・


統計
----------------------------------------------------------
0 recursive calls
0 db block gets
1897 consistent gets
0 physical reads
0 redo size
247808 bytes sent via SQL*Net to client
69766 bytes received via SQL*Net from client
401 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
5999 rows processed

| | コメント (0) | トラックバック (0)

2011年8月11日 (木)

いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング番外編 

おまけのおまけのおまけとは、さすがに書きづらかったのでw 番外編。

いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング8 おまけのおまけで次のように書いていたのを覚えてますか?

"アクセスするブロック数を減らすのはハッシュパーティションのままではもう、むーりーw 限界です。"

なぜ、限界としたか。という点、聞きたくないですか?

聞きたいですよね。:)

理由は次のクエリ(GROUP BYとCUBEでチューニングしたクエリの一番大切部分)と処理時間、実行計画、consistent getsを見ていただければお分かりいただけるかと……  


そーーーなんです。 以下のブロック数と処理時間って、前回、GROUP BY と CUBEだけでチューニングした結果とそっくりですよね。


  1   SELECT
2 SUBSTR(starting_date,1,6) AS month
3 ,shop_code
4 ,SUM(sales_figure) AS sales_figure
5 FROM
6 test2
7 WHERE
8 starting_date BETWEEN '20110101' AND '20110331'
9 GROUP BY
10 SUBSTR(starting_date,1,6)
11* ,shop_code

3900行が選択されました。

経過: 00:00:06.89

実行計画
----------------------------------------------------------
Plan hash value: 2608398149

---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 8274 | 137K| 82839 (2)| 00:16:35 | | |
| 1 | HASH GROUP BY | | 8274 | 137K| 82839 (2)| 00:16:35 | | |
| 2 | PARTITION HASH ALL| | 1703K| 27M| 82788 (2)| 00:16:34 | 1 | 4 |
|* 3 | TABLE ACCESS FULL| TEST2 | 1703K| 27M| 82788 (2)| 00:16:34 | 1 | 4 |
---------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

3 - filter("STARTING_DATE"<='20110331' AND "STARTING_DATE">='20110101')


統計
----------------------------------------------------------
0 recursive calls
0 db block gets
302341 consistent gets
302289 physical reads
0 redo size
87392 bytes sent via SQL*Net to client
3369 bytes received via SQL*Net from client
261 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
3900 rows processed

と、いうことで限界! と判断したわけなんです。 どうですか? スッキリしましたか? :) では、また。


これまでのあらずじ…

いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #1
いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #2
いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #3
いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #4
いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #5
いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #6
いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #7 おまけ
いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング8 おまけのおまけ

| | コメント (0) | トラックバック (0)

2011年8月 6日 (土)

いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング8 おまけのおまけ

前回のつづきです。

GROUPING SETSを単純に使っただけでは可読性は向上するが内部で自動的に行われる一時表への展開(WITH句で書くのに似ている)とUNION ALLによる集計時オーバーヘッドが大きくなるようで、WITH句+UNION ALLに書き換えた場合ほど効果はありませんでした。残念。

だったら〜。

ということで、GROUPING SETSは使わず、やってる事がやってる事だから、素直にCUBEを使ってクロス集計しちゃえばオーバーヘッドとなっているWITH句+UNION ALLへの展開も行わないようにすればなって良いんジャマイカ! そうしよう!


で、パーティションは大人の事情でハッシュのままに、WITH句+UNION ALLへの書き換えや、GROUPING SETSで自動的にWITH句+UNION ALLへ展開する方法を止めたのが以下のクエリ。

え〜〜〜〜〜、え〜〜〜〜〜〜。シリアル実行としては最速の結果、6秒台キタ〜〜〜〜!。
可読性は副問合せなどの影響でちょいと落ちますがSQL文は短いのでそれほど影響はないですよね。いままで一番短いのではないでしょうか:)

  1  SELECT
2 CASE
3 WHEN grouping_id(month) = 1 THEN
4 CASE
5 WHEN SUBSTR(MIN(month),5,2)||SUBSTR(MAX(month),5,2) = '0406' THEN 'Q1'
6 WHEN SUBSTR(MIN(month),5,2)||SUBSTR(MAX(month),5,2) = '0709' THEN 'Q2'
7 WHEN SUBSTR(MIN(month),5,2)||SUBSTR(MAX(month),5,2) = '1012' THEN 'Q3'
8 WHEN SUBSTR(MIN(month),5,2)||SUBSTR(MAX(month),5,2) = '0103' THEN 'Q4'
9 END
10 ELSE month
11 END AS month
12 ,CASE
13 WHEN grouping_id(shop_code) = 1 THEN 'ALL'
14 ELSE shop_code
15 END AS shop_code
16 ,SUM(sales_figure) AS sales_figure
17 FROM
18 (
19 SELECT
20 SUBSTR(starting_date,1,6) AS month
21 ,shop_code
22 ,SUM(sales_figure) AS sales_figure
23 FROM
24 test2
25 WHERE
26 starting_date BETWEEN '20110101' AND '20110331'
27 GROUP BY
28 SUBSTR(starting_date,1,6)
29 ,shop_code
30 )
31 GROUP BY
32 CUBE(month,shop_code)
33 HAVING
34 shop_code = '1000'
35 OR grouping_id(shop_code) = 1
36 ORDER BY
37 month
38* ,shop_code

8行が選択されました。

経過: 00:00:06.86

実行計画
----------------------------------------------------------
Plan hash value: 994924564

---------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
---------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1381 | 34525 | 83173 (2)| 00:16:39 | | |
| 1 | SORT ORDER BY | | 1381 | 34525 | 83173 (2)| 00:16:39 | | |
|* 2 | FILTER | | | | | | | |
| 3 | SORT GROUP BY | | 1381 | 34525 | 83173 (2)| 00:16:39 | | |
| 4 | GENERATE CUBE | | 1381 | 34525 | 83173 (2)| 00:16:39 | | |
| 5 | SORT GROUP BY | | 1381 | 34525 | 83173 (2)| 00:16:39 | | |
| 6 | VIEW | | 2758 | 68950 | 83172 (2)| 00:16:39 | | |
| 7 | HASH GROUP BY | | 2758 | 66192 | 83172 (2)| 00:16:39 | | |
| 8 | PARTITION HASH ALL | | 394K| 9242K| 83161 (2)| 00:16:38 | 1 | 4 |
|* 9 | TABLE ACCESS FULL | TEST2 | 394K| 9242K| 83161 (2)| 00:16:38 | 1 | 4 |
---------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - filter("SHOP_CODE"='1000' OR GROUPING_ID(BIN_TO_NUM(SYS_OP_GROUPING("SHOP_CODE",1,0,
SYS_OP_BITVEC)))=1)
9 - filter("STARTING_DATE"<='20110331' AND SUBSTR("STARTING_DATE",1,6)<='201103' AND
SUBSTR("STARTING_DATE",1,6)>='201101' AND "STARTING_DATE">='20110101')


統計
----------------------------------------------------------
0 recursive calls
0 db block gets
302587 consistent gets
302556 physical reads
0 redo size
871 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
3 sorts (memory)
0 sorts (disk)
8 rows processed

お約束、オラクルお任せのパラレル実験。 

お〜〜〜〜〜〜〜〜〜〜〜〜っ。キター、1.2秒台〜〜〜〜〜。 パーティションタイプのミスという痛恨の設計ミスを帳消にしてあげたかも。(それは嘘。
そもそも、アクセスするブロック数を減らすのはハッシュパーティションのままではもう、むーりーw 限界です。

  1  SELECT /*+ PARALLEL */
2 CASE
3 WHEN grouping_id(month) = 1 THEN
4 CASE
5 WHEN SUBSTR(MIN(month),5,2)||SUBSTR(MAX(month),5,2) = '0406' THEN 'Q1'
6 WHEN SUBSTR(MIN(month),5,2)||SUBSTR(MAX(month),5,2) = '0709' THEN 'Q2'
7 WHEN SUBSTR(MIN(month),5,2)||SUBSTR(MAX(month),5,2) = '1012' THEN 'Q3'
8 WHEN SUBSTR(MIN(month),5,2)||SUBSTR(MAX(month),5,2) = '0103' THEN 'Q4'
9 END
10 ELSE month
11 END AS month
12 ,CASE
13 WHEN grouping_id(shop_code) = 1 THEN 'ALL'
14 ELSE shop_code
15 END AS shop_code
16 ,SUM(sales_figure) AS sales_figure
17 FROM
18 (
19 SELECT
20 SUBSTR(starting_date,1,6) AS month
21 ,shop_code
22 ,SUM(sales_figure) AS sales_figure
23 FROM
24 test2
25 WHERE
26 starting_date BETWEEN '20110101' AND '20110331'
27 GROUP BY
28 SUBSTR(starting_date,1,6)
29 ,shop_code
30 )
31 GROUP BY
32 CUBE(month,shop_code)
33 HAVING
34 shop_code = '1000'
35 OR grouping_id(shop_code) = 1
36 ORDER BY
37 month
38* ,shop_code

8行が選択されました。

経過: 00:00:01.24

実行計画
----------------------------------------------------------
Plan hash value: 3457173925

-----------------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | TQ |IN-OUT| PQ Distrib |
-----------------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1381 | 34525 | 5773 (2)| 00:01:10 | | | | | |
| 1 | PX COORDINATOR | | | | | | | | | | |
| 2 | PX SEND QC (ORDER) | :TQ10004 | 1381 | 34525 | 5773 (2)| 00:01:10 | | | Q1,04 | P->S | QC (ORDER) |
| 3 | SORT ORDER BY | | 1381 | 34525 | 5773 (2)| 00:01:10 | | | Q1,04 | PCWP | |
| 4 | PX RECEIVE | | 1381 | 34525 | 5773 (2)| 00:01:10 | | | Q1,04 | PCWP | |
| 5 | PX SEND RANGE | :TQ10003 | 1381 | 34525 | 5773 (2)| 00:01:10 | | | Q1,03 | P->P | RANGE |
|* 6 | FILTER | | | | | | | | Q1,03 | PCWC | |
| 7 | SORT GROUP BY | | 1381 | 34525 | 5773 (2)| 00:01:10 | | | Q1,03 | PCWP | |
| 8 | PX RECEIVE | | 1381 | 34525 | 5773 (2)| 00:01:10 | | | Q1,03 | PCWP | |
| 9 | PX SEND HASH | :TQ10002 | 1381 | 34525 | 5773 (2)| 00:01:10 | | | Q1,02 | P->P | HASH |
| 10 | GENERATE CUBE | | 1381 | 34525 | 5773 (2)| 00:01:10 | | | Q1,02 | PCWC | |
| 11 | SORT GROUP BY | | 1381 | 34525 | 5773 (2)| 00:01:10 | | | Q1,02 | PCWP | |
| 12 | PX RECEIVE | | 1381 | 34525 | 5773 (2)| 00:01:10 | | | Q1,02 | PCWP | |
| 13 | PX SEND HASH | :TQ10001 | 1381 | 34525 | 5773 (2)| 00:01:10 | | | Q1,01 | P->P | HASH |
| 14 | SORT GROUP BY | | 1381 | 34525 | 5773 (2)| 00:01:10 | | | Q1,01 | PCWP | |
| 15 | VIEW | | 2758 | 68950 | 5772 (2)| 00:01:10 | | | Q1,01 | PCWP | |
| 16 | HASH GROUP BY | | 2758 | 66192 | 5772 (2)| 00:01:10 | | | Q1,01 | PCWP | |
| 17 | PX RECEIVE | | 2758 | 66192 | 5772 (2)| 00:01:10 | | | Q1,01 | PCWP | |
| 18 | PX SEND HASH | :TQ10000 | 2758 | 66192 | 5772 (2)| 00:01:10 | | | Q1,00 | P->P | HASH |
| 19 | HASH GROUP BY | | 2758 | 66192 | 5772 (2)| 00:01:10 | | | Q1,00 | PCWP | |
| 20 | PX BLOCK ITERATOR | | 394K| 9242K| 5770 (2)| 00:01:10 | 1 | 4 | Q1,00 | PCWC | |
|* 21 | TABLE ACCESS FULL | TEST2 | 394K| 9242K| 5770 (2)| 00:01:10 | 1 | 4 | Q1,00 | PCWP | |
-----------------------------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

6 - filter("SHOP_CODE"='1000' OR GROUPING_ID(BIN_TO_NUM(SYS_OP_GROUPING("SHOP_CODE",1,0,SYS_OP_BITVEC)))=1)
21 - filter("STARTING_DATE"<='20110331' AND SUBSTR("STARTING_DATE",1,6)<='201103' AND SUBSTR("STARTING_DATE",1,6)>='201101' AND
"STARTING_DATE">='20110101')

Note
-----
- automatic DOP: Computed Degree of Parallelism is 16


統計
----------------------------------------------------------
96 recursive calls
0 db block gets
304109 consistent gets
302556 physical reads
0 redo size
871 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
65 sorts (memory)
0 sorts (disk)
8 rows processed


今一度、最初のイケてないクエリと比較。あ〜、ダメダメだ〜。やっぱり無駄が多すぎですね!

  1  SELECT
2 month
3 ,shop_code
4 ,sales_figure
5 FROM
6 (
7 SELECT
8 SUBSTR(starting_date,1,6) AS month
9 ,shop_code
10 ,SUM(sales_figure) AS sales_figure
11 FROM
12 test2
13 WHERE
14 starting_date BETWEEN '20110101' AND '20110331'
15 AND shop_code = '1000'
16 GROUP BY
17 SUBSTR(starting_date,1,6)
18 ,shop_code
19 UNION ALL
20 SELECT
21 CASE
22 WHEN SUBSTR(starting_date,5,2) BETWEEN '04' AND '06' THEN 'Q1'
23 WHEN SUBSTR(starting_date,5,2) BETWEEN '07' AND '09' THEN 'Q2'
24 WHEN SUBSTR(starting_date,5,2) BETWEEN '10' AND '12' THEN 'Q3'
25 WHEN SUBSTR(starting_date,5,2) BETWEEN '01' AND '03' THEN 'Q4'
26 END AS month
27 ,shop_code
28 ,SUM(sales_figure) AS salles_figure
29 FROM
30 test2
31 WHERE
32 starting_date BETWEEN '20110101' AND '20110331'
33 AND shop_code = '1000'
34 GROUP BY
35 CASE
36 WHEN SUBSTR(starting_date,5,2) BETWEEN '04' AND '06' THEN 'Q1'
37 WHEN SUBSTR(starting_date,5,2) BETWEEN '07' AND '09' THEN 'Q2'
38 WHEN SUBSTR(starting_date,5,2) BETWEEN '10' AND '12' THEN 'Q3'
39 WHEN SUBSTR(starting_date,5,2) BETWEEN '01' AND '03' THEN 'Q4'
40 END
41 ,shop_code
42 UNION ALL
43 SELECT
44 SUBSTR(starting_date,1,6) AS month
45 ,'ALL ' AS shop_code
46 ,SUM(sales_figure) AS sales_figure
47 FROM
48 test2
49 WHERE
50 starting_date BETWEEN '20110101' AND '20110331'
51 GROUP BY
52 SUBSTR(starting_date,1,6)
53 UNION ALL
54 SELECT
55 CASE
56 WHEN SUBSTR(starting_date,5,2) BETWEEN '04' AND '06' THEN 'Q1'
57 WHEN SUBSTR(starting_date,5,2) BETWEEN '07' AND '09' THEN 'Q2'
58 WHEN SUBSTR(starting_date,5,2) BETWEEN '10' AND '12' THEN 'Q3'
59 WHEN SUBSTR(starting_date,5,2) BETWEEN '01' AND '03' THEN 'Q4'
60 END AS month
61 ,'ALL ' AS shop_code
62 ,SUM(sales_figure) AS salles_figure
63 FROM
64 test2
65 WHERE
66 starting_date BETWEEN '20110101' AND '20110331'
67 GROUP BY
68 CASE
69 WHEN SUBSTR(starting_date,5,2) BETWEEN '04' AND '06' THEN 'Q1'
70 WHEN SUBSTR(starting_date,5,2) BETWEEN '07' AND '09' THEN 'Q2'
71 WHEN SUBSTR(starting_date,5,2) BETWEEN '10' AND '12' THEN 'Q3'
72 WHEN SUBSTR(starting_date,5,2) BETWEEN '01' AND '03' THEN 'Q4'
73 END
74 )
75 ORDER BY
76 month
77* ,shop_code

8行が選択されました。

経過: 00:00:20.92

実行計画
----------------------------------------------------------
Plan hash value: 1898009794

-------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |Pstart| Pstop|
-------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 22 | 726 | 166K (2)| 00:33:18 | | |
| 1 | SORT ORDER BY | | 22 | 726 | 166K (2)| 00:33:18 | | |
| 2 | VIEW | | 22 | 726 | 166K (2)| 00:33:18 | | |
| 3 | UNION-ALL | | | | | | | |
| 4 | HASH GROUP BY | | 3 | 72 | 43 (3)| 00:00:01 | | |
| 5 | PARTITION HASH ALL | | 303 | 7272 | 42 (0)| 00:00:01 | 1 | 4 |
| 6 | TABLE ACCESS BY LOCAL INDEX ROWID| TEST2 | 303 | 7272 | 42 (0)| 00:00:01 | 1 | 4 |
|* 7 | INDEX RANGE SCAN | PK_TEST2 | 303 | | 19 (0)| 00:00:01 | 1 | 4 |
| 8 | HASH GROUP BY | | 7 | 119 | 43 (3)| 00:00:01 | | |
| 9 | PARTITION HASH ALL | | 303 | 5151 | 42 (0)| 00:00:01 | 1 | 4 |
| 10 | TABLE ACCESS BY LOCAL INDEX ROWID| TEST2 | 303 | 5151 | 42 (0)| 00:00:01 | 1 | 4 |
|* 11 | INDEX RANGE SCAN | PK_TEST2 | 303 | | 19 (0)| 00:00:01 | 1 | 4 |
| 12 | HASH GROUP BY | | 3 | 57 | 83172 (2)| 00:16:39 | | |
| 13 | PARTITION HASH ALL | | 394K| 7316K| 83161 (2)| 00:16:38 | 1 | 4 |
|* 14 | TABLE ACCESS FULL | TEST2 | 394K| 7316K| 83161 (2)| 00:16:38 | 1 | 4 |
| 15 | HASH GROUP BY | | 9 | 108 | 83172 (2)| 00:16:39 | | |
| 16 | PARTITION HASH ALL | | 394K| 4621K| 83161 (2)| 00:16:38 | 1 | 4 |
|* 17 | TABLE ACCESS FULL | TEST2 | 394K| 4621K| 83161 (2)| 00:16:38 | 1 | 4 |
-------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

7 - access("SHOP_CODE"='1000' AND "STARTING_DATE">='20110101' AND "STARTING_DATE"<='20110331')
filter(SUBSTR("STARTING_DATE",1,6)<='201103' AND SUBSTR("STARTING_DATE",1,6)>='201101')
11 - access("SHOP_CODE"='1000' AND "STARTING_DATE">='20110101' AND "STARTING_DATE"<='20110331')
filter(SUBSTR("STARTING_DATE",1,6)<='201103' AND SUBSTR("STARTING_DATE",1,6)>='201101')
14 - filter("STARTING_DATE"<='20110331' AND SUBSTR("STARTING_DATE",1,6)<='201103' AND
SUBSTR("STARTING_DATE",1,6)>='201101' AND "STARTING_DATE">='20110101')
17 - filter("STARTING_DATE"<='20110331' AND SUBSTR("STARTING_DATE",1,6)<='201103' AND
SUBSTR("STARTING_DATE",1,6)>='201101' AND "STARTING_DATE">='20110101')


統計
----------------------------------------------------------
0 recursive calls
0 db block gets
606978 consistent gets
605112 physical reads
0 redo size
875 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
8 rows processed

前回の結果なのでここには載せませんが、GROUPSING SETSで書き換えた場合や、WITH句+UNION ALLで書き換えた場合でも一時表への書き込み及び一時表からの読み込みは複数回発生し、それがボディーブローのように効いていたんよね。:)

これもお約束、そもそもパーティションタイプが月単位のレンジパーティションだったら〜(タラレバw)どんな結果になるか。

キター、シリアル実行でも4秒台、4秒切りそうな勢いです:)
月単位のレンジパーティションにより無駄なブロックを読み込む必要がなくなったことが効いてますね。

  1  SELECT
2 CASE
3 WHEN grouping_id(month) = 1 THEN
4 CASE
5 WHEN SUBSTR(MIN(month),5,2)||SUBSTR(MAX(month),5,2) = '0406' THEN 'Q1'
6 WHEN SUBSTR(MIN(month),5,2)||SUBSTR(MAX(month),5,2) = '0709' THEN 'Q2'
7 WHEN SUBSTR(MIN(month),5,2)||SUBSTR(MAX(month),5,2) = '1012' THEN 'Q3'
8 WHEN SUBSTR(MIN(month),5,2)||SUBSTR(MAX(month),5,2) = '0103' THEN 'Q4'
9 END
10 ELSE month
11 END AS month
12 ,CASE
13 WHEN grouping_id(shop_code) = 1 THEN 'ALL'
14 ELSE shop_code
15 END AS shop_code
16 ,SUM(sales_figure) AS sales_figure
17 FROM
18 (
19 SELECT
20 SUBSTR(starting_date,1,6) AS month
21 ,shop_code
22 ,SUM(sales_figure) AS sales_figure
23 FROM
24 test3
25 WHERE
26 starting_date BETWEEN '20110101' AND '20110331'
27 GROUP BY
28 SUBSTR(starting_date,1,6)
29 ,shop_code
30 )
31 GROUP BY
32 CUBE(month,shop_code)
33 HAVING
34 shop_code = '1000' OR
35 grouping_id(shop_code) = 1
36 ORDER BY
37 month
38* ,shop_code

8行が選択されました。

経過: 00:00:04.04

実行計画
----------------------------------------------------------
Plan hash value: 2039156429

-----------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | Pstart| Pstop |
-----------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 32 | | 52177 (2)| 00:10:27 | | |
| 1 | SORT ORDER BY | | 1 | 32 | | 52177 (2)| 00:10:27 | | |
|* 2 | FILTER | | | | | | | | |
| 3 | SORT GROUP BY | | 1 | 32 | | 52177 (2)| 00:10:27 | | |
| 4 | GENERATE CUBE | | 1 | 32 | | 52177 (2)| 00:10:27 | | |
| 5 | SORT GROUP BY | | 1 | 32 | | 52177 (2)| 00:10:27 | | |
| 6 | VIEW | | 80894 | 2527K| | 52171 (2)| 00:10:27 | | |
| 7 | HASH GROUP BY | | 80894 | 1342K| 428M| 52171 (2)| 00:10:27 | | |
| 8 | PARTITION RANGE ITERATOR | | 15M| 258M| | 20630 (2)| 00:04:08 | 1 | 3 |
|* 9 | TABLE ACCESS FULL | TEST3 | 15M| 258M| | 20630 (2)| 00:04:08 | 1 | 3 |
-----------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - filter("SHOP_CODE"='1000' OR GROUPING_ID(BIN_TO_NUM(SYS_OP_GROUPING("SHOP_CODE",1,0,SYS_OP_BITVEC)
))=1)
9 - filter("STARTING_DATE"<='20110331' AND "STARTING_DATE">='20110101')


統計
----------------------------------------------------------
1 recursive calls
0 db block gets
73961 consistent gets
25665 physical reads
0 redo size
871 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
3 sorts (memory)
0 sorts (disk)
8 rows processed

これまた恒例になった、オラクル任せのパラレル処理〜〜。ついにでました、1秒切りそうな処理時間w

  1  SELECT /*+ PARALLEL */
2 CASE
3 WHEN grouping_id(month) = 1 THEN
4 CASE
5 WHEN SUBSTR(MIN(month),5,2)||SUBSTR(MAX(month),5,2) = '0406' THEN 'Q1'
6 WHEN SUBSTR(MIN(month),5,2)||SUBSTR(MAX(month),5,2) = '0709' THEN 'Q2'
7 WHEN SUBSTR(MIN(month),5,2)||SUBSTR(MAX(month),5,2) = '1012' THEN 'Q3'
8 WHEN SUBSTR(MIN(month),5,2)||SUBSTR(MAX(month),5,2) = '0103' THEN 'Q4'
9 END
10 ELSE month
11 END AS month
12 ,CASE
13 WHEN grouping_id(shop_code) = 1 THEN 'ALL'
14 ELSE shop_code
15 END AS shop_code
16 ,SUM(sales_figure) AS sales_figure
17 FROM
18 (
19 SELECT
20 SUBSTR(starting_date,1,6) AS month
21 ,shop_code
22 ,SUM(sales_figure) AS sales_figure
23 FROM
24 test3
25 WHERE
26 starting_date BETWEEN '20110101' AND '20110331'
27 GROUP BY
28 SUBSTR(starting_date,1,6)
29 ,shop_code
30 )
31 GROUP BY
32 CUBE(month,shop_code)
33 HAVING
34 shop_code = '1000' OR
35 grouping_id(shop_code) = 1
36 ORDER BY
37 month
38* ,shop_code

8行が選択されました。

経過: 00:00:01.09

実行計画
----------------------------------------------------------
Plan hash value: 4042039911

-------------------------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | Pstart| Pstop | TQ |IN-OUT| PQ Distrib |
-------------------------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 32 | | 13834 (2)| 00:02:47 | | | | | |
| 1 | PX COORDINATOR | | | | | | | | | | | |
| 2 | PX SEND QC (ORDER) | :TQ10004 | 1 | 32 | | 13834 (2)| 00:02:47 | | | Q1,04 | P->S | QC (ORDER) |
| 3 | SORT ORDER BY | | 1 | 32 | | 13834 (2)| 00:02:47 | | | Q1,04 | PCWP | |
| 4 | PX RECEIVE | | 1 | 32 | | 13834 (2)| 00:02:47 | | | Q1,04 | PCWP | |
| 5 | PX SEND RANGE | :TQ10003 | 1 | 32 | | 13834 (2)| 00:02:47 | | | Q1,03 | P->P | RANGE |
|* 6 | FILTER | | | | | | | | | Q1,03 | PCWC | |
| 7 | SORT GROUP BY | | 1 | 32 | | 13834 (2)| 00:02:47 | | | Q1,03 | PCWP | |
| 8 | PX RECEIVE | | 1 | 32 | | 13834 (2)| 00:02:47 | | | Q1,03 | PCWP | |
| 9 | PX SEND HASH | :TQ10002 | 1 | 32 | | 13834 (2)| 00:02:47 | | | Q1,02 | P->P | HASH |
| 10 | GENERATE CUBE | | 1 | 32 | | 13834 (2)| 00:02:47 | | | Q1,02 | PCWC | |
| 11 | SORT GROUP BY | | 1 | 32 | | 13834 (2)| 00:02:47 | | | Q1,02 | PCWP | |
| 12 | PX RECEIVE | | 1 | 32 | | 13834 (2)| 00:02:47 | | | Q1,02 | PCWP | |
| 13 | PX SEND HASH | :TQ10001 | 1 | 32 | | 13834 (2)| 00:02:47 | | | Q1,01 | P->P | HASH |
| 14 | SORT GROUP BY | | 1 | 32 | | 13834 (2)| 00:02:47 | | | Q1,01 | PCWP | |
| 15 | VIEW | | 80894 | 2527K| | 13831 (2)| 00:02:46 | | | Q1,01 | PCWP | |
| 16 | HASH GROUP BY | | 80894 | 1342K| 428M| 13831 (2)| 00:02:46 | | | Q1,01 | PCWP | |
| 17 | PX RECEIVE | | 80894 | 1342K| | 13831 (2)| 00:02:46 | | | Q1,01 | PCWP | |
| 18 | PX SEND HASH | :TQ10000 | 80894 | 1342K| | 13831 (2)| 00:02:46 | | | Q1,00 | P->P | HASH |
| 19 | HASH GROUP BY | | 80894 | 1342K| 428M| 13831 (2)| 00:02:46 | | | Q1,00 | PCWP | |
| 20 | PX BLOCK ITERATOR | | 15M| 258M| | 5726 (2)| 00:01:09 | 1 | 3 | Q1,00 | PCWC | |
|* 21 | TABLE ACCESS FULL | TEST3 | 15M| 258M| | 5726 (2)| 00:01:09 | 1 | 3 | Q1,00 | PCWP | |
-------------------------------------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

6 - filter("SHOP_CODE"='1000' OR GROUPING_ID(BIN_TO_NUM(SYS_OP_GROUPING("SHOP_CODE",1,0,SYS_OP_BITVEC)))=1)
21 - filter("STARTING_DATE"<='20110331' AND "STARTING_DATE">='20110101')

Note
-----
- automatic DOP: Computed Degree of Parallelism is 4


統計
----------------------------------------------------------
24 recursive calls
0 db block gets
74326 consistent gets
73923 physical reads
0 redo size
871 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
17 sorts (memory)
0 sorts (disk)
8 rows processed


以上、いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング 無事に終了。(おわらすのか〜w)


おまけのおまけまでチューニングしハッシュパーティションのままでも6秒台までになることは確認しましたが、実際に提示したクエリは、UNION ALLで記述された無駄の多いダメダメクエリをWITH句とUNION ALLに書き換えた8秒台の結果となるクエリでした。

なぜ、今回のおまけのおまけで載せた最速クエリを提示しなかったか。。。。。その理由は・・・・・・、8秒台であればユーザと調整可能なレベルだったから、元クエリを書いた方に書き換え方を伝えやすかった(UNION ALLを残しつつチューニング)という、これまた大人の事情が絡んでいます;)。

いま以上にチューニングできるとはわかっていても、余力を残しつつ許容できるレベルでチューニングを止めるという”チューニングのゴール”は大切ですよ。(チューニングに割ける時間もお金も限りがありますから)

8秒台のクエリもデータ量や処理量が増加した際、再び問題視される時期が来るかもしれません。その時は、GROUP BY+CUBEにすれば喜ばれますよ。月単位のレンジパーティションに切り替えてあげるだけでも喜ばれますよ(より工数掛かりますが)。チューニング余地は見切れていたほうがいいですよね。


追記、なにか忘れてるー、と思ったらPIVOTの事すっかり忘れてたw。どうしようw

さて、次のネタのキーワードは、「悩ませ過ぎは及ばざるがごとし」w にしようかな。




これまでのあらずじ…

いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #1
いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #2
いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #3
いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #4
いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #5
いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #6
いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #7 おまけ

| | コメント (0) | トラックバック (0)

2011年8月 2日 (火)

いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング7 おまけ

前回、思いつきでGROUPING SETSに書き換えたら予想外に結果が悪かったわけですが、よーく考えたら事前にもうちょっとサマってしまえばいけるんじゃないかと気づいて少々書き換えてみました、
悲惨だった前回の結果に比べたら随分改善しましたが、それでも元に戻った程度ですね。(^^;;;;;;

やはり、いくない。

以下、前回、一番処理時間が長くなったケース。単純にGROUPING SETSに書き換えた場合、元のクエリより遅い。アクセスブロック数は3/4程度なんですがね。処理時間がねぇ〜

 1  SELECT
2 CASE
3 WHEN quarter IS NULL THEN month
4 ELSE quarter
5 END AS month
6 ,CASE
7 WHEN grouping_id = 1 THEN 'ALL'
8 ELSE shop_code
9 END AS shop_code
10 ,sales_figure
11 FROM (
12 SELECT
13 grouping_id(shop_code) as grouping_id
14 ,quarter
15 ,month
16 ,shop_code
17 ,SUM(sales_figure) AS sales_figure
18 FROM
19 (
20 SELECT
21 CASE
22 WHEN SUBSTR(starting_date,5,2) BETWEEN '04' AND '06' THEN 'Q1'
23 WHEN SUBSTR(starting_date,5,2) BETWEEN '07' AND '09' THEN 'Q2'
24 WHEN SUBSTR(starting_date,5,2) BETWEEN '10' AND '12' THEN 'Q3'
25 WHEN SUBSTR(starting_date,5,2) BETWEEN '01' AND '03' THEN 'Q4'
26 END AS quarter
27 ,SUBSTR(starting_date,1,6) AS month
28 ,shop_code
29 ,sales_figure
30 FROM
31 test2
32 WHERE
33 SUBSTR(starting_date,1,6) BETWEEN '201101' AND '201103'
34 )
35 GROUP BY GROUPING SETS (
36 (month, shop_code),
37 (quarter, shop_code),
38 (month),
39 (quarter)
40 )
41 )
42 WHERE
43 shop_code = '1000'
44 OR grouping_id = 1
45 ORDER BY
46 month
47* ,shop_code

8行が選択されました。

経過: 00:00:34.88

実行計画
----------------------------------------------------------
Plan hash value: 1500989315

------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | Pstart| Pstop |
------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 711K| 33M| | 93048 (3)| 00:18:37 | | |
| 1 | SORT ORDER BY | | 711K| 33M| 43M| 93048 (3)| 00:18:37 | | |
| 2 | VIEW | | 711K| 33M| | 84288 (3)| 00:16:52 | | |
| 3 | TEMP TABLE TRANSFORMATION | | | | | | | | |
| 4 | LOAD AS SELECT | SYS_TEMP_0FD9D6636_4A53D793 | | | | | | | |
| 5 | PARTITION HASH ALL | | 15M| 351M| | 84280 (3)| 00:16:52 | 1 | 4 |
|* 6 | TABLE ACCESS FULL | TEST2 | 15M| 351M| | 84280 (3)| 00:16:52 | 1 | 4 |
| 7 | LOAD AS SELECT | SYS_TEMP_0FD9D6637_4A53D793 | | | | | | | |
| 8 | SORT GROUP BY ROLLUP | | 1 | 33 | | 3 (34)| 00:00:01 | | |
| 9 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6636_4A53D793 | 1 | 33 | | 2 (0)| 00:00:01 | | |
| 10 | LOAD AS SELECT | SYS_TEMP_0FD9D6637_4A53D793 | | | | | | | |
| 11 | SORT GROUP BY ROLLUP | | 1 | 23 | | 3 (34)| 00:00:01 | | |
| 12 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6636_4A53D793 | 1 | 23 | | 2 (0)| 00:00:01 | | |
| 13 | VIEW | | 1 | 50 | | 2 (0)| 00:00:01 | | |
|* 14 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6637_4A53D793 | 1 | 50 | | 2 (0)| 00:00:01 | | |
------------------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

6 - filter(SUBSTR("STARTING_DATE",1,6)<='201103' AND SUBSTR("STARTING_DATE",1,6)>='201101')
14 - filter("SYS_TEMP_0FD9D6637_4A53D793"."C1"='1000' OR
BIN_TO_NUM(SYS_OP_VECBIT(SYS_OP_NUMTORAW("SYS_TEMP_0FD9D6637_4A53D793"."D0"),1))=1)


統計
----------------------------------------------------------
761 recursive calls
52432 db block gets
405879 consistent gets
405750 physical reads
1944 redo size
871 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
3 sorts (memory)
0 sorts (disk)
8 rows processed

意外な結果になってしまったので、WITH句は利用していないのですが今回試したのは事前にある程度サマったケース。
コードサイズも一番小さくて可読性もよいと思うんだけどね〜。
アクセスしているブロック数は1/2でいい感じなのですが、処理時間は今回ネタにしたクエリ(後述)より少々良い程度。ブロック数は半減したのに処理時間がさほど改善していないのはCPUへの負荷が考えていた以上に高いのでしょうかね。(それはまた別途しらべておきますか)

  1  SELECT
2 CASE
3 WHEN quarter IS NULL THEN month
4 ELSE quarter
5 END AS month
6 ,CASE
7 WHEN grouping_id(shop_code) = 1 THEN 'ALL'
8 ELSE shop_code
9 END AS shop_code
10 ,SUM(sales_figure) AS sales_figure
11 FROM
12 (
13 SELECT
14 CASE
15 WHEN SUBSTR(starting_date,5,2) BETWEEN '04' AND '06' THEN 'Q1'
16 WHEN SUBSTR(starting_date,5,2) BETWEEN '07' AND '09' THEN 'Q2'
17 WHEN SUBSTR(starting_date,5,2) BETWEEN '10' AND '12' THEN 'Q3'
18 WHEN SUBSTR(starting_date,5,2) BETWEEN '01' AND '03' THEN 'Q4'
19 END AS quarter
20 ,SUBSTR(starting_date,1,6) AS month
21 ,shop_code
22 ,SUM(sales_figure) AS sales_figure
23 FROM
24 test2
25 WHERE
26 starting_date BETWEEN '20110101' AND '20110331'
27 GROUP BY
28 CASE
29 WHEN SUBSTR(starting_date,5,2) BETWEEN '04' AND '06' THEN 'Q1'
30 WHEN SUBSTR(starting_date,5,2) BETWEEN '07' AND '09' THEN 'Q2'
31 WHEN SUBSTR(starting_date,5,2) BETWEEN '10' AND '12' THEN 'Q3'
32 WHEN SUBSTR(starting_date,5,2) BETWEEN '01' AND '03' THEN 'Q4'
33 END
34 ,SUBSTR(starting_date,1,6)
35 ,shop_code
36 )
37 GROUP BY GROUPING SETS (
38 (month, shop_code),
39 (quarter, shop_code),
40 (month),
41 (quarter)
42 )
43 HAVING
44 shop_code = '1000'
45 OR grouping_id(shop_code) = 1
46 ORDER BY
47 month
48* ,shop_code

8行が選択されました。

経過: 00:00:19.69

実行計画
----------------------------------------------------------
Plan hash value: 3332072264

--------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
--------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2758 | 134K| 83181 (2)| 00:16:39 | | |
| 1 | TEMP TABLE TRANSFORMATION | | | | | | | |
| 2 | LOAD AS SELECT | SYS_TEMP_0FD9D66D1_4A54AE09 | | | | | | |
| 3 | HASH GROUP BY | | 17550 | 411K| 83172 (2)| 00:16:39 | | |
| 4 | PARTITION HASH ALL | | 394K| 9242K| 83161 (2)| 00:16:38 | 1 | 4 |
|* 5 | TABLE ACCESS FULL | TEST2 | 394K| 9242K| 83161 (2)| 00:16:38 | 1 | 4 |
| 6 | LOAD AS SELECT | SYS_TEMP_0FD9D66D2_4A54AE09 | | | | | | |
| 7 | SORT GROUP BY ROLLUP | | 1 | 33 | 3 (34)| 00:00:01 | | |
| 8 | TABLE ACCESS FULL | SYS_TEMP_0FD9D66D1_4A54AE09 | 1 | 33 | 2 (0)| 00:00:01 | | |
| 9 | LOAD AS SELECT | SYS_TEMP_0FD9D66D2_4A54AE09 | | | | | | |
| 10 | SORT GROUP BY ROLLUP | | 1 | 23 | 3 (34)| 00:00:01 | | |
| 11 | TABLE ACCESS FULL | SYS_TEMP_0FD9D66D1_4A54AE09 | 1 | 23 | 2 (0)| 00:00:01 | | |
| 12 | SORT ORDER BY | | 2758 | 134K| 3 (34)| 00:00:01 | | |
| 13 | VIEW | | 1 | 50 | 2 (0)| 00:00:01 | | |
|* 14 | TABLE ACCESS FULL | SYS_TEMP_0FD9D66D2_4A54AE09 | 1 | 50 | 2 (0)| 00:00:01 | | |
--------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

5 - filter("SYS_TBL_$2$"."STARTING_DATE"<='20110331' AND SUBSTR("STARTING_DATE",1,6)<='201103' AND
SUBSTR("STARTING_DATE",1,6)>='201101' AND "SYS_TBL_$2$"."STARTING_DATE">='20110101')
14 - filter("SYS_TEMP_0FD9D66D2_4A54AE09"."C1"='1000' OR
BIN_TO_NUM(SYS_OP_VECBIT(SYS_OP_NUMTORAW("SYS_TEMP_0FD9D66D2_4A54AE09"."D0"),1))=1)


統計
----------------------------------------------------------
358 recursive calls
52 db block gets
302715 consistent gets
302587 physical reads
1764 redo size
871 bytes sent via SQL*Net to client
519 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
3 sorts (memory)
0 sorts (disk)
8 rows processed


前々回、WITH句とunion allだけでチューニングしたクエリと比べてみるとブロック数は同じ程度でもCPUコストの差は実行計画からもある程度読み取れますね(参考程度ですがw)。

  1  WITH
2 t01 AS
3 (
4 SELECT
5 SUBSTR(starting_date,1,6) AS month
6 ,CASE
7 WHEN SUBSTR(starting_date,5,2) BETWEEN '04' AND '06' THEN 'Q1'
8 WHEN SUBSTR(starting_date,5,2) BETWEEN '07' AND '09' THEN 'Q2'
9 WHEN SUBSTR(starting_date,5,2) BETWEEN '10' AND '12' THEN 'Q3'
10 WHEN SUBSTR(starting_date,5,2) BETWEEN '01' AND '03' THEN 'Q4'
11 END AS quarter
12 ,shop_code
13 ,SUM(sales_figure) as sales_figure
14 FROM
15 test2
16 WHERE
17 starting_date BETWEEN '20110101' AND '20110331'
18 GROUP BY
19 SUBSTR(starting_date,1,6)
20 ,SUBSTR(starting_date,5,2)
21 ,shop_code
22 ),
23 t02 AS
24 (
25 SELECT
26 month
27 ,quarter
28 ,shop_code
29 ,sales_figure
30 FROM
31 t01
32 WHERE
33 month BETWEEN '201101' AND '201103'
34 AND shop_code = '1000'
35 )
36 SELECT
37 month
38 ,shop_code
39 ,sales_figure
40 FROM
41 (
42 SELECT
43 month
44 ,shop_code
45 ,SUM(sales_figure) AS sales_figure
46 FROM
47 t02
48 GROUP BY
49 month
50 ,shop_code
51 UNION ALL
52 SELECT
53 quarter AS month
54 ,shop_code
55 ,SUM(sales_figure) AS sales_figure
56 FROM
57 t02
58 GROUP BY
59 quarter
60 ,shop_code
61 UNION ALL
62 SELECT
63 month
64 ,'ALL ' AS shop_code
65 ,SUM(sales_figure) AS sales_figure
66 FROM
67 t01
68 GROUP BY
69 month
70 UNION ALL
71 SELECT
72 quarter AS month
73 ,'ALL ' AS shop_code
74 ,SUM(sales_figure) AS salles_figure
75 FROM
76 t01
77 GROUP BY
78 quarter
79 )
80 ORDER BY
81 month
82* ,shop_code

8行が選択されました。

経過: 00:00:08.35

実行計画
----------------------------------------------------------
Plan hash value: 2861358139

--------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
--------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3692 | 118K| 83282 (2)| 00:16:40 | | |
| 1 | TEMP TABLE TRANSFORMATION | | | | | | | |
| 2 | LOAD AS SELECT | SYS_TEMP_0FD9D660A_4A53712A | | | | | | |
| 3 | HASH GROUP BY | | 17550 | 411K| 83172 (2)| 00:16:39 | | |
| 4 | PARTITION HASH ALL | | 394K| 9242K| 83161 (2)| 00:16:38 | 1 | 4 |
|* 5 | TABLE ACCESS FULL | TEST2 | 394K| 9242K| 83161 (2)| 00:16:38 | 1 | 4 |
| 6 | LOAD AS SELECT | SYS_TEMP_0FD9D660B_4A53712A | | | | | | |
|* 7 | VIEW | | 17550 | 497K| 17 (0)| 00:00:01 | | |
| 8 | TABLE ACCESS FULL | SYS_TEMP_0FD9D660A_4A53712A | 17550 | 411K| 17 (0)| 00:00:01 | | |
| 9 | SORT ORDER BY | | 3692 | 118K| 93 (8)| 00:00:02 | | |
| 10 | VIEW | | 3692 | 118K| 92 (7)| 00:00:02 | | |
| 11 | UNION-ALL | | | | | | | |
| 12 | HASH GROUP BY | | 2758 | 68950 | 27 (4)| 00:00:01 | | |
| 13 | VIEW | | 17550 | 428K| 26 (0)| 00:00:01 | | |
| 14 | TABLE ACCESS FULL | SYS_TEMP_0FD9D660B_4A53712A | 17550 | 497K| 26 (0)| 00:00:01 | | |
| 15 | HASH GROUP BY | | 920 | 20240 | 27 (4)| 00:00:01 | | |
| 16 | VIEW | | 17550 | 377K| 26 (0)| 00:00:01 | | |
| 17 | TABLE ACCESS FULL | SYS_TEMP_0FD9D660B_4A53712A | 17550 | 497K| 26 (0)| 00:00:01 | | |
| 18 | HASH GROUP BY | | 13 | 260 | 18 (6)| 00:00:01 | | |
| 19 | VIEW | | 17550 | 342K| 17 (0)| 00:00:01 | | |
| 20 | TABLE ACCESS FULL | SYS_TEMP_0FD9D660A_4A53712A | 17550 | 411K| 17 (0)| 00:00:01 | | |
| 21 | HASH GROUP BY | | 1 | 17 | 18 (6)| 00:00:01 | | |
| 22 | VIEW | | 17550 | 291K| 17 (0)| 00:00:01 | | |
| 23 | TABLE ACCESS FULL | SYS_TEMP_0FD9D660A_4A53712A | 17550 | 411K| 17 (0)| 00:00:01 | | |
--------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

5 - filter("STARTING_DATE"<='20110331' AND SUBSTR("STARTING_DATE",1,6)<='201103' AND
SUBSTR("STARTING_DATE",1,6)>='201101' AND "STARTING_DATE">='20110101')
7 - filter("MONTH">='201101' AND "MONTH"<='201103' AND "SHOP_CODE"='1000')


統計
----------------------------------------------------------
4 recursive calls
28 db block gets
302642 consistent gets
302570 physical reads
1156 redo size
875 bytes sent via SQL*Net to client
519 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
8 rows processed


ということで、おまけはおしまい、次回へつづく。(どーやってまとめんるんだこれw)

追記(2011/8/3)
次回は、今回チューニングしたGROUPING SETSを利用した文をさらにチューニングするというおまけのおまけ。(ほんと、どーやってまとめんだこれ!)


これまでのあらずじ…

いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #1
いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #2
いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #3
いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #4
いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #5
いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #6


| | コメント (0) | トラックバック (0)

2011年7月24日 (日)

いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #6

2011/7/28追記
GROUPING SETSで異常に遅かったのは使い方わるいなーと m(_ _)m WITH句で一時表1つ使うのと同じぐらいにはなるかもね。と(次回書きます)

前回のつづきでーす。

前回のは、元々がイケテない、かつ、大人の事情でパーティションタイプ変更とか、マテリアライズドビューとか、パラレルクエリーもだーめー。と言いつつ、なんとか、できる限り早くしてくれーという、匂いの元を絶たないで別の匂いでごまかしてくれー的なことだったのですが、いろいろと考えた末、WITH句を使えばなんとかいい感じになりました。でも、元が元だけにほぼ限界ですね。

大人の事情で男らしくずばーっとパーティションタイプ変更することができないとか言ってた方々も、この結果をもって、交渉のテーブルにつけるんじゃないかな。検討祈る :)
この結果で納得してもらえるかは感知しませんからねw 最後の手としてパーティションタイプ変更を残しておいてもいいいと思いますし。;)

ということで、今回は、他の方法との比較編。

前回、grouping setsでもいけそーな感じがすると書いたのですが、grouping setsの場合裏の動きはOracleにお任せなので…

まあ、見てみましょう。


最初は、シンプルにgrouping setsに置き換えて見ました。(深く考えてないので余計な部分はまだまだありそうですがw )

実行計画と処理時間、アクセスブロック数みて少々意外な結果に驚いたんですよ。 

ダメダメだった元のクエリより処理時間は長くなってる><。 アクセスしているブロック数は随分少なくなっているんですが。CPUへの負荷が高いのか(詳細は別途調べるとして)とにかく前より遅くなっちゃNGです。ただ、クエリ自体は随分読みやすい :)

grouping setsで置き換えた今回のクエリ、実行計画を見るとWITH句で書き換えたときのようものにかなり似ていますが、WITH句で書き換えた場合と大きく異なるのは内部で一時表に置き換えられるタイミングにありそうですね。WITH句は本体のクエリとは別で、しかも一番先に実行されますが、以下の実行計画をみると違いますよね。WITH句で書き換えた実行計画と比較するとその違いがよくわかります。

  1  SELECT
2 CASE
3 WHEN quarter IS NULL THEN month
4 ELSE quarter
5 END AS month
6 ,CASE
7 WHEN grouping_id = 1 THEN 'ALL'
8 ELSE shop_code
9 END AS shop_code
10 ,sales_figure
11 FROM (
12 SELECT
13 grouping_id(shop_code) as grouping_id
14 ,quarter
15 ,month
16 ,shop_code
17 ,SUM(sales_figure) AS sales_figure
18 FROM
19 (
20 SELECT
21 CASE
22 WHEN SUBSTR(starting_date,5,2) BETWEEN '04' AND '06' THEN 'Q1'
23 WHEN SUBSTR(starting_date,5,2) BETWEEN '07' AND '09' THEN 'Q2'
24 WHEN SUBSTR(starting_date,5,2) BETWEEN '10' AND '12' THEN 'Q3'
25 WHEN SUBSTR(starting_date,5,2) BETWEEN '01' AND '03' THEN 'Q4'
26 END AS quarter
27 ,SUBSTR(starting_date,1,6) AS month
28 ,shop_code
29 ,sales_figure
30 FROM
31 test2
32 WHERE
33 SUBSTR(starting_date,1,6) BETWEEN '201101' AND '201103'
34 )
35 GROUP BY GROUPING SETS (
36 (month, shop_code),
37 (quarter, shop_code),
38 (month),
39 (quarter)
40 )
41 )
42 WHERE
43 shop_code = '1000'
44 OR grouping_id = 1
45 ORDER BY
46 month
47* ,shop_code

8行が選択されました。

経過: 00:00:34.88

実行計画
----------------------------------------------------------
Plan hash value: 1500989315

------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | Pstart| Pstop |
------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 711K| 33M| | 93048 (3)| 00:18:37 | | |
| 1 | SORT ORDER BY | | 711K| 33M| 43M| 93048 (3)| 00:18:37 | | |
| 2 | VIEW | | 711K| 33M| | 84288 (3)| 00:16:52 | | |
| 3 | TEMP TABLE TRANSFORMATION | | | | | | | | |
| 4 | LOAD AS SELECT | SYS_TEMP_0FD9D6636_4A53D793 | | | | | | | |
| 5 | PARTITION HASH ALL | | 15M| 351M| | 84280 (3)| 00:16:52 | 1 | 4 |
|* 6 | TABLE ACCESS FULL | TEST2 | 15M| 351M| | 84280 (3)| 00:16:52 | 1 | 4 |
| 7 | LOAD AS SELECT | SYS_TEMP_0FD9D6637_4A53D793 | | | | | | | |
| 8 | SORT GROUP BY ROLLUP | | 1 | 33 | | 3 (34)| 00:00:01 | | |
| 9 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6636_4A53D793 | 1 | 33 | | 2 (0)| 00:00:01 | | |
| 10 | LOAD AS SELECT | SYS_TEMP_0FD9D6637_4A53D793 | | | | | | | |
| 11 | SORT GROUP BY ROLLUP | | 1 | 23 | | 3 (34)| 00:00:01 | | |
| 12 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6636_4A53D793 | 1 | 23 | | 2 (0)| 00:00:01 | | |
| 13 | VIEW | | 1 | 50 | | 2 (0)| 00:00:01 | | |
|* 14 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6637_4A53D793 | 1 | 50 | | 2 (0)| 00:00:01 | | |
------------------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

6 - filter(SUBSTR("STARTING_DATE",1,6)<='201103' AND SUBSTR("STARTING_DATE",1,6)>='201101')
14 - filter("SYS_TEMP_0FD9D6637_4A53D793"."C1"='1000' OR
BIN_TO_NUM(SYS_OP_VECBIT(SYS_OP_NUMTORAW("SYS_TEMP_0FD9D6637_4A53D793"."D0"),1))=1)


統計
----------------------------------------------------------
761 recursive calls
52432 db block gets
405879 consistent gets
405750 physical reads
1944 redo size
871 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
3 sorts (memory)
0 sorts (disk)
8 rows processed

GROUPING SETSで内部的に行われる一時表作成の効率が今ひとつなのであれば、やはり明示的にWITH句で宣言してからやったほうがいいのかな〜ということで、WITH句で一番大きな一時表を作ってみます。

お〜〜〜〜〜〜〜〜〜〜っ。随分変りましたねー。

  1  WITH
2 t01 AS
3 (
4 SELECT
5 SUBSTR(starting_date,1,6) AS month
6 ,CASE
7 WHEN SUBSTR(starting_date,5,2) BETWEEN '04' AND '06' THEN 'Q1'
8 WHEN SUBSTR(starting_date,5,2) BETWEEN '07' AND '09' THEN 'Q2'
9 WHEN SUBSTR(starting_date,5,2) BETWEEN '10' AND '12' THEN 'Q3'
10 WHEN SUBSTR(starting_date,5,2) BETWEEN '01' AND '03' THEN 'Q4'
11 END AS quarter
12 ,shop_code
13 ,SUM(sales_figure) as sales_figure
14 FROM
15 test2
16 WHERE
17 starting_date BETWEEN '20110101' AND '20110331'
18 GROUP BY
19  SUBSTR(starting_date,1,6)
20 ,SUBSTR(starting_date,5,2)
21 ,shop_code
22 )
23 SELECT
24 CASE
25 WHEN quarter IS NULL THEN month
26 ELSE quarter
27 END AS month
28 ,CASE
29 WHEN grouping_id = 1 THEN 'ALL'
30 ELSE shop_code
31 END AS shop_code
32 ,sales_figure
33 FROM (
34 SELECT
35 grouping_id(shop_code) as grouping_id
36 ,quarter
37 ,month
38 ,shop_code
39 ,SUM(sales_figure) AS sales_figure
40 FROM
41 t01
42 GROUP BY GROUPING SETS (
43 (month, shop_code),
44 (quarter, shop_code),
45 (month),
46 (quarter)
47 )
48 )
49 WHERE
50 shop_code = '1000'
51 OR grouping_id = 1
52 ORDER BY
53 month
54* ,shop_code

8行が選択されました。

経過: 00:00:11.83

実行計画
----------------------------------------------------------
Plan hash value: 3348003365

----------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2758 | 134K| 83181 (2)| 00:16:39 | | |
| 1 | SORT ORDER BY | | 2758 | 134K| 83181 (2)| 00:16:39 | | |
| 2 | VIEW | | 2758 | 134K| 83180 (2)| 00:16:39 | | |
| 3 | TEMP TABLE TRANSFORMATION | | | | | | | |
| 4 | LOAD AS SELECT | SYS_TEMP_0FD9D6650_4A53D793 | | | | | | |
| 5 | HASH GROUP BY | | 17550 | 411K| 83172 (2)| 00:16:39 | | |
| 6 | PARTITION HASH ALL | | 394K| 9242K| 83161 (2)| 00:16:38 | 1 | 4 |
|* 7 | TABLE ACCESS FULL | TEST2 | 394K| 9242K| 83161 (2)| 00:16:38 | 1 | 4 |
| 8 | LOAD AS SELECT | SYS_TEMP_0FD9D6651_4A53D793 | | | | | | |
| 9 | SORT GROUP BY ROLLUP | | 1 | 33 | 3 (34)| 00:00:01 | | |
| 10 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6650_4A53D793 | 1 | 33 | 2 (0)| 00:00:01 | | |
| 11 | LOAD AS SELECT | SYS_TEMP_0FD9D6651_4A53D793 | | | | | | |
| 12 | SORT GROUP BY ROLLUP | | 1 | 23 | 3 (34)| 00:00:01 | | |
| 13 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6650_4A53D793 | 1 | 23 | 2 (0)| 00:00:01 | | |
| 14 | VIEW | | 1 | 50 | 2 (0)| 00:00:01 | | |
|* 15 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6651_4A53D793 | 1 | 50 | 2 (0)| 00:00:01 | | |
----------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

7 - filter("SYS_TBL_$2$"."STARTING_DATE"<='20110331' AND SUBSTR("STARTING_DATE",1,6)<='201103' AND
SUBSTR("STARTING_DATE",1,6)>='201101' AND "SYS_TBL_$2$"."STARTING_DATE">='20110101')
15 - filter("SYS_TEMP_0FD9D66B3_4A54062A"."C1"='1000' OR
BIN_TO_NUM(SYS_OP_VECBIT(SYS_OP_NUMTORAW("SYS_TEMP_0FD9D66B3_4A54062A"."D0"),1))=1)


統計
----------------------------------------------------------
358 recursive calls
53 db block gets
302715 consistent gets
302589 physical reads
1712 redo size
871 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
3 sorts (memory)
0 sorts (disk)
8 rows processed


じゃ、WITH句だけで行ったチューニング同様に2つの一時表を作ることにしましょー :)
WITH句で2つの一時表を準備(本体の表へは1度だけアクセス)、かつ、grouping sets を使いunion allの利用は最小限にしてみました。w

読みやすくなったし、速度的にも WITH句で2つの一時表を使う場合と変らないし、GROUPING SETSだけだと今回のような問題は解決しづらいかもしれませんね、今のところ。
可読性の向上にはかなり効果あるとおもいます、GROUPING SETSって。


  1  WITH
2 t01 AS
3 (
4 SELECT
5 SUBSTR(starting_date,1,6) AS month
6 ,CASE
7 WHEN SUBSTR(starting_date,5,2) BETWEEN '04' AND '06' THEN 'Q1'
8 WHEN SUBSTR(starting_date,5,2) BETWEEN '07' AND '09' THEN 'Q2'
9 WHEN SUBSTR(starting_date,5,2) BETWEEN '10' AND '12' THEN 'Q3'
10 WHEN SUBSTR(starting_date,5,2) BETWEEN '01' AND '03' THEN 'Q4'
11 END AS quarter
12 ,shop_code
13 ,SUM(sales_figure) as sales_figure
14 FROM
15 test2
16 WHERE
17 starting_date BETWEEN '20110101' AND '20110331'
18 GROUP BY
19  SUBSTR(starting_date,1,6)
20 ,SUBSTR(starting_date,5,2)
21 ,shop_code
22 ),
23 t02 AS
24 (
25 SELECT
26 month
27 ,quarter
28 ,shop_code
29 ,sales_figure
30 FROM
31 t01
32 WHERE
33 month BETWEEN '201101' AND '201103'
34 AND shop_code = '1000'
35 )
36 SELECT
37 CASE
38 WHEN quarter IS NULL THEN month
39 ELSE quarter
40 END AS month
41 ,shop_code
42 ,sales_figure
43 FROM (
44 SELECT
45 quarter
46 ,month
47 ,shop_code
48 ,SUM(sales_figure) AS sales_figure
49 FROM
50 t02
51 GROUP BY GROUPING SETS (
52 (month, shop_code),
53 (quarter, shop_code)
54 )
55 UNION ALL
56 SELECT
57 quarter
58 ,month
59 ,'ALL' AS shop_code
60 ,SUM(sales_figure) AS sales_figure
61 FROM
62 t01
63 GROUP BY GROUPING SETS (
64 (month),
65 (quarter)
66 )
67 )
68 ORDER BY
69 month
70* ,shop_code

8行が選択されました。

経過: 00:00:08.34

実行計画
----------------------------------------------------------
Plan hash value: 1439899557

------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 17 | 595 | 83223 (2)| 00:16:39 | | |
| 1 | TEMP TABLE TRANSFORMATION | | | | | | | |
| 2 | LOAD AS SELECT | SYS_TEMP_0FD9D667D_4A53D793 | | | | | | |
| 3 | HASH GROUP BY | | 17550 | 411K| 83172 (2)| 00:16:39 | | |
| 4 | PARTITION HASH ALL | | 394K| 9242K| 83161 (2)| 00:16:38 | 1 | 4 |
|* 5 | TABLE ACCESS FULL | TEST2 | 394K| 9242K| 83161 (2)| 00:16:38 | 1 | 4 |
| 6 | SORT ORDER BY | | 17 | 595 | 51 (10)| 00:00:01 | | |
| 7 | VIEW | | 17 | 595 | 50 (8)| 00:00:01 | | |
| 8 | UNION-ALL | | | | | | | |
| 9 | TEMP TABLE TRANSFORMATION | | | | | | | |
| 10 | LOAD AS SELECT | SYS_TEMP_0FD9D667E_4A53D793 | | | | | | |
|* 11 | TABLE ACCESS FULL | SYS_TEMP_0FD9D667D_4A53D793 | 1 | 24 | 17 (0)| 00:00:01 | | |
| 12 | LOAD AS SELECT | SYS_TEMP_0FD9D667F_4A53D793 | | | | | | |
| 13 | HASH GROUP BY | | 1 | 33 | 3 (34)| 00:00:01 | | |
| 14 | TABLE ACCESS FULL | SYS_TEMP_0FD9D667E_4A53D793 | 1 | 33 | 2 (0)| 00:00:01 | | |
| 15 | LOAD AS SELECT | SYS_TEMP_0FD9D667F_4A53D793 | | | | | | |
| 16 | HASH GROUP BY | | 1 | 23 | 3 (34)| 00:00:01 | | |
| 17 | TABLE ACCESS FULL | SYS_TEMP_0FD9D667E_4A53D793 | 1 | 23 | 2 (0)| 00:00:01 | | |
| 18 | VIEW | | 1 | 37 | 2 (0)| 00:00:01 | | |
| 19 | TABLE ACCESS FULL | SYS_TEMP_0FD9D667F_4A53D793 | 1 | 37 | 2 (0)| 00:00:01 | | |
| 20 | TEMP TABLE TRANSFORMATION | | | | | | | |
| 21 | LOAD AS SELECT | SYS_TEMP_0FD9D6680_4A53D793 | | | | | | |
| 22 | TABLE ACCESS FULL | SYS_TEMP_0FD9D667D_4A53D793 | 17550 | 411K| 17 (0)| 00:00:01 | | |
| 23 | LOAD AS SELECT | SYS_TEMP_0FD9D6681_4A53D793 | | | | | | |
| 24 | HASH GROUP BY | | 1 | 27 | 3 (34)| 00:00:01 | | |
| 25 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6680_4A53D793 | 1 | 27 | 2 (0)| 00:00:01 | | |
| 26 | LOAD AS SELECT | SYS_TEMP_0FD9D6681_4A53D793 | | | | | | |
| 27 | HASH GROUP BY | | 1 | 17 | 3 (34)| 00:00:01 | | |
| 28 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6680_4A53D793 | 1 | 17 | 2 (0)| 00:00:01 | | |
| 29 | VIEW | | 1 | 31 | 2 (0)| 00:00:01 | | |
| 30 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6681_4A53D793 | 1 | 31 | 2 (0)| 00:00:01 | | |
------------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

5 - filter("STARTING_DATE"<='20110331' AND SUBSTR("STARTING_DATE",1,6)<='201103' AND
SUBSTR("STARTING_DATE",1,6)>='201101' AND "STARTING_DATE">='20110101')
11 - filter("SYS_TBL_$2$"."C0">='201101' AND "SYS_TBL_$2$"."C0"<='201103' AND "SYS_TBL_$2$"."C2"='1000')


統計
----------------------------------------------------------
790 recursive calls
82 db block gets
302843 consistent gets
302593 physical reads
3964 redo size
871 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
8 rows processed

次回は、月毎のレンジパーティションで同じ対処をしたらとこまで改善するのか確認しておきましょう。




これまでのあらずじ…

いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #1
いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #2
いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #3
いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #4
いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #5

| | コメント (0) | トラックバック (0)

2011年7月19日 (火)

いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #5

前回のつづきです。

さて、前回登場したボスキャラなSQL。どう料理しましょーか。
前回は、まずは肩ならし程度のチューニングをしましたがそれほど改善していません。(^^;;;; 元が元ですからね。

このままでは多いく改善することはむーりー、なので構文変更を前提にしましょう。

で、このクエリをよーく見ていたら、店、品目毎の日単位の売上げデータから、店毎の月単位売上げ合計と四半期の売上げ合計、全店の月単位売上げ合計、四半期の売上げ合計を求めるクエリだとわかりました。

本来なら月単位のレンジパーティション表とか、マテリアライズドビューでも用意しておけばすげー簡単な話ではあるんですが、パーティションタイプの変更とかマテリアライズドビューの追加作成とかむーりーと言われてしまう大人の事情が因縁をつけてきますw

でも、じ〜〜〜〜〜〜っと、このSQL文を見ていると改善案が見えてきます。大きな無駄が……………………見えてきますよね。ほーら、ほーらw

  1  SELECT
2 month
3 ,shop_code
4 ,sales_figure
5 FROM
6 (
7 SELECT
8 SUBSTR(starting_date,1,6) AS month
9 ,shop_code
10 ,SUM(sales_figure) AS sales_figure
11 FROM
12 test2
13 WHERE
14 starting_date BETWEEN '20110101' AND '20110331'
15 AND shop_code = '1000'
16 GROUP BY
17 SUBSTR(starting_date,1,6)
18 ,shop_code
19 UNION ALL
20 SELECT
21 CASE
22 WHEN SUBSTR(starting_date,5,2) BETWEEN '04' AND '06' THEN 'Q1'
23 WHEN SUBSTR(starting_date,5,2) BETWEEN '07' AND '09' THEN 'Q2'
24 WHEN SUBSTR(starting_date,5,2) BETWEEN '10' AND '12' THEN 'Q3'
25 WHEN SUBSTR(starting_date,5,2) BETWEEN '01' AND '03' THEN 'Q4'
26 END AS month
27 ,shop_code
28 ,SUM(sales_figure) AS salles_figure
29 FROM
30 test2
31 WHERE
32 starting_date BETWEEN '20110101' AND '20110331'
33 AND shop_code = '1000'
34 GROUP BY
35 CASE
36 WHEN SUBSTR(starting_date,5,2) BETWEEN '04' AND '06' THEN 'Q1'
37 WHEN SUBSTR(starting_date,5,2) BETWEEN '07' AND '09' THEN 'Q2'
38 WHEN SUBSTR(starting_date,5,2) BETWEEN '10' AND '12' THEN 'Q3'
39 WHEN SUBSTR(starting_date,5,2) BETWEEN '01' AND '03' THEN 'Q4'
40 END
41 ,shop_code
42 UNION ALL
43 SELECT
44 SUBSTR(starting_date,1,6) AS month
45 ,'ALL ' AS shop_code
46 ,SUM(sales_figure) AS sales_figure
47 FROM
48 test2
49 WHERE
50 starting_date BETWEEN '20110101' AND '20110331'
51 GROUP BY
52 SUBSTR(starting_date,1,6)
53 UNION ALL
54 SELECT
55 CASE
56 WHEN SUBSTR(starting_date,5,2) BETWEEN '04' AND '06' THEN 'Q1'
57 WHEN SUBSTR(starting_date,5,2) BETWEEN '07' AND '09' THEN 'Q2'
58 WHEN SUBSTR(starting_date,5,2) BETWEEN '10' AND '12' THEN 'Q3'
59 WHEN SUBSTR(starting_date,5,2) BETWEEN '01' AND '03' THEN 'Q4'
60 END AS month
61 ,'ALL ' AS shop_code
62 ,SUM(sales_figure) AS salles_figure
63 FROM
64 test2
65 WHERE
66 starting_date BETWEEN '20110101' AND '20110331'
67 GROUP BY
68 CASE
69 WHEN SUBSTR(starting_date,5,2) BETWEEN '04' AND '06' THEN 'Q1'
70 WHEN SUBSTR(starting_date,5,2) BETWEEN '07' AND '09' THEN 'Q2'
71 WHEN SUBSTR(starting_date,5,2) BETWEEN '10' AND '12' THEN 'Q3'
72 WHEN SUBSTR(starting_date,5,2) BETWEEN '01' AND '03' THEN 'Q4'
73 END
74 )
75 ORDER BY
76 month
77* ,shop_code

8行が選択されました。

経過: 00:00:21.03

実行計画
----------------------------------------------------------
Plan hash value: 1898009794

-------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |Pstart|Pstop |
-------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 22 | 726 | 166K (2)| 00:33:18 | | |
| 1 | SORT ORDER BY | | 22 | 726 | 166K (2)| 00:33:18 | | |
| 2 | VIEW | | 22 | 726 | 166K (2)| 00:33:18 | | |
| 3 | UNION-ALL | | | | | | | |
| 4 | HASH GROUP BY | | 3 | 72 | 43 (3)| 00:00:01 | | |
| 5 | PARTITION HASH ALL | | 303 | 7272 | 42 (0)| 00:00:01 | 1 | 4 |
| 6 | TABLE ACCESS BY LOCAL INDEX ROWID| TEST2 | 303 | 7272 | 42 (0)| 00:00:01 | 1 | 4 |
|* 7 | INDEX RANGE SCAN | PK_TEST2 | 303 | | 19 (0)| 00:00:01 | 1 | 4 |
| 8 | HASH GROUP BY | | 7 | 119 | 43 (3)| 00:00:01 | | |
| 9 | PARTITION HASH ALL | | 303 | 5151 | 42 (0)| 00:00:01 | 1 | 4 |
| 10 | TABLE ACCESS BY LOCAL INDEX ROWID| TEST2 | 303 | 5151 | 42 (0)| 00:00:01 | 1 | 4 |
|* 11 | INDEX RANGE SCAN | PK_TEST2 | 303 | | 19 (0)| 00:00:01 | 1 | 4 |
| 12 | HASH GROUP BY | | 3 | 57 | 83172 (2)| 00:16:39 | | |
| 13 | PARTITION HASH ALL | | 394K| 7316K| 83161 (2)| 00:16:38 | 1 | 4 |
|* 14 | TABLE ACCESS FULL | TEST2 | 394K| 7316K| 83161 (2)| 00:16:38 | 1 | 4 |
| 15 | HASH GROUP BY | | 9 | 108 | 83172 (2)| 00:16:39 | | |
| 16 | PARTITION HASH ALL | | 394K| 4621K| 83161 (2)| 00:16:38 | 1 | 4 |
|* 17 | TABLE ACCESS FULL | TEST2 | 394K| 4621K| 83161 (2)| 00:16:38 | 1 | 4 |
-------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

7 - access("SHOP_CODE"='1000' AND "STARTING_DATE">='20110101' AND "STARTING_DATE"<='20110331')
filter(SUBSTR("STARTING_DATE",1,6)<='201103' AND SUBSTR("STARTING_DATE",1,6)>='201101')
11 - access("SHOP_CODE"='1000' AND "STARTING_DATE">='20110101' AND "STARTING_DATE"<='20110331')
filter(SUBSTR("STARTING_DATE",1,6)<='201103' AND SUBSTR("STARTING_DATE",1,6)>='201101')
14 - filter("STARTING_DATE"<='20110331' AND SUBSTR("STARTING_DATE",1,6)<='201103' AND
SUBSTR("STARTING_DATE",1,6)>='201101' AND "STARTING_DATE">='20110101')
17 - filter("STARTING_DATE"<='20110331' AND SUBSTR("STARTING_DATE",1,6)<='201103' AND
SUBSTR("STARTING_DATE",1,6)>='201101' AND "STARTING_DATE">='20110101')


統計
----------------------------------------------------------
0 recursive calls
0 db block gets
606978 consistent gets
605112 physical reads
0 redo size
875 bytes sent via SQL*Net to client
519 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
8 rows processed

03:43:16 SCOTT>

見えてきましたよね、無駄が。

このクエリ、同じ検索範囲のデータを対象に4回もTEST2表にアクセスしています。全表走査2回、改善したとはいえ2回の全ローカル索引のレンジスキャンを行っています。無駄なアクセスが多すぎます。
こんなタイプのUNION ALLやUNION繰り返しタイプのクエリを改善できる方法は……

まず浮かんだのは、WITH句を使って各クエリの共通部分をまとめてしまう方法です。

WITH句に記述したクエリは最初に1度実行され結果を一時セグメントに溜め込みます。その後、一時セグメントに溜め込んだ結果を使い回せばいいので巨大な表本体を何度も参照する必要がなくなります。
そうそう、うまく使えば、都度使い捨てのマテリアライズドビュー(例えが良くないですが気にしないでね)みたいな使い方ができます。


書き換えのポイントは一番大きな範囲で集計する共通部分を見つけ出してWITH句にまとめてしまうこと!
あとはその結果をうまく使い回すこと!  それだけです。 SQL文も共通部分をWITH句にまとめたことで随分読みやすくなりましたよね。 直感的に読みやすい訳ではないですがね。:)

以下、書き換えた結果…

  1  WITH
2 t01 AS
3 (
4 SELECT
5 SUBSTR(starting_date,1,6) AS month
6 ,CASE
7 WHEN SUBSTR(starting_date,5,2) BETWEEN '04' AND '06' THEN 'Q1'
8 WHEN SUBSTR(starting_date,5,2) BETWEEN '07' AND '09' THEN 'Q2'
9 WHEN SUBSTR(starting_date,5,2) BETWEEN '10' AND '12' THEN 'Q3'
10 WHEN SUBSTR(starting_date,5,2) BETWEEN '01' AND '03' THEN 'Q4'
11 END AS quarter
12 ,shop_code
13 ,SUM(sales_figure) as sales_figure
14 FROM
15 test2
16 WHERE
17 starting_date BETWEEN '20110101' AND '20110331'
18 GROUP BY
19 SUBSTR(starting_date,1,6)
20 ,SUBSTR(starting_date,5,2)
21 ,shop_code
22 ),
23 t02 AS
24 (
25 SELECT
26 month
27 ,quarter
28 ,shop_code
29 ,sales_figure
30 FROM
31 t01
32 WHERE
33 month BETWEEN '201101' AND '201103'
34 AND shop_code = '1000'
35 )
36 SELECT
37 month
38 ,shop_code
39 ,sales_figure
40 FROM
41 (
42 SELECT
43 month
44 ,shop_code
45 ,SUM(sales_figure) AS sales_figure
46 FROM
47 t02
48 GROUP BY
49 month
50 ,shop_code
51 UNION ALL
52 SELECT
53 quarter AS month
54 ,shop_code
55 ,SUM(sales_figure) AS sales_figure
56 FROM
57 t02
58 GROUP BY
59 quarter
60 ,shop_code
61 UNION ALL
62 SELECT
63 month
64 ,'ALL ' AS shop_code
65 ,SUM(sales_figure) AS sales_figure
66 FROM
67 t01
68 GROUP BY
69 month
70 UNION ALL
71 SELECT
72 quarter AS month
73 ,'ALL ' AS shop_code
74 ,SUM(sales_figure) AS salles_figure
75 FROM
76 t01
77 GROUP BY
78 quarter
79 )
80 ORDER BY
81 month
82* ,shop_code

8行が選択されました。

経過: 00:00:08.35

実行計画
----------------------------------------------------------
Plan hash value: 2861358139

--------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
--------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3692 | 118K| 83282 (2)| 00:16:40 | | |
| 1 | TEMP TABLE TRANSFORMATION | | | | | | | |
| 2 | LOAD AS SELECT | SYS_TEMP_0FD9D660A_4A53712A | | | | | | |
| 3 | HASH GROUP BY | | 17550 | 411K| 83172 (2)| 00:16:39 | | |
| 4 | PARTITION HASH ALL | | 394K| 9242K| 83161 (2)| 00:16:38 | 1 | 4 |
|* 5 | TABLE ACCESS FULL | TEST2 | 394K| 9242K| 83161 (2)| 00:16:38 | 1 | 4 |
| 6 | LOAD AS SELECT | SYS_TEMP_0FD9D660B_4A53712A | | | | | | |
|* 7 | VIEW | | 17550 | 497K| 17 (0)| 00:00:01 | | |
| 8 | TABLE ACCESS FULL | SYS_TEMP_0FD9D660A_4A53712A | 17550 | 411K| 17 (0)| 00:00:01 | | |
| 9 | SORT ORDER BY | | 3692 | 118K| 93 (8)| 00:00:02 | | |
| 10 | VIEW | | 3692 | 118K| 92 (7)| 00:00:02 | | |
| 11 | UNION-ALL | | | | | | | |
| 12 | HASH GROUP BY | | 2758 | 68950 | 27 (4)| 00:00:01 | | |
| 13 | VIEW | | 17550 | 428K| 26 (0)| 00:00:01 | | |
| 14 | TABLE ACCESS FULL | SYS_TEMP_0FD9D660B_4A53712A | 17550 | 497K| 26 (0)| 00:00:01 | | |
| 15 | HASH GROUP BY | | 920 | 20240 | 27 (4)| 00:00:01 | | |
| 16 | VIEW | | 17550 | 377K| 26 (0)| 00:00:01 | | |
| 17 | TABLE ACCESS FULL | SYS_TEMP_0FD9D660B_4A53712A | 17550 | 497K| 26 (0)| 00:00:01 | | |
| 18 | HASH GROUP BY | | 13 | 260 | 18 (6)| 00:00:01 | | |
| 19 | VIEW | | 17550 | 342K| 17 (0)| 00:00:01 | | |
| 20 | TABLE ACCESS FULL | SYS_TEMP_0FD9D660A_4A53712A | 17550 | 411K| 17 (0)| 00:00:01 | | |
| 21 | HASH GROUP BY | | 1 | 17 | 18 (6)| 00:00:01 | | |
| 22 | VIEW | | 17550 | 291K| 17 (0)| 00:00:01 | | |
| 23 | TABLE ACCESS FULL | SYS_TEMP_0FD9D660A_4A53712A | 17550 | 411K| 17 (0)| 00:00:01 | | |
--------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

5 - filter("STARTING_DATE"<='20110331' AND SUBSTR("STARTING_DATE",1,6)<='201103' AND
SUBSTR("STARTING_DATE",1,6)>='201101' AND "STARTING_DATE">='20110101')
7 - filter("MONTH">='201101' AND "MONTH"<='201103' AND "SHOP_CODE"='1000')


統計
----------------------------------------------------------
4 recursive calls
28 db block gets
302642 consistent gets
302570 physical reads
1156 redo size
875 bytes sent via SQL*Net to client
519 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
8 rows processed

04:15:55 SCOTT>

アクセスしているブロック数は約1/2に減少し処理時間も20秒台から8秒台へ改善することができました。バンザーイ!w

ついでなので、オラクル任せのパラレルクエリだとどうなるか試してみました。(CPUたくさんあるんでw)
アクセスブロック数は少々増えますが、パラレルの良さが出ています。2秒台になりましたー。しかしーw 、影響が大きいのでこのときは参考出品で、ここまでできるよーって話のネタだけにしときました :)

  1  WITH
2 t01 AS
3 (
4 SELECT
5 SUBSTR(starting_date,1,6) AS month
6 ,CASE
7 WHEN SUBSTR(starting_date,5,2) BETWEEN '04' AND '06' THEN 'Q1'
8 WHEN SUBSTR(starting_date,5,2) BETWEEN '07' AND '09' THEN 'Q2'
9 WHEN SUBSTR(starting_date,5,2) BETWEEN '10' AND '12' THEN 'Q3'
10 WHEN SUBSTR(starting_date,5,2) BETWEEN '01' AND '03' THEN 'Q4'
11 END AS quarter
12 ,shop_code
13 ,SUM(sales_figure) as sales_figure
14 FROM
15 test2
16 WHERE
17 starting_date BETWEEN '20110101' AND '20110331'
18 GROUP BY
19 SUBSTR(starting_date,1,6)
20 ,SUBSTR(starting_date,5,2)
21 ,shop_code
22 ),
23 t02 AS
24 (
25 SELECT
26 month
27 ,quarter
28 ,shop_code
29 ,sales_figure
30 FROM
31 t01
32 WHERE
33 month BETWEEN '201101' AND '201103'
34 AND shop_code = '1000'
35 )
36 SELECT /*+ PARALLEL */
37 month
38 ,shop_code
39 ,sales_figure
40 FROM
41 (
42 SELECT
43 month
44 ,shop_code
45 ,SUM(sales_figure) AS sales_figure
46 FROM
47 t02
48 GROUP BY
49 month
50 ,shop_code
51 UNION ALL
52 SELECT
53 quarter AS month
54 ,shop_code
55 ,SUM(sales_figure) AS sales_figure
56 FROM
57 t02
58 GROUP BY
59 quarter
60 ,shop_code
61 UNION ALL
62 SELECT
63 month
64 ,'ALL ' AS shop_code
65 ,SUM(sales_figure) AS sales_figure
66 FROM
67 t01
68 GROUP BY
69 month
70 UNION ALL
71 SELECT
72 quarter AS month
73 ,'ALL ' AS shop_code
74 ,SUM(sales_figure) AS salles_figure
75 FROM
76 t01
77 GROUP BY
78 quarter
79 )
80 ORDER BY
81 month
82* ,shop_code

8行が選択されました。

経過: 00:00:02.98

実行計画
----------------------------------------------------------
Plan hash value: 1065177875

-------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | TQ |IN-OUT| PQ Distrib |
-------------------------------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3692 | 118K| 5787 (2)| 00:01:10 | | | | | |
| 1 | TEMP TABLE TRANSFORMATION | | | | | | | | | | |
| 2 | PX COORDINATOR | | | | | | | | | | |
| 3 | PX SEND QC (RANDOM) | :TQ10001 | 17550 | 411K| 5772 (2)| 00:01:10 | | | Q1,01 | P->S | QC (RAND) |
| 4 | LOAD AS SELECT | SYS_TEMP_0FD9D6626_4A53712A | | | | | | | Q1,01 | PCWP | |
| 5 | HASH GROUP BY | | 17550 | 411K| 5772 (2)| 00:01:10 | | | Q1,01 | PCWP | |
| 6 | PX RECEIVE | | 17550 | 411K| 5772 (2)| 00:01:10 | | | Q1,01 | PCWP | |
| 7 | PX SEND HASH | :TQ10000 | 17550 | 411K| 5772 (2)| 00:01:10 | | | Q1,00 | P->P | HASH |
| 8 | HASH GROUP BY | | 17550 | 411K| 5772 (2)| 00:01:10 | | | Q1,00 | PCWP | |
| 9 | PX BLOCK ITERATOR | | 394K| 9242K| 5770 (2)| 00:01:10 | 1 | 4 | Q1,00 | PCWC | |
|* 10 | TABLE ACCESS FULL | TEST2 | 394K| 9242K| 5770 (2)| 00:01:10 | 1 | 4 | Q1,00 | PCWP | |
| 11 | PX COORDINATOR | | | | | | | | | | |
| 12 | PX SEND QC (RANDOM) | :TQ20000 | 17550 | 497K| 2 (0)| 00:00:01 | | | Q2,00 | P->S | QC (RAND) |
| 13 | LOAD AS SELECT | SYS_TEMP_0FD9D6627_4A53712A | | | | | | | Q2,00 | PCWP | |
|* 14 | VIEW | | 17550 | 497K| 2 (0)| 00:00:01 | | | Q2,00 | PCWP | |
| 15 | PX BLOCK ITERATOR | | 17550 | 411K| 2 (0)| 00:00:01 | | | Q2,00 | PCWC | |
| 16 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6626_4A53712A | 17550 | 411K| 2 (0)| 00:00:01 | | | Q2,00 | PCWP | |
| 17 | PX COORDINATOR | | | | | | | | | | |
| 18 | PX SEND QC (ORDER) | :TQ30005 | 3692 | 118K| 13 (39)| 00:00:01 | | | Q3,05 | P->S | QC (ORDER) |
| 19 | SORT ORDER BY | | 3692 | 118K| 13 (39)| 00:00:01 | | | Q3,05 | PCWP | |
| 20 | PX RECEIVE | | 3692 | 118K| 12 (34)| 00:00:01 | | | Q3,05 | PCWP | |
| 21 | PX SEND RANGE | :TQ30004 | 3692 | 118K| 12 (34)| 00:00:01 | | | Q3,04 | P->P | RANGE |
| 22 | BUFFER SORT | | 3692 | 118K| | | | | Q3,04 | PCWP | |
| 23 | VIEW | | 3692 | 118K| 12 (34)| 00:00:01 | | | Q3,04 | PCWP | |
| 24 | UNION-ALL | | | | | | | | Q3,04 | PCWP | |
| 25 | HASH GROUP BY | | 2758 | 68950 | 3 (34)| 00:00:01 | | | Q3,04 | PCWP | |
| 26 | PX RECEIVE | | 2758 | 68950 | 3 (34)| 00:00:01 | | | Q3,04 | PCWP | |
| 27 | PX SEND HASH | :TQ30000 | 2758 | 68950 | 3 (34)| 00:00:01 | | | Q3,00 | P->P | HASH |
| 28 | HASH GROUP BY | | 2758 | 68950 | 3 (34)| 00:00:01 | | | Q3,00 | PCWP | |
| 29 | VIEW | | 17550 | 428K| 2 (0)| 00:00:01 | | | Q3,00 | PCWP | |
| 30 | PX BLOCK ITERATOR | | 17550 | 497K| 2 (0)| 00:00:01 | | | Q3,00 | PCWC | |
| 31 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6627_4A53712A | 17550 | 497K| 2 (0)| 00:00:01 | | | Q3,00 | PCWP | |
| 32 | HASH GROUP BY | | 920 | 20240 | 3 (34)| 00:00:01 | | | Q3,04 | PCWP | |
| 33 | PX RECEIVE | | 920 | 20240 | 3 (34)| 00:00:01 | | | Q3,04 | PCWP | |
| 34 | PX SEND HASH | :TQ30001 | 920 | 20240 | 3 (34)| 00:00:01 | | | Q3,01 | P->P | HASH |
| 35 | HASH GROUP BY | | 920 | 20240 | 3 (34)| 00:00:01 | | | Q3,01 | PCWP | |
| 36 | VIEW | | 17550 | 377K| 2 (0)| 00:00:01 | | | Q3,01 | PCWP | |
| 37 | PX BLOCK ITERATOR | | 17550 | 497K| 2 (0)| 00:00:01 | | | Q3,01 | PCWC | |
| 38 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6627_4A53712A | 17550 | 497K| 2 (0)| 00:00:01 | | | Q3,01 | PCWP | |
| 39 | HASH GROUP BY | | 13 | 260 | 3 (34)| 00:00:01 | | | Q3,04 | PCWP | |
| 40 | PX RECEIVE | | 13 | 260 | 3 (34)| 00:00:01 | | | Q3,04 | PCWP | |
| 41 | PX SEND HASH | :TQ30002 | 13 | 260 | 3 (34)| 00:00:01 | | | Q3,02 | P->P | HASH |
| 42 | HASH GROUP BY | | 13 | 260 | 3 (34)| 00:00:01 | | | Q3,02 | PCWP | |
| 43 | VIEW | | 17550 | 342K| 2 (0)| 00:00:01 | | | Q3,02 | PCWP | |
| 44 | PX BLOCK ITERATOR | | 17550 | 411K| 2 (0)| 00:00:01 | | | Q3,02 | PCWC | |
| 45 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6626_4A53712A | 17550 | 411K| 2 (0)| 00:00:01 | | | Q3,02 | PCWP | |
| 46 | HASH GROUP BY | | 1 | 17 | 3 (34)| 00:00:01 | | | Q3,04 | PCWP | |
| 47 | PX RECEIVE | | 1 | 17 | 3 (34)| 00:00:01 | | | Q3,04 | PCWP | |
| 48 | PX SEND HASH | :TQ30003 | 1 | 17 | 3 (34)| 00:00:01 | | | Q3,03 | P->P | HASH |
| 49 | HASH GROUP BY | | 1 | 17 | 3 (34)| 00:00:01 | | | Q3,03 | PCWP | |
| 50 | VIEW | | 17550 | 291K| 2 (0)| 00:00:01 | | | Q3,03 | PCWP | |
| 51 | PX BLOCK ITERATOR | | 17550 | 411K| 2 (0)| 00:00:01 | | | Q3,03 | PCWC | |
| 52 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6626_4A53712A | 17550 | 411K| 2 (0)| 00:00:01 | | | Q3,03 | PCWP | |
-------------------------------------------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

10 - filter("STARTING_DATE"<='20110331' AND SUBSTR("STARTING_DATE",1,6)<='201103' AND SUBSTR("STARTING_DATE",1,6)>='201101' AND
"STARTING_DATE">='20110101')
14 - filter("MONTH">='201101' AND "MONTH"<='201103' AND "SHOP_CODE"='1000')

Note
-----
- automatic DOP: Computed Degree of Parallelism is 16


統計
----------------------------------------------------------
348 recursive calls
5435 db block gets
318993 consistent gets
309118 physical reads
310176 redo size
875 bytes sent via SQL*Net to client
519 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
33 sorts (memory)
0 sorts (disk)
8 rows processed

04:31:33 SCOTT>

パラレルクエリの話は一旦横に置いといて(月単位のレンジパーティションならもっと良い結果がでそうですがそれはまた別途ということで…


WITH句以外にもGROUPING SETも効果がありそうではあります。次回は、それらを試して結果を比較してみようかと…。

つづく。


これまでのあらずじ…

いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #1
いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #2
いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #3
いろいろと面倒くさい大人の事情縛りのOracleパフォーマンスチューニング #4

| | コメント (0) | トラックバック (0)

2011年2月17日 (木)

shutdown immeidateしない、ほかの理由に遭遇! おまけのおまけ(でた〜最近、よくあるパターンw)

さて、前回のおまけで終了〜。 のつもりだったがリスナー経由の時は問題ないな〜と気づいて気が変わり。おまけのおまけとなりましたw


前回まではBEQで繋いでたな〜、と思ってリスナー経由の専用サーバー接続で同じことを試してみたらshutdown immeidateが待機させられない事に気づいた。

お〜〜〜〜っ。oracleのサーバープロセスがdefunctにならないっつーことは…

ということで、早速試してみた。

※1つめの端末でSQL*Plusを起動してOracleをスタートアップ(なお事前にリスナーは起動済みです)

[oracle@lampeye ˜]$ sqlplus /nolog

SQL*Plus: Release 11.1.0.7.0 - Production on 水 2月 16 23:10:11 2011

Copyright (c) 1982, 2008, Oracle. All rights reserved.

23:10:11 > conn / as sysdba
接続されました。
23:21:54 SYS> startup
ORACLEインスタンスが起動しました。

Total System Global Area 1603411968 bytes
Fixed Size 2160112 bytes
Variable Size 436210192 bytes
Database Buffers 1157627904 bytes
Redo Buffers 7413760 bytes
データベースがマウントされました。
データベースがオープンされました。
23:22:04 SYS>

※2つめの端末でSQL*Plusを起動してリスナー経由(この例では専用サーバー接続)でOracleへ接続後、host command(!)でshellへ入っておく。

[oracle@lampeye ˜]$ 
[oracle@lampeye ˜]$ sqlplus /nolog

SQL*Plus: Release 11.1.0.7.0 - Production on 水 2月 16 23:22:45 2011

Copyright (c) 1982, 2008, Oracle. All rights reserved.

23:22:45 > conn scott/tiger@lampeye
接続されました。
23:22:53 SCOTT> !
[oracle@lampeye ˜]$

※この状態で、プロセスツリーをチェックしてみると…Bequeath Protocol接続の時は、PID=5398の子プロセスとしてOracleのサーバープロセスがforkされていたのに、居ないのよ…

[oracle@lampeye ˜]$ ps -ef | grep gnome-terminal
oracle 4976 1 0 23:08 ? 00:00:01 gnome-terminal
oracle 5440 5031 0 23:23 pts/3 00:00:00 grep gnome-terminal
[oracle@lampeye ˜]$
[oracle@lampeye ˜]$ pstree -p 4976 -ual
gnome-terminal,4976,oracle
├─bash,4982
│ └─sqlplus,5154
│ └─oracle,5376 (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))
├─bash,5007
│ └─sqlplus,5398
│ └─bash,5413
├─bash,5031
│ └─pstree,5441 -p 4976 -ual
├─bash,5161
├─gnome-pty-helpe,4981
└─{gnome-terminal},4983
[oracle@lampeye ˜]$

※じゃ、どこに行ったのよ…と、調べてみると…リスナー経由だとサーバープロセスの親プロセスはINIT

23:29:17 SYS> select s.username,p.username,p.spid from v$process p join v$session s on p.addr = s.paddr where s.username='SCOTT'

USERNAME USERNAME SPID
------------------------------ --------------- ------------------------
SCOTT oracle 5400

経過: 00:00:00.01
23:29:18 SYS>

[oracle@lampeye ˜]$ ps -f -p 5400
UID PID PPID C STIME TTY TIME CMD
oracle 5400 1 0 23:22 ? 00:00:00 oraclelampeye (LOCAL=NO)
[oracle@lampeye ˜]$

※これならshutdown immeidateは待たされずに実行される!

23:35:22 SYS> 
23:35:22 SYS> shutdown immediate
データベースがクローズされました。
データベースがディスマウントされました。
ORACLEインスタンスがシャットダウンされました。
23:35:33 SYS>

ということは、SQL*PlusからBequeath Protocol接続の場合、host commandでshellへ入ったままにしているとshutdown immeidateが待機させられるのな…


じゃ、sqlnet.ora に BEQUEATH_DETACH=yes を設定すれば回避できそーな気がする
Oracle Database Net Servicesリファレンス 11g リリース1(11.1)- 5.2.1 BEQUEATH_DETACH

早速、検証…

sqlnet.oraにBEQUEATH_DETACH=yesを追記。

[oracle@lampeye ˜]$ 
[oracle@lampeye ˜]$ cat $ORACLE_HOME/network/admin/sqlnet.ora
# sqlnet.ora Network Configuration File: /opt/u01/app/oracle/product/11.1.0/db_1/network/admin/sqlnet.ora
# Generated by Oracle configuration tools.

NAMES.DIRECTORY_PATH= (TNSNAMES, EZCONNECT)
BEQUEATH_DETACH=yes

[oracle@lampeye ˜]$

※1つめの端末でSQL*Plusを起動し、Oracleをstartup…

[oracle@lampeye ˜]$ sqlplus /nolog

SQL*Plus: Release 11.1.0.7.0 - Production on 水 2月 16 23:39:14 2011

Copyright (c) 1982, 2008, Oracle. All rights reserved.

23:39:14 > conn / as sysdba
アイドル・インスタンスに接続しました。
23:39:17 SYS> startup
ORACLEインスタンスが起動しました。

Total System Global Area 1603411968 bytes
Fixed Size 2160112 bytes
Variable Size 436210192 bytes
Database Buffers 1157627904 bytes
Redo Buffers 7413760 bytes
データベースがマウントされました。
データベースがオープンされました。
23:39:26 SYS>


※2つめの端末でSQL*Plusを起動、BEQ接続でSCOTTユーザへ接続後、host command(!)でshellへ入っておく…

[oracle@lampeye ˜]$ sqlplus /nolog

SQL*Plus: Release 11.1.0.7.0 - Production on 水 2月 16 23:39:39 2011

Copyright (c) 1982, 2008, Oracle. All rights reserved.

23:39:39 > conn scott/tiger
接続されました。
23:39:45 SCOTT> !
[oracle@lampeye ˜]$


※この状態でプロセスツリーを見てみると…お〜〜〜、SQL*Plusの子プロセスではなくなっている…

[oracle@lampeye ˜]$ pstree -p 4976 -ual 
gnome-terminal,4976,oracle
├─bash,4982
│ └─sqlplus,5596
├─bash,5007
│ └─sqlplus,5664
│ └─bash,5686
├─bash,5031
│ └─pstree,5711 -p 4976 -ual
├─bash,5161
├─gnome-pty-helpe,4981
└─{gnome-terminal},4983
[oracle@lampeye ˜]$

※じゃ〜、どこの子になっちゃったのか調べてみましょう…

23:41:08 SYS> select s.username,p.username,p.spid from v$process p join v$session s on p.addr = s.paddr where s.username IN ('SYS','SCOTT');

USERNAME USERNAME SPID
------------------------------ --------------- ------------------------
SYS oracle 5685
SCOTT oracle 5666

経過: 00:00:00.03
23:41:40 SYS>

お〜、やはり、SQL*Plusの子じゃなくて、INITの養子となってしまったようですw

[oracle@lampeye ˜]$ ps -f -p 5685 5666
UID PID PPID C STIME TTY STAT TIME CMD
oracle 5666 1 0 23:39 ? Ss 0:00 oraclelampeye (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))
oracle 5685 1 0 23:40 ? Ss 0:00 oraclelampeye (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))
[oracle@lampeye ˜]$

これなら、shutdown immeidateも待たされないでしょうね :)

23:42:52 SYS> shutdown immediate
データベースがクローズされました。
データベースがディスマウントされました。
ORACLEインスタンスがシャットダウンされました。
23:43:07 SYS>

immeidateしない、ほかの理由に遭遇! ネタはこれで、ほんとにほんとのおしまい :)


shutdown immeidateしない、ほかの理由に遭遇!
shutdown immeidateしない、ほかの理由に遭遇! #2
shutdown immeidateしない、ほかの理由に遭遇! #3
shutdown immeidateしない、ほかの理由に遭遇! おまけ

| | コメント (0) | トラックバック (0)

2011年2月10日 (木)

shutdown immeidateしない、ほかの理由に遭遇! おまけ

前回までで状況も把握できたし、そうなった場合の回避策も見えたのですが、子プロセスの生成とかdefunctなゾンピ君の刈り取りってどーなってんだろーと気になり…

子プロセスの生成状況を以下の順で見てみる…

  1. shellに入っただけ
  2. SQL*Plus起動
  3. SCOTTユーザへ接続
  4. host command(!)でshellへ入る


shellに入っただけ

[oracle@pleco ˜]$ 
[oracle@pleco ˜]$

[oracle@pleco ˜]$ 
[oracle@pleco ˜]$ ps -e -u oracle | grep gnome-terminal
3337 ? 00:00:09 gnome-terminal
[oracle@pleco ˜]$
[oracle@pleco ˜]$ pstree -p 3337 -u
gnome-terminal(3337,oracle)─┬─bash(3377)
├─bash(3737)───pstree(4063)
├─gnome-pty-helpe(3342)
└─{gnome-terminal}(3344)


SQL*Plus起動

[oracle@pleco ˜]$ 
[oracle@pleco ˜]$
[oracle@pleco ˜]$ sqlplus /nolog

SQL*Plus: Release 11.1.0.7.0 - Production on 木 2月 10 14:54:44 2011

Copyright (c) 1982, 2008, Oracle. All rights reserved.

14:54:44 >

[oracle@pleco ˜]$ 
[oracle@pleco ˜]$ pstree -p 3337 -u
gnome-terminal(3337,oracle)─┬─bash(3377)───sqlplus(4064)
├─bash(3737)───pstree(4066)
├─gnome-pty-helpe(3342)
└─{gnome-terminal}(3344)


SCOTTユーザへ接続

[oracle@pleco ˜]$ 
[oracle@pleco ˜]$
[oracle@pleco ˜]$ sqlplus /nolog

SQL*Plus: Release 11.1.0.7.0 - Production on 木 2月 10 14:54:44 2011

Copyright (c) 1982, 2008, Oracle. All rights reserved.

14:54:44 > conn scott/tiger
接続されました。
14:54:57 SCOTT>

scottユーザに接続した状態…
このようにSQL*Plusの子プロセスが1つであればshutdown immeidateが待機させられることはないんだけど…ね。
[oracle@pleco ˜]$ 
[oracle@pleco ˜]$ pstree -p 3337 -u
gnome-terminal(3337,oracle)─┬─bash(3377)───sqlplus(4064)───oracle(4067)
├─bash(3737)───pstree(4068)
├─gnome-pty-helpe(3342)
└─{gnome-terminal}(3344)


host command(!)でshellに入った

[oracle@pleco ˜]$ 
[oracle@pleco ˜]$
[oracle@pleco ˜]$ sqlplus /nolog

SQL*Plus: Release 11.1.0.7.0 - Production on 木 2月 10 14:54:44 2011

Copyright (c) 1982, 2008, Oracle. All rights reserved.

14:54:44 > conn scott/tiger
接続されました。
14:54:57 SCOTT> !
[oracle@pleco ˜]$

SQL*Plusからホストコマンド(!)でshellに入った状態…
SQL*Plusの子プロセスが複数でoracle以外のがある状態で、他のSQL*Plusからshutdown immediateを実行されちゃうと、以下にあるpid=4067が<defunct>状態のまま刈り取られない。===>Oracleがshutdown immeidateで停止しない。ってことになるのな。
[oracle@pleco ˜]$ 
[oracle@pleco ˜]$ pstree -p 3337 -u
gnome-terminal(3337,oracle)─┬─bash(3377)───sqlplus(4064)─┬─bash(4069)
└─oracle(4067)
├─bash(3737)───pstree(4093)
├─gnome-pty-helpe(3342)
└─{gnome-terminal}(3344)
[oracle@pleco ˜]$
[oracle@pleco ˜]$

じゃ、実験!

以下のようにshutdown immeidateが待機させられている状態を作る。赤字(pid=3627)の子プロセスがdefunctつまりゾンビになるわけね。

shutdown immeidateを実行するSQL*Plusとは別にSQL*Plusを起動し、host command(!)でshellに入っておきます…

16:09:28 > conn scott/tiger
接続されました。
16:12:45 SCOTT> !
[oracle@pleco ˜]$

[oracle@pleco ˜]$ pstree -p 3372 -u
gnome-terminal(3372,oracle)─┬─bash(3378)───sqlplus(3493)─┬─bash(3628)
└─oracle(3627)
├─bash(3403)───sqlplus(3427)───oracle(3599)
├─bash(3520)───pstree(3672)
├─gnome-pty-helpe(3377)
└─{gnome-terminal}(3379)

この状態で、もう一つのSQL*Plusからsysユーザでshutdown immeidateを実行します…shutdown immeidateは待機させられます。
この時、pid=3627の子プロセスはdefunct状態になってますが、刈り取られていません。この影響でshutdown immediateが待機させられています。
SQL*Plusからshellに入っていない場合、つまり、SQL*Plusのプロセス(pid=3493)の子プロセスが1つしかない場合は、shutdown immeidateが待機させられることはない…この辺りに問題がありそうな気がします…

16:12:59 SYS> 
16:12:59 SYS>
16:13:00 SYS> shutdown immediate

[oracle@pleco ˜]$ pstree -p 3372 -u
gnome-terminal(3372,oracle)─┬─bash(3378)───sqlplus(3493)─┬─bash(3628)
└─oracle(3627)
├─bash(3403)───sqlplus(3427)───oracle(3599)
├─bash(3520)───pstree(3672)
├─gnome-pty-helpe(3377)
└─{gnome-terminal}(3379)

試しに親プロセスであるSQL*Plus(pid=3493)にSIGCHLDシグナルを送ってみましょう。
[oracle@pleco ˜]$ kill -SIGCHLD 3493
[oracle@pleco ˜]$ kill -SIGCHLD 3493
[oracle@pleco ˜]$ kill -SIGCHLD 3493
[oracle@pleco ˜]$ kill -SIGCHLD 3493
[oracle@pleco ˜]$ kill -SIGCHLD 3493
・・・・以下略w・・・・

ん〜〜〜〜〜。ゾンビを刈り取ってくれません><

試しにshellからexitしてみます…

16:09:28 > conn scott/tiger
接続されました。
16:12:45 SCOTT> !
[oracle@pleco ˜]$ exit
exit

16:18:24 SCOTT>
[oracle@pleco ˜]$ pstree -p 3372 -u
gnome-terminal(3372,oracle)─┬─bash(3378)───sqlplus(3493)───oracle(3627)
├─bash(3403)───sqlplus(3427)───oracle(3599)
├─bash(3520)───pstree(3673)
├─gnome-pty-helpe(3377)
└─{gnome-terminal}(3379)

shellからはexitしました。SQL*Plus(pid=3493)の子プロセスがoracleだけ(pid=3627)のゾンビだけになりました。oracleのゾンビ(pid=3627)が残っているうちはshutdown immeidateは待機させられたままです! 

では、もう一回、親プロセスであるSQL*PlusにSIGCHLDシグナルを送ってみましょう! 今度はうまく行きそうな気がします!

[oracle@pleco ˜]$ kill -SIGCHLD 3493
[oracle@pleco ˜]$ pstree -p 3372 -u
gnome-terminal(3372,oracle)─┬─bash(3378)───sqlplus(3493)
├─bash(3403)───sqlplus(3427)───oracle(3599)
├─bash(3520)───pstree(3675)
├─gnome-pty-helpe(3377)
└─{gnome-terminal}(3379)
[oracle@pleco ˜]$

やった〜〜〜〜〜〜 :) SQL*Plus(pid=3493)の子プロセス(pid=3627)のゾンビが見事に刈り取られました!

その瞬間……待機させられていたshutdown immeidateは見事終了!!!!

16:12:59 SYS> 
16:12:59 SYS>
16:13:00 SYS> shutdown immediate
データベースがクローズされました。
データベースがディスマウントされました。
ORACLEインスタンスがシャットダウンされました。
16:18:42 SYS>


shutdown immeidateしない、ほかの理由に遭遇! ネタはこれにて :)




shutdown immeidateしない、ほかの理由に遭遇!
shutdown immeidateしない、ほかの理由に遭遇! #2
shutdown immeidateしない、ほかの理由に遭遇! #3
shutdown immeidateしない、ほかの理由に遭遇! おまけ

| | コメント (0) | トラックバック (0)

2011年2月 9日 (水)

shutdown immeidateしない、ほかの理由に遭遇! #3

もう一つ検証し忘れてた!。

この現象に気づいたとき、SQL*Plusから接続していたユーザがsysユーザや、systemユーザだけだったので、それ以外のユーザで接続している場合は大丈夫なんじゃね?都市伝説の検証…

これまでと同様に2つのSQL*Plusを起動しておきます。

1つめのSQL*Plusでは、sysユーザに接続しておきます…

[oracle@leaffish ˜]$ sqlplus /nolog

SQL*Plus: Release 11.2.0.1.0 Production on 水 2月 9 07:26:10 2011

Copyright (c) 1982, 2009, Oracle. All rights reserved.

07:26:10 > conn / as sysdba
接続されました。


2つめのSQL*Plusでは、scottユーザ(sysユーザ、systemユーザ以外の一般ユーザ)に接続し、host command(!)でshellに入ったままにしておきます…

[oracle@leaffish ˜]$ sqlplus /nolog

SQL*Plus: Release 11.2.0.1.0 Production on 水 2月 9 07:26:23 2011

Copyright (c) 1982, 2009, Oracle. All rights reserved.

07:26:23 > conn scott/tiger
接続されました。
07:26:29 SCOTT> !
[oracle@leaffish ˜]$


では、sysユーザでshutdown immeidateを実行してみます…

07:26:10 > conn / as sysdba
接続されました。
07:26:16 SYS>
07:26:16 SYS>
07:26:17 SYS> shutdown immediate

お〜〜〜、shutdown immeidateが待機させられています。

「SQL*Plusから接続していたユーザがsysユーザや、systemユーザだけだったので、それ以外のユーザで接続している場合は大丈夫なんじゃね?都市伝説」は都市伝説
Oracleへ接続するユーザに関係なく、SQL*Plusからhost command(!)でshellに入ったままのセッションがある状態で他のセッションからshutdown immeidateを実行した場合、shutdown immeidateは、shutdown timeoutせずにshutdownを待機し続けるのは事実。

まとめると…

現象:

  • shutdown immeidate文を実行したがshutdown timeout(1時間)も発生せずshutdownが待機させれれたままになり停止できない。


発生条件(Updated 16-Feb-2011):

  • Linux/Unix系のOracle11g R2 11.2.0.1.0 (ちなみにそれ以外のリリースでは11.1.0.7.0で同様の現象を確認しています、他のリリースでは未検証。)
  • shutdown immeidateを発行するセッション以外に、SQL*Plusからhost command(! はたま host)でshellに入ったままになっているセッションがある場合。かつ、Bequeath ProtocolでOracleへ接続している。


確認ポイント:

  • アラートログに "SHUTDOWN: Active processes prevent shutdown operation"が繰り返される。
  • ps -ef | grep ora などでプロセスをみると <defunct>な子プロセスがあり、親プロセスがSQL*Plusである。
  • ls -lrt で最後にリストされるトレースファイル(shutdownを実行しているプロセスのトレースファイル)に"ksukia: Attempt <連番?> to re-kill process OS PID=<pid>"のメッセージが繰り返し出力され続ける


対処(Updated 16-Feb-2011):

  • shutdown aboartするしかない。<defunct>なプロセスの親であるSQL*Plusのプロセスをkill -SIGTERMとか-SIGKILLで終了させる。それでもshutdownが待機しているようなら、最後の手段、shutdown abortということで。
    SQL*Plus起動してる人が連絡取れる場所にいるのならその方にexitしてもらうのもありw
  • その他の方法として、sqlnet.oraに、BEQUEATH_DETACH=yes を設定して、サーバープロセスをSQL*Plusの子ではなく、INITの子になってもらう(これがおすすめかも)


現象と回避方法を確認したリリース(Updated 16-Feb-2011):

  • Oracle11g R1 11.1.0.7.0 for Linux (32bit/64bit)
  • Oracle11g R1 11.1.0.7.0 for HP-UX(itanium)
  • Oracle11g R2 11.2.0.1.0 for Linux (32bit/64bit)
  • Oracle11g R2 11.2.0.1.0 for Solaris x86-64

KROWNっぽいまとめ方にしてみました :) (他のUnix系リリースでも作りはおなじでしょうね)

でもさあ、SQL*Plusからホストコマンド、使うんだよね結構。shellに入って、SQL*Plusから入っていたこと忘れて、また、SQL*Plus起動しちゃって…さらにshellに入って…以下繰り返しw。 注意しましょうね。→ 自分。




shutdown immeidateしない、ほかの理由に遭遇!
shutdown immeidateしない、ほかの理由に遭遇! #2
shutdown immeidateしない、ほかの理由に遭遇! #3
shutdown immeidateしない、ほかの理由に遭遇! おまけ

| | コメント (0) | トラックバック (0)

shutdown immeidateしない、ほかの理由に遭遇! #2

さて、昨日のつづきです。

Oracle11g R2 11.2.0.1.0 for Linux x86 をVirtualBox4.0 for MacOS XのCentOS5.5にインストールしてあります。

昨日は、SQL*Plusの!(host command)でshellへ入っている状態、かつ、別端末のSQL*plusからshutdown immeidate文を発行してしまうとSQL*Plusのプロセスの子プロセスに<defunct>なプロセスが登場して、shutdown immeidateを待機させてしまうところまでを再現してみました。

今日は、shutdown immediate文を発行するsysユーザ以外のsysユーザがSQL*Plusから接続しているだけでもshutdown immediateを待機させるんじゃないか?疑惑の確認と、shutdown immeidateの待機させるだけじゃなく、shutdown timeoutも抑止しちゃってるよね疑惑などを検鏡検証してみようと思います。

短期遠征先から帰宅している予定だったのによそーーーーー外の1日延泊となってしまった次いでに、VirtuslBox4.0のCentOS5.5のOracle11g R2でたっぷり検証してみましょうw

では、最初に、shutdown immeidateを実行するsysユーザ以外のsysユーザがSQL*Plusから接続しているだけでも実行に他の端末のSQL*Plusでsysユーザが接続しているだけでもshutdown immeidateを待機させるんじゃないか?疑惑するんじゃね?疑惑の検証から。

まず、SQL*Plusでsysユーザに接続している端末を2つ用意して…

一つめのSQL*Plusで〜す。

[oracle@leaffish ˜]$ 
[oracle@leaffish ˜]$ sqlplus /nolog

SQL*Plus: Release 11.2.0.1.0 Production on 水 2月 9 00:09:00 2011

Copyright (c) 1982, 2009, Oracle. All rights reserved.

00:09:00 > conn / as sysdba
接続されました。
00:09:11 SYS>
00:09:12 SYS>
00:09:12 SYS>

2つめのSQL*Plusで〜す。

[oracle@leaffish ˜]$ 
[oracle@leaffish ˜]$ sqlplus /nolog

SQL*Plus: Release 11.2.0.1.0 Production on 水 2月 9 00:08:39 2011

Copyright (c) 1982, 2009, Oracle. All rights reserved.

00:08:39 > conn / as sysdba
接続されました。
00:08:44 SYS>
00:08:45 SYS>
00:08:45 SYS>

この状態で1つめのSQL*Plusのsysユーザでshutdown immeidate文を実行します…

00:22:43 SYS> 
00:22:43 SYS> shutdown immediate
データベースがクローズされました。
データベースがディスマウントされました。
ORACLEインスタンスがシャットダウンされました。
00:22:57 SYS>

待機させられることなく、shutdown immeidate文が実行されました。Oracle11g R2 11.2.0.1.0 for Linuxでは”疑惑”だけだったようですね。一安心w。他のバージョンだとどうなんだろ=>TODO.
(昨日の記事では、systemユーザがSQL*Plusで接続している場合、他の端末のSQL*Plusのsysユーザがshutdown immeidateを実行した場合の検証もしていましたよね。これでshutdown immeidate文を実行するセッション以外にsysユーザやsystemユーザのセッションが存在していてもshutdown immeidateが待機させられることは、すくなくともOracle11g R2 11.2.0.1.0 for Linuxでは発生しないことは確かなようです。)


つづいて、SQL*Plusのhost command(!)からshellへ入ったままのセッションが存在している状態でshutdown immeidate文を別セッションから実行してしまうとshutdown immediateを待機させるだけでなく、shutdown timeoutも妨害してしまい1時間を経過してもハングしたままじゃね疑惑を検証してみたいと思います。

同じように2つのSQL*Plusを起動し、ともにsysユーザで接続して、一方のセッションではhost command (!)でshellへ入ったままにしておきます。

1つめのSQL*Plusです…

[oracle@leaffish ˜]$ sqlplus /nolog

SQL*Plus: Release 11.2.0.1.0 Production on 水 2月 9 00:36:01 2011

Copyright (c) 1982, 2009, Oracle. All rights reserved.

00:36:01 > conn / as sysdba
接続されました。
00:36:04 SYS>
00:36:04 SYS>

2つめのSQL*Plusです〜、こちらはhost commandでshellへ入っておきます。

[oracle@leaffish ˜]$ sqlplus /nolog

SQL*Plus: Release 11.2.0.1.0 Production on 水 2月 9 00:35:51 2011

Copyright (c) 1982, 2009, Oracle. All rights reserved.

00:35:51 > conn / as sysdba
接続されました。
00:35:54 SYS>
00:35:56 SYS> !
[oracle@leaffish ˜]$
[oracle@leaffish ˜]$

この状態で1つめのSQL*Plusのセッションからshutdown immeidate文を実行してみます…

00:39:34 SYS> 
00:39:34 SYS> shutdown immediate

見事にshutdown immeidateは待機させられます。すばらし〜。
このまま放置してみます。Oracle10g以降の機能であるshutdown timeoutが働いて1時間程度でshutdownはキャンセルされるはずです。しばしの間、ご歓談くださいませ。:)

・・・・・・・・・中略・・・・・・・・・・・

ながらくお待たせいたしました〜、shutdown immeidateを実行してから2時間以上経過しましたが、shutdown timeoutでshutdownがキャンセルされるどころか、止まる気配すらありません…

以下、アラートログの内容です。

Wed Feb 09 00:39:41 2011
Shutting down instance (immediate)
Stopping background process SMCO
Shutting down instance: further logons disabled
Stopping background process QMNC
Stopping background process MMNL
Stopping background process MMON
License high water mark = 2
All dispatchers and shared servers shutdown
Wed Feb 09 00:44:51 2011
SHUTDOWN: Active processes prevent shutdown operation
Wed Feb 09 00:50:05 2011
SHUTDOWN: Active processes prevent shutdown operation
Wed Feb 09 00:55:20 2011
SHUTDOWN: Active processes prevent shutdown operation
Wed Feb 09 01:00:36 2011
SHUTDOWN: Active processes prevent shutdown operation
Wed Feb 09 01:05:48 2011
SHUTDOWN: Active processes prevent shutdown operation
Wed Feb 09 01:10:57 2011
SHUTDOWN: Active processes prevent shutdown operation
Wed Feb 09 01:16:12 2011
SHUTDOWN: Active processes prevent shutdown operation

・・・中略・・・

Wed Feb 09 02:28:17 2011
SHUTDOWN: Active processes prevent shutdown operation
Wed Feb 09 02:33:21 2011
SHUTDOWN: Active processes prevent shutdown operation
Wed Feb 09 02:38:25 2011
SHUTDOWN: Active processes prevent shutdown operation
Wed Feb 09 02:43:28 2011
SHUTDOWN: Active processes prevent shutdown operation
Wed Feb 09 02:48:32 2011
SHUTDOWN: Active processes prevent shutdown operation
Wed Feb 09 02:53:38 2011
SHUTDOWN: Active processes prevent shutdown operation


ということで、「shutdown immeidateを待機させるだけじゃなく、shutdown timeoutも抑止しちゃってるよね!疑惑」は、疑惑じゃなくて真実。


次回へつづく。


shutdown immeidateしない、ほかの理由に遭遇!
shutdown immeidateしない、ほかの理由に遭遇! #2
shutdown immeidateしない、ほかの理由に遭遇! #3
shutdown immeidateしない、ほかの理由に遭遇! おまけ

| | コメント (0) | トラックバック (0)

2011年2月 8日 (火)

shutdown immeidateしない、ほかの理由に遭遇!

別途検証して別エントリにする予定だけど(遠征先で時間ないので…)、この状態でshutdown immeidateが待機するとshutdown timeoutしないというのも特徴みたい…

Oracleのバージョンは11g R2 11.2.0.1.0 for Linux (32bit)だけどUnix/Linux系なら発生するよ、きっと。

そういえば、以前こんなエントリ書いてましたっけ「shutdown timeout

では、早速再現テスト。

まず、SQL*Plusを起動、SYSユーザに接続してOracleインスタンスを起動します…

[oracle@leaffish ˜]$ sqlplus /nolog

SQL*Plus: Release 11.2.0.1.0 Production on 火 2月 8 00:46:11 2011

Copyright (c) 1982, 2009, Oracle. All rights reserved.

00:46:11 > conn / as sysdba
アイドル・インスタンスに接続しました。
00:46:16 SYS> startup
ORACLEインスタンスが起動しました。

Total System Global Area 422670336 bytes
Fixed Size 1336960 bytes
Variable Size 373295488 bytes
Database Buffers 41943040 bytes
Redo Buffers 6094848 bytes
データベースがマウントされました。
データベースがオープンされました。
00:47:17 SYS>


別端末でSQL*Plusを起動してSYSTEMユーザまたはSYSユーザに接続.
(別途詳しく検証する予定だけど、今のところSYSTEM/SYSユーザ以外では発生してないので)

[oracle@leaffish ˜]$ 
[oracle@leaffish ˜]$ sqlplus /nolog

SQL*Plus: Release 11.2.0.1.0 Production on 火 2月 8 00:50:18 2011

Copyright (c) 1982, 2009, Oracle. All rights reserved.

00:50:18 > conn system
パスワードを入力してください:
接続されました。
00:50:23 SYSTEM>


次にOracleを起動したSQL*PlusのSYSユーザでshutdown immeidateを発行する…

00:51:22 SYS> shutdown immediate
データベースがクローズされました。
データベースがディスマウントされました。
ORACLEインスタンスがシャットダウンされました。
00:51:34 SYS>


この状態だとOracleインスタンスは正常にshutdown immeidateで停止できる。あたりまえだけど。

では、再現テストですよん。

では次のパターンはどうか?

前述した手順と同じく、SYSで接続してOracleインスタンスを起動する…

[oracle@leaffish ˜]$ sqlplus /nolog

SQL*Plus: Release 11.2.0.1.0 Production on 火 2月 8 00:54:47 2011

Copyright (c) 1982, 2009, Oracle. All rights reserved.

00:54:47 > conn / as sysdba
アイドル・インスタンスに接続しました。
00:54:52 SYS> startup
ORACLEインスタンスが起動しました。

Total System Global Area 422670336 bytes
Fixed Size 1336960 bytes
Variable Size 373295488 bytes
Database Buffers 41943040 bytes
Redo Buffers 6094848 bytes
データベースがマウントされました。
データベースがオープンされました。
00:55:46 SYS>


前述した手順と同様に、別端末でSQL*Plusを起動し、SYSTEMユーザ(SYSユーザでもいいよ)へ接続する。
さらに、! (SQL*Plusのhost command)でshellに入っておく…。ここがポイント

[oracle@leaffish ˜]$ 
[oracle@leaffish ˜]$
[oracle@leaffish ˜]$ sqlplus /nolog

SQL*Plus: Release 11.2.0.1.0 Production on 火 2月 8 01:01:42 2011

Copyright (c) 1982, 2009, Oracle. All rights reserved.

01:01:42 > conn system
パスワードを入力してください:
接続されました。
01:01:47 SYSTEM> !
[oracle@leaffish ˜]$


shutdow immeidateの待機を再現させますよー、Oracleインスタンスを起動したSQL*PlusのSYSユーザでshutdown immeidate文を発行する…

01:03:04 SYS> 
01:03:05 SYS> shutdown immediate


いつまでたってもOracleインスタンスは停止しない。この例では載せていないがマニュアルに記載されているshutdown timeoutも1時間たっても2時間たっても発生しないようだ…(別途検証予定)


アラートログを確認してみると…5分毎に、”SHUTDOWN: Active processes prevent shutdown operation”というログを出力し続けてる…

Tue Feb 08 01:03:07 2011
Shutting down instance (immediate)
Shutting down instance: further logons disabled
Stopping background process QMNC
Stopping background process MMNL
Stopping background process MMON
License high water mark = 2
All dispatchers and shared servers shutdown
Tue Feb 08 01:08:17 2011
SHUTDOWN: Active processes prevent shutdown operation
Tue Feb 08 01:13:24 2011
SHUTDOWN: Active processes prevent shutdown operation
Tue Feb 08 01:18:31 2011
SHUTDOWN: Active processes prevent shutdown operation
Tue Feb 08 01:23:37 2011
SHUTDOWN: Active processes prevent shutdown operation
Tue Feb 08 01:28:43 2011
SHUTDOWN: Active processes prevent shutdown operation


プロセスのトレースファイルで最新のものでファイルサイズが増えつつけているものがある…
tailでのぞいてみると…

PID=3542のOSプロセスをkillできずにループしているように見える…

[oracle@leaffish trace]$ ll -lrt

・・・中略・・・

-rw-r----- 1 oracle oinstall 61 2月 8 01:00 discus_mman_3483.trm
-rw-r----- 1 oracle oinstall 863 2月 8 01:00 discus_mman_3483.trc
-rw-r----- 1 oracle oinstall 61 2月 8 01:00 discus_dbrm_3477.trm
-rw-r----- 1 oracle oinstall 904 2月 8 01:00 discus_dbrm_3477.trc
-rw-r----- 1 oracle oinstall 45 2月 8 01:01 discus_ora_3539.trm
-rw-r----- 1 oracle oinstall 669 2月 8 01:01 discus_ora_3539.trc
-rw-r----- 1 oracle oinstall 235323 2月 8 01:08 alert_discus.log
-rw-r----- 1 oracle oinstall 6420 2月 8 01:12 discus_ora_3513.trm
-rw-r----- 1 oracle oinstall 60565 2月 8 01:12 discus_ora_3513.trc
[oracle@leaffish trace]$
[oracle@leaffish trace]$ tail -f discus_ora_3513.trc
ksukia: Starting kill, flags = 1
ksukia: killed 0 out of 1 processes.

*** 2011-02-08 01:13:15.641
ksukia: Starting kill, flags = 1
ksukia: killed 0 out of 1 processes.

*** 2011-02-08 01:13:16.663
ksukia: Starting kill, flags = 1
ksukia: killed 0 out of 1 processes.

*** 2011-02-08 01:13:17.678
ksukia: Starting kill, flags = 1
ksukia: Attempt 119 to re-kill process OS PID=3542.
ksukia: killed 1 out of 1 processes.

*** 2011-02-08 01:13:18.699
ksukia: Starting kill, flags = 1
ksukia: killed 0 out of 1 processes.

*** 2011-02-08 01:13:19.709
ksukia: Starting kill, flags = 1
ksukia: killed 0 out of 1 processes.

*** 2011-02-08 01:13:20.735
ksukia: Starting kill, flags = 1
ksukia: killed 0 out of 1 processes.

*** 2011-02-08 01:13:21.750
ksukia: Starting kill, flags = 1
ksukia: killed 0 out of 1 processes.

*** 2011-02-08 01:13:22.756
ksukia: Starting kill, flags = 1
ksukia: Attempt 120 to re-kill process OS PID=3542.
ksukia: killed 1 out of 1 processes.

*** 2011-02-08 01:13:23.779
ksukia: Starting kill, flags = 1
ksukia: killed 0 out of 1 processes.

*** 2011-02-08 01:13:24.790
ksukia: Starting kill, flags = 1
ksukia: killed 0 out of 1 processes.
ksukia: Starting kill, flags = 1
ksukia: killed 0 out of 1 processes.

*** 2011-02-08 01:13:25.821
ksukia: Starting kill, flags = 1
ksukia: killed 0 out of 1 processes.

[oracle@leaffish trace]$

killできないと繰り返しログに吐かれているプロセス PID=3542とは何者?…
psとpstreeコマンドでみてみると…

SQL*Plusの!(host command)でshellに入る生成されるプロセスらしい…、このプロセスSYSTEMユーザやSYSユーザ以外接続している場合はなぜか今のところ生成されいないように見える…

この<defunct>なプロセスは何屋さん? shutdown immediateをimmediateじゃない状態にするのは大量のundoデータだけじゃないのね〜><

それもSQL*Plusの!(host command)は便利なので、私も多用していまして、ついつい、SQL*Plusに接続して、!でshellに入って、SQL*Plusから入ったのを忘れてさらに、SQL*Plus起動して、!でshellに入って…なんてことやってしまうことは多々あります。><

これが原因で、shutdown immeidateが待機させられるなんて〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜><。

[oracle@leaffish ˜]$ ps -ef | grep 3542
oracle 3542 3541 0 01:01 ? 00:00:00 [oracle] <defunct>
oracle 3785 3056 0 01:24 pts/5 00:00:00 grep 3542
[oracle@leaffish ˜]$
[oracle@leaffish ˜]$ pstree -up oracle

・・・中略・・・

gnome-terminal(2806)─┬─bash(2812)───sqlplus(3398)───oracle(3513)
├─bash(2909)───tail(3055)
├─bash(2937)
├─bash(3031)───sqlplus(3541)─┬─bash(3543)
│ └─oracle(3542)
├─bash(3056)───pstree(3772)
├─gnome-pty-helpe(2811)
└─{gnome-terminal}(2813)

・・・以下略・・・


もう少し検証してみましょう! 

shellからだけexitしてみるも……Oracleはまだ停止しない…

01:01:42 > conn system
パスワードを入力してください:
接続されました。
01:01:47 SYSTEM> !
[oracle@leaffish ˜]$ exit
exit

01:30:56 SYSTEM>


じゃ、SQL*Plusからもexitしよう

01:01:42 > conn system
パスワードを入力してください:
接続されました。
01:01:47 SYSTEM> !
[oracle@leaffish ˜]$ exit
exit

01:30:56 SYSTEM> exit
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing optionsとの接続が切断されました。
[oracle@leaffish ˜]$


次の瞬間……

データベースがクローズされました。
データベースがディスマウントされました。
ORACLEインスタンスがシャットダウンされました。
01:32:10 SYS>

なんだと〜〜〜〜〜〜〜〜。いつからこーなんだー。 怖くてSQL*Plusから!(host command)でshellに入れないじゃないか〜〜〜><


次回へつづく。


shutdown immeidateしない、ほかの理由に遭遇!
shutdown immeidateしない、ほかの理由に遭遇! #2
shutdown immeidateしない、ほかの理由に遭遇! #3
shutdown immeidateしない、ほかの理由に遭遇! おまけ

| | コメント (0) | トラックバック (0)

2011年1月29日 (土)

階層問合せか、再帰問合せか、それが問題だ #3 おまけ

階層問合せと再帰問合せを比較するため条件を合わせるという意味でWITH句を利用したが、階層問合せは、再帰問合せと異なりWITH句は必要ないのも有利ですね。

実行計画こそWITH句を利用した場合と変わりまりませんが、階層問合せではWITH句は必須ではないので、WITH句を利用しない階層問合せとWITH句が必須な再帰問合せでは、今のところ、階層問合せの方がPGAの利用サイズが決定的に少ないのは間違いないですね :)

WITH句伴わない階層問合せでPGAサイズを見てみると…

SCOTT> r
1 select
2 empno,
3 ename,
4 job,
5 mgr,
6 level
7 from
8 emp
9 start with
10 mgr is null
11 connect by
12* prior empno = mgr

EMPNO ENAME JOB MGR LEVEL
---------- ---------- --------- ---------- ----------
7839 KING PRESIDENT 1
7566 JONES MANAGER 7839 2
7788 SCOTT ANALYST 7566 3
7876 ADAMS CLERK 7788 4
7902 FORD ANALYST 7566 3
7369 SMITH CLERK 7902 4
7698 BLAKE MANAGER 7839 2
7499 ALLEN SALESMAN 7698 3
7521 WARD SALESMAN 7698 3
7654 MARTIN SALESMAN 7698 3
7844 TURNER SALESMAN 7698 3
7900 JAMES CLERK 7698 3
7782 CLARK MANAGER 7839 2
7934 MILLER CLERK 7782 3

14行が選択されました。

再帰問合せとの差がはっきりでましたね〜 Oracle11g R2では階層問合せでいいかな。再帰問合せはどーゆー場合に有利なんだろ。悩む。

SYS> /

SID NAME VALUE
---------- ------------------------------ ----------
66 session pga memory 672296
66 session pga memory max 672296
66 session uga memory 246552
66 session uga memory max 246552


SYS> /

SID NAME VALUE
---------- ------------------------------ ----------
66 session pga memory 999976
66 session pga memory max 999976
66 session uga memory 377528
66 session uga memory max 377528

SYS>




階層問合せか、再帰問合せか、それが問題だ
階層問合せか、再帰問合せか、それが問題だ #2

| | コメント (0) | トラックバック (0)

2011年1月 6日 (木)

VirtualBox de Oracle11g R2 RAC #23

VirtualBox de Oracle11g R2 RACのつづき。

さて、いよいよVirtualBox de Oracle11g R2 RACの最終回。簡単なTAFのテスト!

  1. ハードウェア構成(VMなのでVMの構成も含めて)、ソフトウェア構成など
  2. Linux (CentOS 5.5 x86_64)のインストール
  3. Openfiler2.3 x86のインストール
  4. Openfiler2.3 x86によるiSCSIボリュームの構成
  5. Oracle RACノードでのiSCSIボリュームの構成 その1その2その3
  6. Oracle所有者、Oracle Grid Infrastructureユーザの作成と関連ディレクトリの作成及び環境変数の設定
  7. Oracle向けLinuxサーバーの構成(カーネルパラメータの設定)
  8. Oracle RACノード間リモートアクセスの構成とntpの構成
    sshの構成は念のために行った、多分、実施しなくても大丈夫だと思うけど…ついでなので、ちょいと意地悪な実験をしてみた)
  9. ローカルネームサーバの構成
  10. Oracle RACノード構成ファイルの確認
  11. Oracle Automatic Storage Management(ASMLib 2.0.5 x84_64)のインストール及び構成
  12. Oracle11g R2 11.2.0.1.0 RACインストール事前作業
  13. Oracle11g R2 11.2.0.1.0 Grid Infrastractureのインストール
  14. Oracle11g R2 11.2.0.1.0 Database softwareのインストール
  15. Oracle11g R2 11.2.0.1.0 examplesのインストール
  16. Oracle Cluster databaseの作成
  17. Net Serviceの確認
  18. Oralce Grid InsfastructureとDatabase構成の確認
  19. Clusterの開始と停止の確認
  20. 簡単なTransparent Application Failover (TAF)の確認

簡単なTransparent Application Failover (TAF)の確認

MacOS X Snow LeopardにあるOracle Instant Client 10g R2 for MacOS Xのtnsnames.oraを編集し以下の定義を追加しておきました!

ORCLTAF =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = discus-rac64-scan.macdeoracle.jp)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = orcl.macdeoracle.info)
(FAILOVER_MODE =
(TYPE = SELECT)
(METHOD = BASIC)
(RETRIES = 180)
(DELAY = 5)
)
)
)

TAF定義の接続識別子で接続します。

discus:˜ oracle$ 
discus:˜ oracle$ sqlplus /nolog

SQL*Plus: Release 10.2.0.4.0 - Production on 木 1月 6 04:47:16 2011

Copyright (c) 1982, 2007, Oracle. All Rights Reserved.

> conn scott/tiger@orcltaf
接続されました。
SCOTT>
SCOTT>
SCOTT> select count(*) from user_objects;

COUNT(*)
----------
0


orcl1インスタンスで、sysユーザで接続し、セッションの状態を確認してみます。

[oracle@discus164 ˜]$ 
[oracle@discus164 ˜]$ sqlplus /nolog

SQL*Plus: Release 11.2.0.1.0 Production on 木 1月 6 04:48:42 2011

Copyright (c) 1982, 2009, Oracle. All rights reserved.

SYS>
SYS>
SYS> conn / as sysdba
接続されました。
SYS>
SYS> select
2 instance_name
3 ,username
4 ,failover_type
5 ,failover_method
6 ,failed_over
7 from
8 gv$session sess join gv$instance inst
9 on sess.inst_id = inst.inst_id
10 where
11 sess.username = 'SCOTT'
12 /

INSTANCE_NAME USERNAME FAILOVER_TYPE FAILOVER_M FAI
---------------- ------------------------------ ------------- ---------- ---
orcl1 SCOTT SELECT BASIC NO

SYS>


SCOTTはorcl1インスタンスに接続されクエリが実行されたようですね!
failoverさせるため、orcl1インスタンスをabortで強制停止してみます。

SYS> !srvctl status database -d orcl
インスタンスorcl1はノードdiscus164で実行中です。
インスタンスorcl2はノードdiscus264で実行中です。

SYS> !srvctl stop instance -d orcl -i orcl1 -o abort
SYS>
SYS> !srvctl status database -d orcl
インスタンスorcl1はノードdiscus164で実行されていません。
インスタンスorcl2はノードdiscus264で実行中です。

SYS>
SYS> l
1 select
2 instance_name
3 ,username
4 ,failover_type
5 ,failover_method
6 ,failed_over
7 from
8 gv$session sess join gv$instance inst
9 on sess.inst_id = inst.inst_id
10 where
11* sess.username = 'SCOTT'
SYS> /
select
*
行1でエラーが発生しました。:
ORA-03135: 接続が失われました
プロセスID: 5563
セッションID: 13、シリアル番号: 25


おっと〜、sysユーザでorcl1インスタンスに接続していたのでした〜。exitしちゃいます。


SCOTTユーザで、failoverさせるためクエリを再実行します。

SCOTT> r
1* select count(*) from user_objects

COUNT(*)
----------
0

SCOTT>


インスタンス:orcl2へ接続し直し確認。お〜うまくいけてますね!
orcl1のセッションだったscottユーザのセッションがfailoverしorcl2のセッションになっています。また今回設定したTAFのモードではクエリはエラーにはならず、生存インスタンスへ透過的にfailoverされます。

[oracle@discus264 ˜]$ 
[oracle@discus264 ˜]$ sqlplus /nolog

SQL*Plus: Release 11.2.0.1.0 Production on 木 1月 6 04:55:48 2011

Copyright (c) 1982, 2009, Oracle. All rights reserved.

> conn / as sysdba
接続されました。
SYS> select
2 instance_name
3 ,username
4 ,failover_type
5 ,failover_method
6 ,failed_over
7 from
8 gv$session sess join gv$instance inst
9 on sess.inst_id = inst.inst_id
10 where
11 sess.username = 'SCOTT'
12 /


INSTANCE_NAME USERNAME FAILOVER_TYPE FAILOVER_M FAI
---------------- ------------------------------ ------------- ---------- ---
orcl2 SCOTT SELECT BASIC YES

SYS>


ちなみにcrsctl status resource -tで確認すると

・・・中略・・・
--------------------------------------------------------------------------------
Cluster Resources
--------------------------------------------------------------------------------
ora.LISTENER_SCAN1.lsnr
1 ONLINE ONLINE discus264
ora.LISTENER_SCAN2.lsnr
1 ONLINE ONLINE discus164
ora.LISTENER_SCAN3.lsnr
1 ONLINE ONLINE discus164
ora.discus164.vip
1 ONLINE ONLINE discus164
ora.discus264.vip
1 ONLINE ONLINE discus264
ora.oc4j
1 OFFLINE OFFLINE
ora.orcl.db
1 OFFLINE OFFLINE Instance Shutdown
2 ONLINE ONLINE discus264 Open
ora.scan1.vip
1 ONLINE ONLINE discus264
ora.scan2.vip
1 ONLINE ONLINE discus164
ora.scan3.vip
1 ONLINE ONLINE discus164
[grid@discus164 ˜]$

となっています。今回のようにデータベースインスタンスだけを停止した場合はこんな状態になるんですね。:)


ついでなので更新トランザクションも試してみましょうかね。
停止したデータベースインスタンスを起動し、scottユーザでupdate文を実行します。

discus:˜ oracle$ 
discus:˜ oracle$ sqlplus scott/tiger@orcltaf

SQL*Plus: Release 10.2.0.4.0 - Production on 木 1月 6 05:20:27 2011

Copyright (c) 1982, 2007, Oracle. All Rights Reserved.

Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP
and Data Mining options
に接続されました。
SCOTT>
SCOTT>
SCOTT> insert into hoge values('abc');

1行が作成されました。

SCOTT>


orcl2インスタンスにsysユーザで接続して状態を確認してみます。
scottユーザはorcl1インスタンスに接続してinsert文を実行したようですね。まだ、failoverしていません。

SYS> 
SYS> l
1 select
2 instance_name
3 ,username
4 ,failover_type
5 ,failover_method
6 ,failed_over
7 from
8 gv$session sess join gv$instance inst
9 on sess.inst_id = inst.inst_id
10 where
11* sess.username = 'SCOTT'
SYS> /

INSTANCE_NAME USERNAME FAILOVER_TYPE FAILOVER_M FAI
---------------- ------------------------------ ------------- ---------- ---
orcl1 SCOTT SELECT BASIC NO


では、先ほどと同じようにorcl1インスタンスを強制停止してみます

SYS> !srvctl stop instance -d orcl -i orcl1 -o abort

SYS>
SYS> !srvctl status database -d orcl
インスタンスorcl1はノードdiscus164で実行されていません。
インスタンスorcl2はノードdiscus264で実行中です。


scottユーザで再度insert文を実行してみました。TAF特有のエラーメッセージが返されましたね。

SCOTT> r
1* insert into hoge values('abc')
insert into hoge values('abc')
*
行1でエラーが発生しました。:
ORA-25402: トランザクションをロールバックしてください。


セッションの状態を確認してみると…セッションはfailoverしています!

SYS> r
1 select
2 instance_name
3 ,username
4 ,failover_type
5 ,failover_method
6 ,failed_over
7 from
8 gv$session sess join gv$instance inst
9 on sess.inst_id = inst.inst_id
10 where
11* sess.username = 'SCOTT'

INSTANCE_NAME USERNAME FAILOVER_TYPE FAILOVER_M FAI
---------------- ------------------------------ ------------- ---------- ---
orcl2 SCOTT SELECT BASIC YES


scottユーザのトランザクションをロールバック後、リトライしてみると…

SCOTT> 
SCOTT> rollback;

ロールバックが完了しました。

SCOTT> insert into hoge values('abc');

1行が作成されました。

SCOTT>
SCOTT>

うまくいきましたね :)


ということで、VirtualBox de Oracle11g R2 RAC for Linux x86_64環境のできあがり〜。(完)






これまでのあらすじ
Mac de Oracle - 10万円未満 de RAC (11g編)#28

VirtualBox de RAC (Oracle11g R1編) #1
VirtualBox de RAC (Oracle11g R1編) #2



VirtualBox de Oracle11g R2 RAC #1
VirtualBox de Oracle11g R2 RAC #2 - 事前調査など…
VirtualBox de Oracle11g R2 RAC #3
VirtualBox de Oracle11g R2 RAC #4
VirtualBox de Oracle11g R2 RAC #5
VirtualBox de Oracle11g R2 RAC #6
VirtualBox de Oracle11g R2 RAC #7
VirtualBox de Oracle11g R2 RAC #8
VirtualBox de Oracle11g R2 RAC #9
VirtualBox de Oracle11g R2 RAC #10
VirtualBox de Oracle11g R2 RAC #11
VirtualBox de Oracle11g R2 RAC #12
VirtualBox de Oracle11g R2 RAC #13
VirtualBox de Oracle11g R2 RAC #14
VirtualBox de Oracle11g R2 RAC #15
VirtualBox de Oracle11g R2 RAC #16
VirtualBox de Oracle11g R2 RAC #17
VirtualBox de Oracle11g R2 RAC #18
VirtualBox de Oracle11g R2 RAC #19
VirtualBox de Oracle11g R2 RAC #20
VirtualBox de Oracle11g R2 RAC #21
VirtualBox de Oracle11g R2 RAC #22




VirtualBox de Oracle11g R2 RAC #16 - 番外編

| | コメント (0) | トラックバック (0)

2011年1月 5日 (水)

VirtualBox de Oracle11g R2 RAC #22

VirtualBox de Oracle11g R2 RACのつづき。

ラス前です :) cluster databaseの起動停止確認。

  1. ハードウェア構成(VMなのでVMの構成も含めて)、ソフトウェア構成など
  2. Linux (CentOS 5.5 x86_64)のインストール
  3. Openfiler2.3 x86のインストール
  4. Openfiler2.3 x86によるiSCSIボリュームの構成
  5. Oracle RACノードでのiSCSIボリュームの構成 その1その2その3
  6. Oracle所有者、Oracle Grid Infrastructureユーザの作成と関連ディレクトリの作成及び環境変数の設定
  7. Oracle向けLinuxサーバーの構成(カーネルパラメータの設定)
  8. Oracle RACノード間リモートアクセスの構成とntpの構成
    sshの構成は念のために行った、多分、実施しなくても大丈夫だと思うけど…ついでなので、ちょいと意地悪な実験をしてみた)
  9. ローカルネームサーバの構成
  10. Oracle RACノード構成ファイルの確認
  11. Oracle Automatic Storage Management(ASMLib 2.0.5 x84_64)のインストール及び構成
  12. Oracle11g R2 11.2.0.1.0 RACインストール事前作業
  13. Oracle11g R2 11.2.0.1.0 Grid Infrastractureのインストール
  14. Oracle11g R2 11.2.0.1.0 Database softwareのインストール
  15. Oracle11g R2 11.2.0.1.0 examplesのインストール
  16. Oracle Cluster databaseの作成
  17. Net Serviceの確認
  18. Oralce Grid InsfastructureとDatabase構成の確認
  19. Clusterの開始と停止の確認
  20. 簡単なTransparent Application Failover (TAF)の確認

Clusterの開始と停止の確認

Grid Infrastructureは自動起動にしてますが、手動起動、停止を確認しておきます。

rootユーザにてcrsctlコマンドでclusterを起動します。データベースインスタンスはOracle所有者でsrvctlコマンドを利用して起動してみます。
(ちなみに、rootユーザには、grid infrastructureのHOMEのbinへパスを通してあります。)

[root@discus164 ˜]# 
[root@discus164 ˜]# crsctl check cluster -all
**************************************************************
discus164:
CRS-4535: Cannot communicate with Cluster Ready Services
CRS-4530: Communications failure contacting Cluster Synchronization Services daemon
CRS-4534: Cannot communicate with Event Manager
**************************************************************
discus264:
CRS-4535: Cannot communicate with Cluster Ready Services
CRS-4530: Communications failure contacting Cluster Synchronization Services daemon
CRS-4534: Cannot communicate with Event Manager
**************************************************************
[root@discus164 ˜]#
[root@discus164 ˜]# crsctl start cluster -all
CRS-2672: 'ora.cssdmonitor'('discus164')の起動を試行しています
CRS-2672: 'ora.cssdmonitor'('discus264')の起動を試行しています
CRS-2676: 'ora.cssdmonitor'('discus264')の起動が成功しました
CRS-2676: 'ora.cssdmonitor'('discus164')の起動が成功しました
CRS-2672: 'ora.cssd'('discus164')の起動を試行しています
CRS-2672: 'ora.cssd'('discus264')の起動を試行しています
CRS-2672: 'ora.diskmon'('discus264')の起動を試行しています
CRS-2672: 'ora.diskmon'('discus164')の起動を試行しています
CRS-2676: 'ora.diskmon'('discus264')の起動が成功しました
CRS-2676: 'ora.diskmon'('discus164')の起動が成功しました
CRS-2676: 'ora.cssd'('discus164')の起動が成功しました
CRS-2676: 'ora.cssd'('discus264')の起動が成功しました
CRS-2672: 'ora.ctssd'('discus164')の起動を試行しています
CRS-2672: 'ora.ctssd'('discus264')の起動を試行しています
CRS-2676: 'ora.ctssd'('discus164')の起動が成功しました
CRS-2672: 'ora.evmd'('discus164')の起動を試行しています
CRS-2676: 'ora.ctssd'('discus264')の起動が成功しました
CRS-2672: 'ora.evmd'('discus264')の起動を試行しています
CRS-2672: 'ora.asm'('discus164')の起動を試行しています
CRS-2672: 'ora.asm'('discus264')の起動を試行しています
CRS-2676: 'ora.evmd'('discus264')の起動が成功しました
CRS-2676: 'ora.evmd'('discus164')の起動が成功しました
CRS-2676: 'ora.asm'('discus164')の起動が成功しました
CRS-2672: 'ora.crsd'('discus164')の起動を試行しています
CRS-2676: 'ora.asm'('discus264')の起動が成功しました
CRS-2672: 'ora.crsd'('discus264')の起動を試行しています
CRS-2676: 'ora.crsd'('discus164')の起動が成功しました
CRS-2676: 'ora.crsd'('discus264')の起動が成功しました
[root@discus164 ˜]#
[root@discus164 ˜]# crsctl check cluster -all
**************************************************************

discus164:
CRS-4535: Cannot communicate with Cluster Ready Services
CRS-4529: Cluster Synchronization Services is online
CRS-4533: Event Manager is online
**************************************************************
discus264:
CRS-4535: Cannot communicate with Cluster Ready Services
CRS-4529: Cluster Synchronization Services is online
CRS-4533: Event Manager is online
**************************************************************
[root@discus164 ˜]#
[root@discus164 ˜]# crsctl status resource -w 'TYPE co ora' -t
--------------------------------------------------------------------------------
NAME TARGET STATE SERVER STATE_DETAILS
--------------------------------------------------------------------------------
Local Resources
--------------------------------------------------------------------------------
ora.CRS.dg
ONLINE ONLINE discus164
ONLINE ONLINE discus264
ora.DATA.dg
OFFLINE OFFLINE discus164
OFFLINE OFFLINE discus264
ora.FRA.dg
OFFLINE OFFLINE discus164
OFFLINE OFFLINE discus264
ora.LISTENER.lsnr
ONLINE ONLINE discus164
ONLINE ONLINE discus264
ora.asm
ONLINE ONLINE discus164 Started
ONLINE ONLINE discus264 Started
ora.eons
ONLINE ONLINE discus164
ONLINE ONLINE discus264
ora.gsd
OFFLINE OFFLINE discus164
OFFLINE OFFLINE discus264
ora.net1.network
ONLINE ONLINE discus164
ONLINE ONLINE discus264
ora.ons
ONLINE ONLINE discus164
ONLINE ONLINE discus264
ora.registry.acfs
ONLINE ONLINE discus164
ONLINE ONLINE discus264
--------------------------------------------------------------------------------
Cluster Resources
--------------------------------------------------------------------------------
ora.LISTENER_SCAN1.lsnr
1 ONLINE ONLINE discus264
ora.LISTENER_SCAN2.lsnr
1 ONLINE ONLINE discus164
ora.LISTENER_SCAN3.lsnr
1 ONLINE ONLINE discus164
ora.discus164.vip
1 ONLINE ONLINE discus164
ora.discus264.vip
1 ONLINE ONLINE discus264
ora.oc4j
1 OFFLINE OFFLINE
ora.orcl.db
1 OFFLINE OFFLINE
2 OFFLINE OFFLINE
ora.scan1.vip
1 ONLINE ONLINE discus264
ora.scan2.vip
1 ONLINE ONLINE discus164
ora.scan3.vip
1 ONLINE ONLINE discus164
[root@discus164 ˜]#

データベースインスタンスを起動します。

[root@discus164 ˜]# su - oracle
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$ srvctl start database -d orcl
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$ srvctl status database -d orcl
インスタンスorcl1はノードdiscus164で実行中です。
インスタンスorcl2はノードdiscus264で実行中です。
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$ exit
logout

[root@discus164 ˜]#
[root@discus164 ˜]# crsctl status resource ora.orcl.db
NAME=ora.orcl.db
TYPE=ora.database.type
TARGET=ONLINE , ONLINE
STATE=ONLINE on discus164, ONLINE on discus264

[root@discus164 ˜]#

起動しましたね :)

最後に、データベースインスタンスは起動したままの状態で、clusterを停止/起動し、再び、データベースインスタンスが起動した状態になるかを確認しておきます。
Oracle Restartってんでしたっけ? この機能。

まず、データベースインスタンスは起動したまま、Grid Infrastructureを停止(全ノードを停止)します。

[root@discus164 ˜]# crsctl stop cluster -all
CRS-2673: 'ora.crsd'('discus164')の停止を試行しています
CRS-2673: 'ora.crsd'('discus264')の停止を試行しています
CRS-2790: 'discus264'上にある、Cluster Ready Services管理下のリソースのシャットダウンを開始しています
CRS-2673: 'ora.LISTENER.lsnr'('discus264')の停止を試行しています
CRS-2790: 'discus164'上にある、Cluster Ready Services管理下のリソースのシャットダウンを開始しています
CRS-2673: 'ora.LISTENER.lsnr'('discus164')の停止を試行しています
CRS-2673: 'ora.LISTENER_SCAN2.lsnr'('discus164')の停止を試行しています
CRS-2673: 'ora.LISTENER_SCAN3.lsnr'('discus164')の停止を試行しています
CRS-2673: 'ora.CRS.dg'('discus164')の停止を試行しています
CRS-2673: 'ora.LISTENER_SCAN1.lsnr'('discus264')の停止を試行しています
CRS-2673: 'ora.orcl.db'('discus164')の停止を試行しています
CRS-2673: 'ora.CRS.dg'('discus264')の停止を試行しています
CRS-2673: 'ora.orcl.db'('discus264')の停止を試行しています
CRS-2673: 'ora.registry.acfs'('discus264')の停止を試行しています
CRS-2673: 'ora.registry.acfs'('discus164')の停止を試行しています
CRS-2677: 'ora.LISTENER.lsnr'('discus264')の停止が成功しました
CRS-2673: 'ora.discus264.vip'('discus264')の停止を試行しています
CRS-2677: 'ora.LISTENER_SCAN1.lsnr'('discus264')の停止が成功しました
CRS-2673: 'ora.scan1.vip'('discus264')の停止を試行しています
CRS-2677: 'ora.discus264.vip'('discus264')の停止が成功しました
CRS-2677: 'ora.scan1.vip'('discus264')の停止が成功しました
CRS-2677: 'ora.LISTENER_SCAN3.lsnr'('discus164')の停止が成功しました
CRS-2673: 'ora.scan3.vip'('discus164')の停止を試行しています
CRS-2677: 'ora.LISTENER.lsnr'('discus164')の停止が成功しました
CRS-2673: 'ora.discus164.vip'('discus164')の停止を試行しています
CRS-2677: 'ora.LISTENER_SCAN2.lsnr'('discus164')の停止が成功しました
CRS-2673: 'ora.scan2.vip'('discus164')の停止を試行しています
CRS-2677: 'ora.scan3.vip'('discus164')の停止が成功しました
CRS-2677: 'ora.discus164.vip'('discus164')の停止が成功しました
CRS-2677: 'ora.scan2.vip'('discus164')の停止が成功しました
CRS-2677: 'ora.registry.acfs'('discus264')の停止が成功しました
CRS-2677: 'ora.registry.acfs'('discus164')の停止が成功しました
CRS-2677: 'ora.CRS.dg'('discus264')の停止が成功しました
CRS-2677: 'ora.CRS.dg'('discus164')の停止が成功しました
CRS-2677: 'ora.orcl.db'('discus264')の停止が成功しました
CRS-2673: 'ora.DATA.dg'('discus264')の停止を試行しています
CRS-2673: 'ora.FRA.dg'('discus264')の停止を試行しています
CRS-2677: 'ora.FRA.dg'('discus264')の停止が成功しました
CRS-2677: 'ora.orcl.db'('discus164')の停止が成功しました
CRS-2673: 'ora.DATA.dg'('discus164')の停止を試行しています
CRS-2673: 'ora.FRA.dg'('discus164')の停止を試行しています
CRS-2677: 'ora.DATA.dg'('discus264')の停止が成功しました
CRS-2673: 'ora.asm'('discus264')の停止を試行しています
CRS-2677: 'ora.asm'('discus264')の停止が成功しました
CRS-2673: 'ora.eons'('discus264')の停止を試行しています
CRS-2673: 'ora.ons'('discus264')の停止を試行しています
CRS-2677: 'ora.DATA.dg'('discus164')の停止が成功しました
CRS-2677: 'ora.ons'('discus264')の停止が成功しました
CRS-2673: 'ora.net1.network'('discus264')の停止を試行しています
CRS-2677: 'ora.net1.network'('discus264')の停止が成功しました
CRS-2677: 'ora.FRA.dg'('discus164')の停止が成功しました
CRS-2673: 'ora.asm'('discus164')の停止を試行しています
CRS-2677: 'ora.asm'('discus164')の停止が成功しました
CRS-2677: 'ora.eons'('discus264')の停止が成功しました
CRS-2792: 'discus264'上にある、Cluster Ready Services管理下のリソースのシャットダウンが完了しました
CRS-2673: 'ora.eons'('discus164')の停止を試行しています
CRS-2673: 'ora.ons'('discus164')の停止を試行しています
CRS-2677: 'ora.crsd'('discus264')の停止が成功しました
CRS-2673: 'ora.cssdmonitor'('discus264')の停止を試行しています
CRS-2673: 'ora.ctssd'('discus264')の停止を試行しています
CRS-2673: 'ora.evmd'('discus264')の停止を試行しています
CRS-2673: 'ora.asm'('discus264')の停止を試行しています
CRS-2677: 'ora.cssdmonitor'('discus264')の停止が成功しました
CRS-2677: 'ora.evmd'('discus264')の停止が成功しました
CRS-2677: 'ora.ctssd'('discus264')の停止が成功しました
CRS-2677: 'ora.asm'('discus264')の停止が成功しました
CRS-2673: 'ora.cssd'('discus264')の停止を試行しています
CRS-2677: 'ora.cssd'('discus264')の停止が成功しました
CRS-2673: 'ora.diskmon'('discus264')の停止を試行しています
CRS-2677: 'ora.diskmon'('discus264')の停止が成功しました
CRS-2675: 'ora.ons'('discus164')の停止に失敗しました
CRS-2679: 'ora.ons'('discus164')のクリーニングを試行しています
CRS-2681: 'ora.ons'('discus164')のクリーニングが成功しました
CRS-2673: 'ora.net1.network'('discus164')の停止を試行しています
CRS-2677: 'ora.net1.network'('discus164')の停止が成功しました
CRS-2677: 'ora.eons'('discus164')の停止が成功しました
CRS-2792: 'discus164'上にある、Cluster Ready Services管理下のリソースのシャットダウンが完了しました
CRS-2677: 'ora.crsd'('discus164')の停止が成功しました
CRS-2673: 'ora.cssdmonitor'('discus164')の停止を試行しています
CRS-2673: 'ora.ctssd'('discus164')の停止を試行しています
CRS-2673: 'ora.evmd'('discus164')の停止を試行しています
CRS-2673: 'ora.asm'('discus164')の停止を試行しています
CRS-2677: 'ora.cssdmonitor'('discus164')の停止が成功しました
CRS-2677: 'ora.evmd'('discus164')の停止が成功しました
CRS-2677: 'ora.asm'('discus164')の停止が成功しました
CRS-2677: 'ora.ctssd'('discus164')の停止が成功しました
CRS-2673: 'ora.cssd'('discus164')の停止を試行しています
CRS-2677: 'ora.cssd'('discus164')の停止が成功しました
CRS-2673: 'ora.diskmon'('discus164')の停止を試行しています
CRS-2677: 'ora.diskmon'('discus164')の停止が成功しました
[root@discus164 ˜]#
[root@discus164 ˜]# crsctl check cluster -all
**************************************************************
discus164:
CRS-4535: Cannot communicate with Cluster Ready Services
CRS-4530: Communications failure contacting Cluster Synchronization Services daemon
CRS-4534: Cannot communicate with Event Manager
**************************************************************
discus264:
CRS-4535: Cannot communicate with Cluster Ready Services
CRS-4530: Communications failure contacting Cluster Synchronization Services daemon
CRS-4534: Cannot communicate with Event Manager
**************************************************************
[root@discus164 ˜]#
[root@discus164 ˜]# su - oracle
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$ srvctl status database -d orcl
PRCD-1027 : データベースorclの取得に失敗しました
PRCR-1070 : リソース ora.orcl.dbが登録されているかどうかの確認に失敗しました
Cannot communicate with crsd
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$ exit
logout


では、起動しま〜す。

[oracle@discus164 ˜]$ 
[root@discus164 ˜]# crsctl start cluster -all
CRS-2672: 'ora.cssdmonitor'('discus164')の起動を試行しています
CRS-2672: 'ora.cssdmonitor'('discus264')の起動を試行しています
CRS-2676: 'ora.cssdmonitor'('discus164')の起動が成功しました
CRS-2672: 'ora.cssd'('discus164')の起動を試行しています
CRS-2676: 'ora.cssdmonitor'('discus264')の起動が成功しました
CRS-2672: 'ora.cssd'('discus264')の起動を試行しています
CRS-2672: 'ora.diskmon'('discus264')の起動を試行しています
CRS-2672: 'ora.diskmon'('discus164')の起動を試行しています
CRS-2676: 'ora.diskmon'('discus264')の起動が成功しました
CRS-2676: 'ora.diskmon'('discus164')の起動が成功しました
CRS-2676: 'ora.cssd'('discus264')の起動が成功しました
CRS-2672: 'ora.ctssd'('discus264')の起動を試行しています
CRS-2676: 'ora.cssd'('discus164')の起動が成功しました
CRS-2672: 'ora.ctssd'('discus164')の起動を試行しています
CRS-2676: 'ora.ctssd'('discus264')の起動が成功しました
CRS-2676: 'ora.ctssd'('discus164')の起動が成功しました
CRS-2672: 'ora.evmd'('discus264')の起動を試行しています
CRS-2672: 'ora.evmd'('discus164')の起動を試行しています
CRS-2672: 'ora.asm'('discus264')の起動を試行しています
CRS-2672: 'ora.asm'('discus164')の起動を試行しています
CRS-2676: 'ora.evmd'('discus264')の起動が成功しました
CRS-2676: 'ora.evmd'('discus164')の起動が成功しました
CRS-2676: 'ora.asm'('discus164')の起動が成功しました
CRS-2672: 'ora.crsd'('discus164')の起動を試行しています
CRS-2676: 'ora.asm'('discus264')の起動が成功しました
CRS-2672: 'ora.crsd'('discus264')の起動を試行しています
CRS-2676: 'ora.crsd'('discus164')の起動が成功しました
CRS-2676: 'ora.crsd'('discus264')の起動が成功しました
[root@discus164 ˜]#
[root@discus164 ˜]# crsctl status resource -w 'TYPE co ora' -t
--------------------------------------------------------------------------------
NAME TARGET STATE SERVER STATE_DETAILS
--------------------------------------------------------------------------------
Local Resources
--------------------------------------------------------------------------------
ora.CRS.dg
ONLINE ONLINE discus164
ONLINE ONLINE discus264
ora.DATA.dg
ONLINE ONLINE discus164
OFFLINE OFFLINE discus264
ora.FRA.dg
ONLINE ONLINE discus164
OFFLINE OFFLINE discus264
ora.LISTENER.lsnr
ONLINE ONLINE discus164
ONLINE OFFLINE discus264
ora.asm
ONLINE ONLINE discus164 Started
ONLINE ONLINE discus264 Started
ora.eons
ONLINE ONLINE discus164
ONLINE ONLINE discus264
ora.gsd
OFFLINE OFFLINE discus164
OFFLINE OFFLINE discus264
ora.net1.network
ONLINE ONLINE discus164
ONLINE ONLINE discus264
ora.ons
ONLINE ONLINE discus164
ONLINE ONLINE discus264
ora.registry.acfs
ONLINE ONLINE discus164
ONLINE ONLINE discus264
--------------------------------------------------------------------------------
Cluster Resources
--------------------------------------------------------------------------------
ora.LISTENER_SCAN1.lsnr
1 ONLINE ONLINE discus164
ora.LISTENER_SCAN2.lsnr
1 ONLINE ONLINE discus164
ora.LISTENER_SCAN3.lsnr
1 ONLINE ONLINE discus164
ora.discus164.vip
1 ONLINE ONLINE discus164
ora.discus264.vip
1 ONLINE INTERMEDIATE discus164 FAILED OVER
ora.oc4j
1 OFFLINE OFFLINE
ora.orcl.db
1 ONLINE OFFLINE
2 ONLINE OFFLINE
ora.scan1.vip
1 ONLINE ONLINE discus164
ora.scan2.vip
1 ONLINE ONLINE discus164
ora.scan3.vip
1 ONLINE ONLINE discus164


ora.LISTENER_SCAN1.lsnr/ora.discus264.vipの両リソースがノードdiscus164からノードdiscus264へ移動し、ノードdiscus164でデータベースインスタンスが起動しました…

・・・中着・・・
--------------------------------------------------------------------------------
Cluster Resources
--------------------------------------------------------------------------------
ora.LISTENER_SCAN1.lsnr
1 ONLINE ONLINE discus264
ora.LISTENER_SCAN2.lsnr
1 ONLINE ONLINE discus164
ora.LISTENER_SCAN3.lsnr
1 ONLINE ONLINE discus164
ora.discus164.vip
1 ONLINE ONLINE discus164
ora.discus264.vip
1 ONLINE ONLINE discus264
ora.oc4j
1 OFFLINE OFFLINE
ora.orcl.db
1 ONLINE ONLINE discus164 Open
2 ONLINE OFFLINE
ora.scan1.vip
1 ONLINE ONLINE discus264
ora.scan2.vip
1 ONLINE ONLINE discus164
ora.scan3.vip
1 ONLINE ONLINE discus164


最後にノードdiscus264でもデータベースインスタンスが起動し、crsctl stop cluster -allで停止する以前の状況になっています。 :)

・・・中略・・・
--------------------------------------------------------------------------------
Cluster Resources
--------------------------------------------------------------------------------
ora.LISTENER_SCAN1.lsnr
1 ONLINE ONLINE discus264
ora.LISTENER_SCAN2.lsnr
1 ONLINE ONLINE discus164
ora.LISTENER_SCAN3.lsnr
1 ONLINE ONLINE discus164
ora.discus164.vip
1 ONLINE ONLINE discus164
ora.discus264.vip
1 ONLINE ONLINE discus264
ora.oc4j
1 OFFLINE OFFLINE
ora.orcl.db
1 ONLINE ONLINE discus164 Open
2 ONLINE ONLINE discus264 Open
ora.scan1.vip
1 ONLINE ONLINE discus264
ora.scan2.vip
1 ONLINE ONLINE discus164
ora.scan3.vip
1 ONLINE ONLINE discus164


ということで起動/停止の確認終了!

次回へつづく。






これまでのあらすじ
Mac de Oracle - 10万円未満 de RAC (11g編)#28

VirtualBox de RAC (Oracle11g R1編) #1
VirtualBox de RAC (Oracle11g R1編) #2



VirtualBox de Oracle11g R2 RAC #1
VirtualBox de Oracle11g R2 RAC #2 - 事前調査など…
VirtualBox de Oracle11g R2 RAC #3
VirtualBox de Oracle11g R2 RAC #4
VirtualBox de Oracle11g R2 RAC #5
VirtualBox de Oracle11g R2 RAC #6
VirtualBox de Oracle11g R2 RAC #7
VirtualBox de Oracle11g R2 RAC #8
VirtualBox de Oracle11g R2 RAC #9
VirtualBox de Oracle11g R2 RAC #10
VirtualBox de Oracle11g R2 RAC #11
VirtualBox de Oracle11g R2 RAC #12
VirtualBox de Oracle11g R2 RAC #13
VirtualBox de Oracle11g R2 RAC #14
VirtualBox de Oracle11g R2 RAC #15
VirtualBox de Oracle11g R2 RAC #16
VirtualBox de Oracle11g R2 RAC #17
VirtualBox de Oracle11g R2 RAC #18
VirtualBox de Oracle11g R2 RAC #19
VirtualBox de Oracle11g R2 RAC #20
VirtualBox de Oracle11g R2 RAC #21




VirtualBox de Oracle11g R2 RAC #16 - 番外編

| | コメント (0) | トラックバック (0)

VirtualBox de Oracle11g R2 RAC #21

VirtualBox de Oracle11g R2 RACのつづき。

  1. ハードウェア構成(VMなのでVMの構成も含めて)、ソフトウェア構成など
  2. Linux (CentOS 5.5 x86_64)のインストール
  3. Openfiler2.3 x86のインストール
  4. Openfiler2.3 x86によるiSCSIボリュームの構成
  5. Oracle RACノードでのiSCSIボリュームの構成 その1その2その3
  6. Oracle所有者、Oracle Grid Infrastructureユーザの作成と関連ディレクトリの作成及び環境変数の設定
  7. Oracle向けLinuxサーバーの構成(カーネルパラメータの設定)
  8. Oracle RACノード間リモートアクセスの構成とntpの構成
    sshの構成は念のために行った、多分、実施しなくても大丈夫だと思うけど…ついでなので、ちょいと意地悪な実験をしてみた)
  9. ローカルネームサーバの構成
  10. Oracle RACノード構成ファイルの確認
  11. Oracle Automatic Storage Management(ASMLib 2.0.5 x84_64)のインストール及び構成
  12. Oracle11g R2 11.2.0.1.0 RACインストール事前作業
  13. Oracle11g R2 11.2.0.1.0 Grid Infrastractureのインストール
  14. Oracle11g R2 11.2.0.1.0 Database softwareのインストール
  15. Oracle11g R2 11.2.0.1.0 examplesのインストール
  16. Oracle Cluster databaseの作成
  17. Net Serviceの確認
  18. Oralce Grid InsfastructureとDatabase構成の確認
  19. Clusterの開始と停止の確認
  20. 簡単なTransparent Application Failover (TAF)の確認

Oralce Grid InsfastructureとDatabase構成の確認

OUIやらなんやらがいろいろと構成してくれたりしてくれてるので確認方法の確認って感じですが…

Oracle所有者にて実行…

[oracle@discus164 ˜]$
[oracle@discus164 ˜]$ srvctl status database -d orcl
インスタンスorcl1はノードdiscus164で実行中です。
インスタンスorcl2はノードdiscus264で実行中です。
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$ srvctl status instance -d orcl -n discus164
インスタンスorcl1はノードdiscus164で実行中です。
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$ srvctl status instance -d orcl -n discus264
インスタンスorcl2はノードdiscus264で実行中です。
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$ srvctl status nodeapps
VIP discus164-vipは有効です
VIP discus164-vipはノードで実行中です: discus164
VIP discus264-vipは有効です
VIP discus264-vipはノードで実行中です: discus264
ネットワークは有効です
ネットワークはノードで実行中です: discus164
ネットワークはノードで実行中です: discus264
GSDは無効です
GSDはノードで実行されていません: discus164
GSDはノードで実行されていません: discus264
ONSは有効です
ONSデーモンはノードで実行中です: discus164
ONSデーモンはノードで実行中です: discus264
eONSは有効です
eONSデーモンはノードで実行中です:discus164
eONSデーモンはノードで実行中です:discus264
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$ srvctl status vip -n discus164
VIP discus164-vipは有効です
VIP discus164-vipはノードで実行中です: discus164
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$ srvctl status vip -n discus264
VIP discus264-vipは有効です
VIP discus264-vipはノードで実行中です: discus264
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$ srvctl status asm -a
ASMはdiscus164,discus264で実行中です
ASMは有効です。
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$ srvctl status listener -n discus164
リスナーLISTENERはノードで有効です: discus164
リスナーLISTENERはノードで実行中です: discus164
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$ srvctl status listener -n discus264
リスナーLISTENERはノードで有効です: discus264
リスナーLISTENERはノードで実行中です: discus264
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$ srvctl status scan
SCAN VIP scan1は有効です
SCAN VIP scan1はノードdiscus264で実行されています
SCAN VIP scan2は有効です
SCAN VIP scan2はノードdiscus164で実行されています
SCAN VIP scan3は有効です
SCAN VIP scan3はノードdiscus164で実行されています
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$ srvctl status scan_listener
SCANリスナーLISTENER_SCAN1は有効です
SCANリスナーLISTENER_SCAN1はノードdiscus264で実行されています
SCANリスナーLISTENER_SCAN2は有効です
SCANリスナーLISTENER_SCAN2はノードdiscus164で実行されています
SCANリスナーLISTENER_SCAN3は有効です
SCANリスナーLISTENER_SCAN3はノードdiscus164で実行されています
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$ srvctl status srvpool -a
サーバー・プール名: Free
アクティブ・サーバー数: 0
アクティブ・サーバー名:
サーバー・プール名: Generic
アクティブ・サーバー数: 2
アクティブ・サーバー名: discus164,discus264
NAME=discus164 STATE=ONLINE
NAME=discus264 STATE=ONLINE
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$ srvctl status server -n discus164,discus264 -a
サーバー名: discus164
サーバーの状態: ONLINE
アクティブなサーバー・プール: Generic ora.orcl
サーバーの状態の詳細:
サーバー名: discus264
サーバーの状態: ONLINE
アクティブなサーバー・プール: Generic ora.orcl
サーバーの状態の詳細:
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$ srvctl status oc4j
OC4Jは無効です
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$ srvctl status diskgroup -g DATA -a
ディスク・グループDATAはdiscus164,discus264で実行中です
ディスク・グループDATAは有効です
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$ srvctl status diskgroup -g CRS -a
ディスク・グループCRSはdiscus164,discus264で実行中です
ディスク・グループCRSは有効です
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$ srvctl status diskgroup -g FRA -a
ディスク・グループFRAはdiscus164,discus264で実行中です
ディスク・グループFRAは有効です
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$

構成の確認…

[oracle@discus164 ˜]$ 
[oracle@discus164 ˜]$ srvctl config database -d orcl -a
一意のデータベース名: orcl
データベース名: orcl
Oracleホーム: /u01/app/oracle/product/11.2.0/dbhome_1
Oracleユーザー: oracle
spfile: +DATA/orcl/spfileorcl.ora
ドメイン: macdeoracle.info
開始オプション: open
停止オプション: immediate
データベース・ロール: PRIMARY
管理ポリシー: AUTOMATIC
サーバー・プール: orcl
データベース・インスタンス: orcl1,orcl2
ディスク・グループ: DATA,FRA
サービス:
データベースは有効です
データベースは管理者によって管理されています
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$ srvctl config nodeapps -a -g -s
VIPが存在します。:discus164
VIPが存在します。: /discus164-vip/192.168.1.190/255.255.255.0/eth0
VIPが存在します。:discus264
VIPが存在します。: /discus264-vip/192.168.1.191/255.255.255.0/eth0
GSDが存在します。
ONSデーモンは存在します。ローカル・ポート6100、リモート・ポート6200
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$ srvctl config asm -a
ASMホーム: /u01/app/11.2.0/grid
ASMリスナー: LISTENER
ASMは有効です。
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$ srvctl config listener -a
名前: LISTENER
ネットワーク: 1、所有者: grid
ホーム: <CRS home>
ノードdiscus264,discus164の/u01/app/11.2.0/grid
エンド・ポイント: TCP:1521
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$ srvctl config scan
SCAN名: discus-rac64-scan.macdeoracle.jp、ネットワーク: 1/192.168.1.0/255.255.255.0/eth0
SCAN VIP名: scan1、IP: /discus-rac64-scan.macdeoracle.jp/192.168.1.200
SCAN VIP名: scan2、IP: /discus-rac64-scan.macdeoracle.jp/192.168.1.201
SCAN VIP名: scan3、IP: /discus-rac64-scan.macdeoracle.jp/192.168.1.202
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$ srvctl config scan_listener
SCANリスナーLISTENER_SCAN1は存在します。ポート: TCP:1521
SCANリスナーLISTENER_SCAN2は存在します。ポート: TCP:1521
SCANリスナーLISTENER_SCAN3は存在します。ポート: TCP:1521
[oracle@discus164 ˜]$
[oracle@discus164 ˜]$ srvctl config srvpool
サーバー・プール名: Free
重要度: 0、最小: 0、最大: -1
候補サーバー名:
サーバー・プール名: Generic
重要度: 0、最小: 0、最大: -1
候補サーバー名: discus164,discus264
[oracle@discus164 ˜]$


Grid Infrastructureユーザにて実行…

[grid@discus164 ˜]$ crsctl check cluster -all
**************************************************************
discus164:
CRS-4537: Cluster Ready Servicesがオンラインです
CRS-4529: Cluster Synchronization Servicesがオンラインです
CRS-4533: イベント・マネージャがオンラインです
**************************************************************
discus264:
CRS-4537: Cluster Ready Servicesがオンラインです
CRS-4529: Cluster Synchronization Servicesがオンラインです
CRS-4533: イベント・マネージャがオンラインです
**************************************************************
[grid@discus164 ˜]$
[grid@discus164 ˜]$ crsctl check crs
CRS-4638: Oracle高可用性サービスがオンラインです
CRS-4537: Cluster Ready Servicesがオンラインです
CRS-4529: Cluster Synchronization Servicesがオンラインです
CRS-4533: イベント・マネージャがオンラインです
[grid@discus164 ˜]$
[grid@discus164 ˜]$ crsctl check ctss
CRS-4700: クラスタ時刻同期化サービスはオブザーバ・モードになっています。
[grid@discus164 ˜]$
[grid@discus164 ˜]$ crsctl check css
CRS-4529: Cluster Synchronization Servicesがオンラインです
[grid@discus164 ˜]$
[grid@discus164 ˜]$
[grid@discus164 ˜]$ crsctl status serverpool
NAME=Free
ACTIVE_SERVERS=

NAME=Generic
ACTIVE_SERVERS=discus164 discus264

NAME=ora.orcl
ACTIVE_SERVERS=discus164 discus264

[grid@discus164 ˜]$
[grid@discus164 ˜]$
[grid@discus164 ˜]$ crsctl query css votedisk
## STATE File Universal Id File Name Disk group
-- ----- ----------------- --------- ---------
1. ONLINE 8f431fe5d1304fd9bf6ad331d3aef536 (ORCL:CRSVOL1) [CRS]
1の投票ディスクを検出しました。
[grid@discus164 ˜]$
[grid@discus164 ˜]$ crsctl status resource -t
--------------------------------------------------------------------------------
NAME TARGET STATE SERVER STATE_DETAILS
--------------------------------------------------------------------------------
Local Resources
--------------------------------------------------------------------------------
ora.CRS.dg
ONLINE ONLINE discus164
ONLINE ONLINE discus264
ora.DATA.dg
ONLINE ONLINE discus164
ONLINE ONLINE discus264
ora.FRA.dg
ONLINE ONLINE discus164
ONLINE ONLINE discus264
ora.LISTENER.lsnr
ONLINE ONLINE discus164
ONLINE ONLINE discus264
ora.asm
ONLINE ONLINE discus164 Started
ONLINE ONLINE discus264 Started
ora.eons
ONLINE ONLINE discus164
ONLINE ONLINE discus264
ora.gsd
OFFLINE OFFLINE discus164
OFFLINE OFFLINE discus264
ora.net1.network
ONLINE ONLINE discus164
ONLINE ONLINE discus264
ora.ons
ONLINE ONLINE discus164
ONLINE ONLINE discus264
ora.registry.acfs
ONLINE ONLINE discus164
ONLINE ONLINE discus264
--------------------------------------------------------------------------------
Cluster Resources
--------------------------------------------------------------------------------
ora.LISTENER_SCAN1.lsnr
1 ONLINE ONLINE discus264
ora.LISTENER_SCAN2.lsnr
1 ONLINE ONLINE discus164
ora.LISTENER_SCAN3.lsnr
1 ONLINE ONLINE discus164
ora.discus164.vip
1 ONLINE ONLINE discus164
ora.discus264.vip
1 ONLINE ONLINE discus264
ora.oc4j
1 OFFLINE OFFLINE
ora.orcl.db
1 ONLINE ONLINE discus164 Open
2 ONLINE ONLINE discus264 Open
ora.scan1.vip
1 ONLINE ONLINE discus264
ora.scan2.vip
1 ONLINE ONLINE discus164
ora.scan3.vip
1 ONLINE ONLINE discus164

[grid@discus164 ˜]$


あれ、perlでエラーメッセージでてるけどご愛嬌 :)

[grid@discus164 ˜]$ asmcmd
ASMCMD>
ASMCMD>
ASMCMD> lsdg -g
Use of uninitialized value in string comparison (cmp) at /u01/app/11.2.0/grid/lib/asmcmdbase.pm line 3420, <STDIN> line 42.
Use of uninitialized value in string comparison (cmp) at /u01/app/11.2.0/grid/lib/asmcmdbase.pm line 3420, <STDIN> line 42.
Use of uninitialized value in string comparison (cmp) at /u01/app/11.2.0/grid/lib/asmcmdbase.pm line 3420, <STDIN> line 42.
Use of uninitialized value in string comparison (cmp) at /u01/app/11.2.0/grid/lib/asmcmdbase.pm line 3420, <STDIN> line 42.
Use of uninitialized value in string comparison (cmp) at /u01/app/11.2.0/grid/lib/asmcmdbase.pm line 3420, <STDIN> line 42.
Use of uninitialized value in string comparison (cmp) at /u01/app/11.2.0/grid/lib/asmcmdbase.pm line 3420, <STDIN> line 42.
Inst_ID State Type Rebal Sector Block AU Total_MB Free_MB Req_mir_free_MB Usable_file_MB Offline_disks Voting_files Name
1 MOUNTED EXTERN N 512 4096 1048576 4092 3694 0 3694 0 N CRS/
2 MOUNTED EXTERN N 512 4096 1048576 4092 3694 0 3694 0 N CRS/
1 MOUNTED NORMAL N 512 4096 1048576 43006 37436 0 18718 0 N DATA/
2 MOUNTED NORMAL N 512 4096 1048576 43006 37436 0 18718 0 N DATA/
1 MOUNTED NORMAL N 512 4096 1048576 43006 42336 0 21168 0 N FRA/
2 MOUNTED NORMAL N 512 4096 1048576 43006 42336 0 21168 0 N FRA/
ASMCMD>
ASMCMD> lsct -g
Instance_ID DB_Name Status Software_Version Compatible_version Instance_Name Disk_Group
1 +ASM CONNECTED 11.2.0.1.0 11.2.0.1.0 +ASM1 CRS
1 +ASM CONNECTED 11.2.0.1.0 11.2.0.1.0 +ASM1 DATA
2 +ASM CONNECTED 11.2.0.1.0 11.2.0.1.0 +ASM2 CRS
2 +ASM CONNECTED 11.2.0.1.0 11.2.0.1.0 +ASM2 DATA
1 orcl CONNECTED 11.2.0.1.0 11.2.0.0.0 orcl1 DATA
1 orcl CONNECTED 11.2.0.1.0 11.2.0.0.0 orcl1 FRA
2 orcl CONNECTED 11.2.0.1.0 11.2.0.0.0 orcl2 DATA
2 orcl CONNECTED 11.2.0.1.0 11.2.0.0.0 orcl2 FRA
ASMCMD>
ASMCMD> ls -g
Use of uninitialized value in string comparison (cmp) at /u01/app/11.2.0/grid/lib/asmcmdbase.pm line 3420, <STDIN> line 46.
Use of uninitialized value in string comparison (cmp) at /u01/app/11.2.0/grid/lib/asmcmdbase.pm line 3420, <STDIN> line 46.
Use of uninitialized value in string comparison (cmp) at /u01/app/11.2.0/grid/lib/asmcmdbase.pm line 3420, <STDIN> line 46.
Use of uninitialized value in string comparison (cmp) at /u01/app/11.2.0/grid/lib/asmcmdbase.pm line 3420, <STDIN> line 46.
Use of uninitialized value in string comparison (cmp) at /u01/app/11.2.0/grid/lib/asmcmdbase.pm line 3420, <STDIN> line 46.
Use of uninitialized value in string comparison (cmp) at /u01/app/11.2.0/grid/lib/asmcmdbase.pm line 3420, <STDIN> line 46.
Inst_ID Name
1 CRS/
2 CRS/
1 DATA/
2 DATA/
1 FRA/
2 FRA/
ASMCMD>
ASMCMD> lsof
DB_Name Instance_Name Path
+ASM +ASM1 +crs.255.4294967295
orcl orcl1 +data/orcl/controlfile/current.256.739409625
orcl orcl1 +data/orcl/datafile/sysaux.260.739409693
orcl orcl1 +data/orcl/datafile/system.259.739409647
orcl orcl1 +data/orcl/datafile/undotbs1.261.739409729
orcl orcl1 +data/orcl/datafile/undotbs2.263.739409753
orcl orcl1 +data/orcl/datafile/users.264.739409767
orcl orcl1 +data/orcl/onlinelog/group_1.257.739409631
orcl orcl1 +data/orcl/onlinelog/group_2.258.739409637
orcl orcl1 +data/orcl/onlinelog/group_3.265.739412213
orcl orcl1 +data/orcl/onlinelog/group_4.266.739412217
orcl orcl1 +data/orcl/tempfile/temp.262.739409741
orcl orcl1 +fra/orcl/controlfile/current.256.739409629
orcl orcl1 +fra/orcl/onlinelog/group_1.257.739409635
orcl orcl1 +fra/orcl/onlinelog/group_2.258.739409643
orcl orcl1 +fra/orcl/onlinelog/group_3.259.739412215
orcl orcl1 +fra/orcl/onlinelog/group_4.260.739412225
ASMCMD>

最後にSQL*Plusから

SYS> l
1 select
2 inst_id
3 ,instance_name
4 ,parallel
5 ,status
6 ,database_status
7 ,active_state
8 ,host_name
9 from
10* gv$instance
SYS>
SYS> /

INST_ID INSTANCE_NAME PAR STATUS DATABASE_STATUS ACTIVE_ST HOST_NAME
---------- ---------------- --- ------------ ----------------- --------- ------------------------------
1 orcl1 YES OPEN ACTIVE NORMAL discus164.macdeoracle.jp
2 orcl2 YES OPEN ACTIVE NORMAL discus264.macdeoracle.jp

SYS>


次回へつづく。






これまでのあらすじ
Mac de Oracle - 10万円未満 de RAC (11g編)#28

VirtualBox de RAC (Oracle11g R1編) #1
VirtualBox de RAC (Oracle11g R1編) #2



VirtualBox de Oracle11g R2 RAC #1
VirtualBox de Oracle11g R2 RAC #2 - 事前調査など…
VirtualBox de Oracle11g R2 RAC #3
VirtualBox de Oracle11g R2 RAC #4
VirtualBox de Oracle11g R2 RAC #5
VirtualBox de Oracle11g R2 RAC #6
VirtualBox de Oracle11g R2 RAC #7
VirtualBox de Oracle11g R2 RAC #8
VirtualBox de Oracle11g R2 RAC #9
VirtualBox de Oracle11g R2 RAC #10
VirtualBox de Oracle11g R2 RAC #11
VirtualBox de Oracle11g R2 RAC #12
VirtualBox de Oracle11g R2 RAC #13
VirtualBox de Oracle11g R2 RAC #14
VirtualBox de Oracle11g R2 RAC #15
VirtualBox de Oracle11g R2 RAC #16
VirtualBox de Oracle11g R2 RAC #17
VirtualBox de Oracle11g R2 RAC #18
VirtualBox de Oracle11g R2 RAC #19
VirtualBox de Oracle11g R2 RAC #20




VirtualBox de Oracle11g R2 RAC #16 - 番外編

| | コメント (0) | トラックバック (0)

VirtualBox de Oracle11g R2 RAC #20

VirtualBox de Oracle11g R2 RACのつづき。

データベースも無事?作成できたので、今回はNet Serviceの確認を。

  1. ハードウェア構成(VMなのでVMの構成も含めて)、ソフトウェア構成など
  2. Linux (CentOS 5.5 x86_64)のインストール
  3. Openfiler2.3 x86のインストール
  4. Openfiler2.3 x86によるiSCSIボリュームの構成
  5. Oracle RACノードでのiSCSIボリュームの構成 その1その2その3
  6. Oracle所有者、Oracle Grid Infrastructureユーザの作成と関連ディレクトリの作成及び環境変数の設定
  7. Oracle向けLinuxサーバーの構成(カーネルパラメータの設定)
  8. Oracle RACノード間リモートアクセスの構成とntpの構成
    sshの構成は念のために行った、多分、実施しなくても大丈夫だと思うけど…ついでなので、ちょいと意地悪な実験をしてみた)
  9. ローカルネームサーバの構成
  10. Oracle RACノード構成ファイルの確認
  11. Oracle Automatic Storage Management(ASMLib 2.0.5 x84_64)のインストール及び構成
  12. Oracle11g R2 11.2.0.1.0 RACインストール事前作業
  13. Oracle11g R2 11.2.0.1.0 Grid Infrastractureのインストール
  14. Oracle11g R2 11.2.0.1.0 Database softwareのインストール
  15. Oracle11g R2 11.2.0.1.0 examplesのインストール
  16. Oracle Cluster databaseの作成
  17. Net Serviceの確認
  18. Oralce Grid InsfastructureとDatabase構成の確認
  19. Clusterの開始と停止の確認
  20. 簡単なTransparent Application Failover (TAF)の確認

Net Serviceの確認

まず、クライアントになるMacOS X Snow LeopardのOracle10g R2 Instant Client側の設定(tnsnames.ora)から。

tnsnames.oraにVirtualBox上に構築したRACに接続するため以下ように定義した。
接続識別子ORCLはVirtualBox上に構築した際、自動生成された部分を複製し、残り2つの定義はRACの各ノードを個別に狙って接続するため接続識別子ORCL1/ORCL2を定義した。

discus:˜ oracle$ diff -u $TNS_ADMIN/tnsnames.ora.org $TNS_ADMIN/tnsnames.ora
--- /Users/Shared/instantclient_10_2/tnsnames.ora.org 2011-01-04 22:34:28.000000000 +0900
+++ /Users/Shared/instantclient_10_2/tnsnames.ora 2011-01-04 22:57:31.000000000 +0900
@@ -10,3 +10,32 @@
)
)

+# Oracle11g R2 11.2.0.1.0 RAC for Linux x86_64 / VirtualBox
+ORCL =
+ (DESCRIPTION =
+ (ADDRESS = (PROTOCOL = TCP)(HOST = discus-rac64-scan.macdeoracle.jp)(PORT = 1521))
+ (CONNECT_DATA =
+ (SERVER = DEDICATED)
+ (SERVICE_NAME = orcl.macdeoracle.info)
+ )
+ )
+
+ORCL2 =
+ (DESCRIPTION =
+ (ADDRESS = (PROTOCOL = TCP)(HOST = discus-rac64-scan.macdeoracle.jp)(PORT = 1521))
+ (CONNECT_DATA =
+ (SERVER = DEDICATED)
+ (SERVICE_NAME = orcl.macdeoracle.info)
+ (INSTANCE_NAME = orcl2)
+ )
+ )
+
+ORCL1 =
+ (DESCRIPTION =
+ (ADDRESS = (PROTOCOL = TCP)(HOST = discus-rac64-scan.macdeoracle.jp)(PORT = 1521))
+ (CONNECT_DATA =
+ (SERVER = DEDICATED)
+ (SERVICE_NAME = orcl.macdeoracle.info)
+ (INSTANCE_NAME = orcl1)
+ )
+ )
discus:˜ oracle$


接続テスト

事前にscan vipがどのような状態か確認しておく。

[oracle@discus164 ˜]$ srvctl status scan
SCAN VIP scan1は有効です
SCAN VIP scan1はノードdiscus264で実行されています
SCAN VIP scan2は有効です
SCAN VIP scan2はノードdiscus164で実行されています
SCAN VIP scan3は有効です
SCAN VIP scan3はノードdiscus164で実行されています
[oracle@discus164 ˜]$

[root@discus164 ˜]# crsctl status resource -w 'TYPE co scan' -t
--------------------------------------------------------------------------------
NAME TARGET STATE SERVER STATE_DETAILS
--------------------------------------------------------------------------------
Cluster Resources
--------------------------------------------------------------------------------
ora.LISTENER_SCAN1.lsnr
1 ONLINE ONLINE discus264
ora.LISTENER_SCAN2.lsnr
1 ONLINE ONLINE discus164
ora.LISTENER_SCAN3.lsnr
1 ONLINE ONLINE discus164
ora.scan1.vip
1 ONLINE ONLINE discus264
ora.scan2.vip
1 ONLINE ONLINE discus164
ora.scan3.vip
1 ONLINE ONLINE discus164
[root@discus164 ˜]#

MacOS X Snow LeopardのSQL*PlusからVirtualBox上のOracle11g R2 11.2.0.1.0 RACへの接続テスト。

discus:˜ oracle$ sqlplus /nolog

SQL*Plus: Release 10.2.0.4.0 - Production on 火 1月 4 23:16:53 2011

Copyright (c) 1982, 2007, Oracle. All Rights Reserved.

SQL> -- ロードバランシングで適当なインスタンスへ接続される。この場合インスタンス2に接続した
SQL> conn scott/tiger@orcl
接続されました。
SQL> select instance_name from v$instance;

INSTANCE_NAME
----------------
orcl2

SQL> -- 2度目はインスタンス1に接続した。(うまくいってる!)
SQL> conn scott/tiger@orcl
接続されました。
SQL> select instance_name from v$instance;

INSTANCE_NAME
----------------
orcl1

SQL> -- インスタンス1(orcl1)を狙った接続! OK.
SQL> conn scott/tiger@orcl1
接続されました。
SQL> select instance_name from v$instance;

INSTANCE_NAME
----------------
orcl1

SQL> -- 念のためもう一度。狙ったインスタンスへ接続している。
SQL> conn scott/tiger@orcl1
接続されました。
SQL> select instance_name from v$instance;

INSTANCE_NAME
----------------
orcl1

SQL> -- インスタンス2(orcl2)を狙った接続! OK.
SQL> conn scott/tiger@orcl2
接続されました。
SQL> select instance_name from v$instance;

INSTANCE_NAME
----------------
orcl2

SQL> -- 念のためもう一度!。狙ったインスタンスへ接続している。
SQL> conn scott/tiger@orcl2
接続されました。
SQL> select instance_name from v$instance;

INSTANCE_NAME
----------------
orcl2

SQL>


リモートからのも接続OK :)


以下、RACインスタンスのバージョン情報、Client側情報としてSQL*Plusのバージョン及び、OSのバージョン情報。

SQL> select * from gv$version; 

INST_ID BANNER
---------- --------------------------------------------------------------------------------
2 Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
2 PL/SQL Release 11.2.0.1.0 - Production
2 CORE 11.2.0.1.0 Production
2 TNS for Linux: Version 11.2.0.1.0 - Production
2 NLSRTL Version 11.2.0.1.0 - Production
1 Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
1 PL/SQL Release 11.2.0.1.0 - Production
1 CORE 11.2.0.1.0 Production
1 TNS for Linux: Version 11.2.0.1.0 - Production
1 NLSRTL Version 11.2.0.1.0 - Production

10行が選択されました。

SQL> !sqlplus -v

SQL*Plus: Release 10.2.0.4.0 - Production

SQL> !system_profiler SPSoftwareDataType | grep 'System Version'
System Version: Mac OS X 10.6.5 (10H574)

SQL>

次回へつづく。






これまでのあらすじ
Mac de Oracle - 10万円未満 de RAC (11g編)#28

VirtualBox de RAC (Oracle11g R1編) #1
VirtualBox de RAC (Oracle11g R1編) #2



VirtualBox de Oracle11g R2 RAC #1
VirtualBox de Oracle11g R2 RAC #2 - 事前調査など…
VirtualBox de Oracle11g R2 RAC #3
VirtualBox de Oracle11g R2 RAC #4
VirtualBox de Oracle11g R2 RAC #5
VirtualBox de Oracle11g R2 RAC #6
VirtualBox de Oracle11g R2 RAC #7
VirtualBox de Oracle11g R2 RAC #8
VirtualBox de Oracle11g R2 RAC #9
VirtualBox de Oracle11g R2 RAC #10
VirtualBox de Oracle11g R2 RAC #11
VirtualBox de Oracle11g R2 RAC #12
VirtualBox de Oracle11g R2 RAC #13
VirtualBox de Oracle11g R2 RAC #14
VirtualBox de Oracle11g R2 RAC #15
VirtualBox de Oracle11g R2 RAC #16
VirtualBox de Oracle11g R2 RAC #17
VirtualBox de Oracle11g R2 RAC #18
VirtualBox de Oracle11g R2 RAC #19




VirtualBox de Oracle11g R2 RAC #16 - 番外編

| | コメント (0) | トラックバック (0)

VirtualBox de Oracle11g R2 RAC #16の番外編

VirtualBox de Oracle11g R2 RAC #16の番外編として、Oracle11g R2 11.2.0.1.0のOracle Grid Infrastructureをdeinstallツールのログを備忘録として残しておきます。 :)

[grid@discus164 deinstall]$ ./deinstall
Checking for required files and bootstrapping ...
Please wait ...
Location of logs /tmp/deinstall2010-12-01_08-36-01-午後/logs/

############ ORACLE DEINSTALL & DECONFIG TOOL START ############


######################## CHECK OPERATION START ########################
インストールの構成確認の開始


Oracleホームの場所が存在するかどうかを確認しています /u01/app/11.2.0/grid
選択された削除対象のOracleホームのタイプ: CRS
選択された削除対象のOracleベース: /u01/app/grid
中央インベントリの場所が存在するかどうかを確認しています /u01/app/oraInventory
Oracle Grid Infrastructureホームが存在するかどうかを確認しています /u01/app/11.2.0/grid
次のノードはこのクラスタの一部です: discus164,discus264

インストールの構成確認の終了

Traces log file: /tmp/deinstall2010-12-01_08-36-01-午後/logs//crsdc.log

ネットワーク構成チェック構成START

ネットワーク構成解除トレース・ファイルの場所: /tmp/deinstall2010-12-01_08-36-01-午後/logs/netdc_check7323528496868837695.log

構成解除するすべてのRACリスナーを指定してください[LISTENER]:

ネットワーク構成チェック構成END

ASMチェック構成START

ASM構成解除トレース・ファイルの場所: /tmp/deinstall2010-12-01_08-36-01-午後/logs/asmcadc_check7638050551281896899.log

このOracleホーム/u01/app/11.2.0/gridで自動ストレージ管理(ASM)インスタンスが検出されました。
ASM診断先: /u01/app/grid
ASMディスク・グループ: +CRS
ディスク・グループは削除されます
ASMを構成解除すると、クリーンアップ時にすべてのディスク・グループおよびそのコンテンツが削除されます。これは、
このASMインスタンスを使用するすべてのデータベースおよびACFSに影響します。
既存のディスク・グループを保持する場合、または検出された情報が正しくない場合、'y'と入力することにより、変更できます。前述の情報(y|n)を変更しますか [n]: y
ASMの診断先を指定してください [/u01/app/grid]:
このASMインスタンスによって管理されているディスク・グループを指定してください [+CRS]:

ASMを構成解除すると、クリーンアップ時にすべてのディスク・グループが削除されます。構成解除ツールでディスク・グループy|nを削除しますか [y]: y


######################### CHECK OPERATION END #########################


####################### CHECK OPERATION SUMMARY #######################
Oracle Grid Infrastructureホーム: /u01/app/11.2.0/grid
Oracleホームが存在するクラスタ・ノード: (ノードを","で区切って入力してください。例: node1,node2,...)discus164,discus264
選択された削除対象のOracleホーム: /u01/app/11.2.0/grid
Oracleホームが登録されているインベントリの場所: /u01/app/oraInventory
次のRACリスナーが構成解除されます: LISTENER
ASMインスタンスはこのOracleホームから構成解除されます
続行しますか (y - はい、n - いいえ)[n]: y
このセッションのログは/tmp/deinstall2010-12-01_08-36-01-午後/logs/deinstall_deconfig2010-12-01_08-36-34-PM.outに書き込まれます
このセッションのすべてのエラー・メッセージは/tmp/deinstall2010-12-01_08-36-01-午後/logs/deinstall_deconfig2010-12-01_08-36-34-PM.errに書き込まれます

######################## CLEAN OPERATION START ########################
ASM構成解除トレース・ファイルの場所: /tmp/deinstall2010-12-01_08-36-01-午後/logs/asmcadc_clean4713857881917098991.log
ASMクリーンアップ構成START
ASMクリーンアップ構成END

ネットワーク構成クリーニング構成START

ネットワーク構成解除トレース・ファイルの場所: /tmp/deinstall2010-12-01_08-36-01-午後/logs/netdc_clean533226112421006626.log

RACリスナーの構成解除: LISTENER

リスナーの構成解除: LISTENER
リスナーを停止しています: LISTENER
リスナーの停止に成功しました。
リスナーを登録解除しています: LISTENER
リスナーの登録解除に成功しました。
リスナーは正常に構成解除されました。

すべてのノードでネーミング・メソッド構成ファイルの構成解除中です...
ネーミング・メソッド構成ファイルが正常に構成解除されました。

すべてのノードでローカル・ネット・サービス名構成ファイルの構成解除中です...
ローカル・ネット・サービス名構成ファイルが正常に構成解除されました。

すべてのノードでディレクトリ使用構成ファイルの構成解除中です...
ディレクトリ使用構成ファイルが正常に構成解除されました。

すべてのノードでバックアップ・ファイルの構成解除中です...
バックアップ・ファイルが正常に構成解除されました。

ネットワーク構成が正常にクリーンアップされました。

ネットワーク構成クリーニング構成END


---------------------------------------->

ノード"discus264"のrootユーザーまたは管理者として次のコマンドを実行します。

/tmp/deinstall2010-12-01_08-36-01-午後/perl/bin/perl -I/tmp/deinstall2010-12-01_08-36-01-午後/perl/lib -I/tmp/deinstall2010-12-01_08-36-01-午後/crs/install /tmp/deinstall2010-12-01_08-36-01-午後/crs/install/rootcrs.pl -force -delete -paramfile /tmp/deinstall2010-12-01_08-36-01-午後/response/deinstall_Ora11g_gridinfrahome1.rsp

ノード"discus164"のrootユーザーまたは管理者として次のコマンドを実行します。

/tmp/deinstall2010-12-01_08-36-01-午後/perl/bin/perl -I/tmp/deinstall2010-12-01_08-36-01-午後/perl/lib -I/tmp/deinstall2010-12-01_08-36-01-午後/crs/install /tmp/deinstall2010-12-01_08-36-01-午後/crs/install/rootcrs.pl -force -delete -paramfile /tmp/deinstall2010-12-01_08-36-01-午後/response/deinstall_Ora11g_gridinfrahome1.rsp -lastnode

前述のコマンドを実行した後、[Enter]を押します

<----------------------------------------

Oracle Universal Installerクリーンアップの開始

Oracleホーム'/u01/app/11.2.0/grid'をローカル・ノードの中央インベントリからデタッチします : 終了

ローカル・ノードのディレクトリ'/u01/app/11.2.0/grid'を削除します : 終了

ローカル・ノードのディレクトリ'/u01/app/oraInventory'を削除します : 終了

ローカル・ノードのディレクトリ'/u01/app/grid'を削除します : 終了

Oracleホーム'/u01/app/11.2.0/grid'をリモート・ノード'discus264'の中央インベントリからデタッチします : 終了

リモート・ノード'discus264'のディレクトリ'/u01/app/11.2.0/grid'を削除します : 終了

リモート・ノード'discus264'のディレクトリ'/u01/app/oraInventory'を削除します : 終了

リモート・ノード'discus264'のディレクトリ'/u01/app/grid'を削除します : 終了

Oracle Universal Installerのクリーンアップが成功しました。

Oracle Universal Installerクリーンアップの終了


Oracleインストール・クリーンアップの開始

インストールのクリーンアップ操作により、ノードdiscus164の一時ディレクトリ/tmp/installを削除しています
インストールのクリーンアップ操作により、ノードdiscus264の一時ディレクトリ/tmp/installを削除しています

Oracleインストール・クリーンアップの終了


######################### CLEAN OPERATION END #########################


####################### CLEAN OPERATION SUMMARY #######################
ASMインスタンスはOracleホームから正常に構成解除されました
次のRACリスナーが正常に構成解除されました: LISTENER
Oracleクラスタウェアはノード"discus164"で停止され、正常に構成解除されています
Oracleクラスタウェアはノード"discus264"で停止され、正常に構成解除されています
Oracleクラスタウェアは正常に停止および構成解除されています。
Oracleホーム'/u01/app/11.2.0/grid'がローカル・ノードの中央インベントリから正常にデタッチされました。
ローカル・ノードのディレクトリ'/u01/app/11.2.0/grid'が正常に削除されました。
ローカル・ノードのディレクトリ'/u01/app/oraInventory'が正常に削除されました。
ローカル・ノードのディレクトリ'/u01/app/grid'が正常に削除されました。
Oracleホーム'/u01/app/11.2.0/grid'がリモート・ノード'discus264'の中央インベントリから正常にデタッチされました。
リモート・ノード'discus264'のディレクトリ'/u01/app/11.2.0/grid'が正常に削除されました。
リモート・ノード'discus264'のディレクトリ'/u01/app/oraInventory'が正常に削除されました。
リモート・ノード'discus264'のディレクトリ'/u01/app/grid'が正常に削除されました。
Oracle Universal Installerのクリーンアップが成功しました。


セッション終了時にノード'discus164,discus264'でrootとして'rm -rf /etc/oraInst.loc'を実行します。

Oracleインストールにより、一時ディレクトリが正常にクリーンアップされました。
#######################################################################


############# ORACLE DEINSTALL & DECONFIG TOOL END #############

[grid@discus164 deinstall]$





これまでのあらすじ
Mac de Oracle - 10万円未満 de RAC (11g編)#28

VirtualBox de RAC (Oracle11g R1編) #1
VirtualBox de RAC (Oracle11g R1編) #2



VirtualBox de Oracle11g R2 RAC #1
VirtualBox de Oracle11g R2 RAC #2 - 事前調査など…
VirtualBox de Oracle11g R2 RAC #3
VirtualBox de Oracle11g R2 RAC #4
VirtualBox de Oracle11g R2 RAC #5
VirtualBox de Oracle11g R2 RAC #6
VirtualBox de Oracle11g R2 RAC #7
VirtualBox de Oracle11g R2 RAC #8
VirtualBox de Oracle11g R2 RAC #9
VirtualBox de Oracle11g R2 RAC #10
VirtualBox de Oracle11g R2 RAC #11
VirtualBox de Oracle11g R2 RAC #12
VirtualBox de Oracle11g R2 RAC #13
VirtualBox de Oracle11g R2 RAC #14
VirtualBox de Oracle11g R2 RAC #15
VirtualBox de Oracle11g R2 RAC #16
VirtualBox de Oracle11g R2 RAC #17
VirtualBox de Oracle11g R2 RAC #18
VirtualBox de Oracle11g R2 RAC #19

| | コメント (0) | トラックバック (0)

2011年1月 4日 (火)

VirtualBox de Oracle11g R2 RAC #19

VirtualBox de Oracle11g R2 RACのつづき。

いよいよデータベースの作成です。 :)

  1. ハードウェア構成(VMなのでVMの構成も含めて)、ソフトウェア構成など
  2. Linux (CentOS 5.5 x86_64)のインストール
  3. Openfiler2.3 x86のインストール
  4. Openfiler2.3 x86によるiSCSIボリュームの構成
  5. Oracle RACノードでのiSCSIボリュームの構成 その1その2その3
  6. Oracle所有者、Oracle Grid Infrastructureユーザの作成と関連ディレクトリの作成及び環境変数の設定
  7. Oracle向けLinuxサーバーの構成(カーネルパラメータの設定)
  8. Oracle RACノード間リモートアクセスの構成とntpの構成
    sshの構成は念のために行った、多分、実施しなくても大丈夫だと思うけど…ついでなので、ちょいと意地悪な実験をしてみた)
  9. ローカルネームサーバの構成
  10. Oracle RACノード構成ファイルの確認
  11. Oracle Automatic Storage Management(ASMLib 2.0.5 x84_64)のインストール及び構成
  12. Oracle11g R2 11.2.0.1.0 RACインストール事前作業
  13. Oracle11g R2 11.2.0.1.0 Grid Infrastractureのインストール
  14. Oracle11g R2 11.2.0.1.0 Database softwareのインストール
  15. Oracle11g R2 11.2.0.1.0 examplesのインストール
  16. Oracle Cluster databaseの作成
  17. Net Serviceの確認
  18. Oralce Grid InsfastructureとDatabase構成の確認
  19. Clusterの開始と停止の確認
  20. 簡単なTransparent Application Failover (TAF)の確認

Oracle Cluster databaseの作成


Screenshot981

映像を見てもお分かりだと思いますが、VirtualBox上でクラスタデータベースを作成するとほぼ100%、DBCAの最後のダイアログを表示後DBCAを起動したVMが固まります。
Oracle11g R1 RACをVirtualBox上で構築した時と同じ症状です。DBCAのダイアログ上、データベースは作成されましたと表示されているのでそれを信じるばかり (^^;;;

念のため1時間ほど放置したあと、固まったVMは強制終了、残るノードはCentOSをシャットダウンします。その後、Openfiler、RACの両ノードを起動します。(ノード間の処理で固まっているようで実は処理に時間を要していることがなんどかあったので…念のため)

grid infrastructureユーザからcrsctlコマンドで状態を確認した結果は以下。(ちなみに、VM再起動後の状態)

[grid@discus164 ˜]$ crsctl status resource -t
--------------------------------------------------------------------------------
NAME TARGET STATE SERVER STATE_DETAILS
--------------------------------------------------------------------------------
Local Resources
--------------------------------------------------------------------------------
ora.CRS.dg
ONLINE ONLINE discus164
ONLINE ONLINE discus264
ora.DATA.dg
ONLINE ONLINE discus164
ONLINE ONLINE discus264
ora.FRA.dg
ONLINE ONLINE discus164
ONLINE ONLINE discus264
ora.LISTENER.lsnr
ONLINE ONLINE discus164
ONLINE ONLINE discus264
ora.asm
ONLINE ONLINE discus164 Started
ONLINE ONLINE discus264 Started
ora.eons
ONLINE ONLINE discus164
ONLINE ONLINE discus264
ora.gsd
OFFLINE OFFLINE discus164
OFFLINE OFFLINE discus264
ora.net1.network
ONLINE ONLINE discus164
ONLINE ONLINE discus264
ora.ons
ONLINE ONLINE discus164
ONLINE ONLINE discus264
ora.registry.acfs
ONLINE ONLINE discus164
ONLINE ONLINE discus264
--------------------------------------------------------------------------------
Cluster Resources
--------------------------------------------------------------------------------
ora.LISTENER_SCAN1.lsnr
1 ONLINE ONLINE discus264
ora.LISTENER_SCAN2.lsnr
1 ONLINE ONLINE discus164
ora.LISTENER_SCAN3.lsnr
1 ONLINE ONLINE discus164
ora.discus164.vip
1 ONLINE ONLINE discus164
ora.discus264.vip
1 ONLINE ONLINE discus264
ora.oc4j
1 OFFLINE OFFLINE
ora.orcl.db
1 ONLINE ONLINE discus164 Open
2 ONLINE ONLINE discus264 Open
ora.scan1.vip
1 ONLINE ONLINE discus264
ora.scan2.vip
1 ONLINE ONLINE discus164
ora.scan3.vip
1 ONLINE ONLINE discus164
[grid@discus164 ˜]$


[oracle@discus164 ˜]$ sqlplus /nolog

SQL*Plus: Release 11.2.0.1.0 Production on 火 11月 30 14:54:50 2010

Copyright (c) 1982, 2009, Oracle. All rights reserved.

SQL> conn / as sysdba
パスワードを入力してください:
接続されました。
SQL> set linesize 132
SQL> select * from gv$version;

INST_ID BANNER
---------- --------------------------------------------------------------------------------
1 Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
1 PL/SQL Release 11.2.0.1.0 - Production
1 CORE 11.2.0.1.0 Production
1 TNS for Linux: Version 11.2.0.1.0 - Production
1 NLSRTL Version 11.2.0.1.0 - Production
2 Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
2 PL/SQL Release 11.2.0.1.0 - Production
2 CORE 11.2.0.1.0 Production
2 TNS for Linux: Version 11.2.0.1.0 - Production
2 NLSRTL Version 11.2.0.1.0 - Production

10行が選択されました。

SQL>

ふ〜、なんとかできたようですね。 とりあえず遊べそうです。

次回へつづく。 Grid Infrastructure周りはもっと調べないと…覚える必要のあることはまだまだ多い (^^;;

Oracle Clusterware管理およびデプロイメント・ガイド 11gリリース2(11.2非推奨のサブプログラムまたはコマンド…このマニュアルもちゃんと読んでおかないとな。><






これまでのあらすじ
Mac de Oracle - 10万円未満 de RAC (11g編)#28

VirtualBox de RAC (Oracle11g R1編) #1
VirtualBox de RAC (Oracle11g R1編) #2



VirtualBox de Oracle11g R2 RAC #1
VirtualBox de Oracle11g R2 RAC #2 - 事前調査など…
VirtualBox de Oracle11g R2 RAC #3
VirtualBox de Oracle11g R2 RAC #4
VirtualBox de Oracle11g R2 RAC #5
VirtualBox de Oracle11g R2 RAC #6
VirtualBox de Oracle11g R2 RAC #7
VirtualBox de Oracle11g R2 RAC #8
VirtualBox de Oracle11g R2 RAC #9
VirtualBox de Oracle11g R2 RAC #10
VirtualBox de Oracle11g R2 RAC #11
VirtualBox de Oracle11g R2 RAC #12
VirtualBox de Oracle11g R2 RAC #13
VirtualBox de Oracle11g R2 RAC #14
VirtualBox de Oracle11g R2 RAC #15
VirtualBox de Oracle11g R2 RAC #16
VirtualBox de Oracle11g R2 RAC #17
VirtualBox de Oracle11g R2 RAC #18

| | コメント (0) | トラックバック (0)

2011年1月 3日 (月)

VirtualBox de Oracle11g R2 RAC #18

VirtualBox de Oracle11g R2 RACのつづきです。

インストールしなくてもいいんだけどいろいろと試したくなったときは便利なので、次いでにexamplesもインストール。

  1. ハードウェア構成(VMなのでVMの構成も含めて)、ソフトウェア構成など
  2. Linux (CentOS 5.5 x86_64)のインストール
  3. Openfiler2.3 x86のインストール
  4. Openfiler2.3 x86によるiSCSIボリュームの構成
  5. Oracle RACノードでのiSCSIボリュームの構成 その1その2その3
  6. Oracle所有者、Oracle Grid Infrastructureユーザの作成と関連ディレクトリの作成及び環境変数の設定
  7. Oracle向けLinuxサーバーの構成(カーネルパラメータの設定)
  8. Oracle RACノード間リモートアクセスの構成とntpの構成
    sshの構成は念のために行った、多分、実施しなくても大丈夫だと思うけど…ついでなので、ちょいと意地悪な実験をしてみた)
  9. ローカルネームサーバの構成
  10. Oracle RACノード構成ファイルの確認
  11. Oracle Automatic Storage Management(ASMLib 2.0.5 x84_64)のインストール及び構成
  12. Oracle11g R2 11.2.0.1.0 RACインストール事前作業
  13. Oracle11g R2 11.2.0.1.0 Grid Infrastractureのインストール
  14. Oracle11g R2 11.2.0.1.0 Database softwareのインストール
  15. Oracle11g R2 11.2.0.1.0 examplesのインストール
  16. Oracle Cluster databaseの作成
  17. Net Serviceの確認
  18. Oralce Grid InsfastructureとDatabase構成の確認
  19. Clusterの開始と停止の確認
  20. 簡単なTransparent Application Failover (TAF)の確認

Oracle11g R2 11.2.0.1.0 examplesのインストール

[oracle@discus164 database]$ 
[oracle@discus164 database]$
[oracle@discus164 database]$ cd ../examples
[oracle@discus164 examples]$ ll
合計 48
drwxr-xr-x 7 oracle oinstall 4096 8月 12 2009 doc
drwxr-xr-x 4 oracle oinstall 4096 8月 15 2009 install
drwxrwxr-x 2 oracle oinstall 4096 8月 15 2009 response
-rwxr-xr-x 1 oracle oinstall 3230 8月 15 2009 runInstaller
drwxr-xr-x 12 oracle oinstall 4096 8月 15 2009 stage
-rw-r--r-- 1 oracle oinstall 3419 8月 18 2009 welcome.html
[oracle@discus164 examples]$

[oracle@discus164 examples]$ ./runInstaller
Oracle Universal Installerを起動中です...
・・・中略・・・

Screenshot391

Screenshot621

Screenshot631

Screenshot641

Screenshot651

Screenshot661

Screenshot671

次回へつづく。






これまでのあらすじ
Mac de Oracle - 10万円未満 de RAC (11g編)#28

VirtualBox de RAC (Oracle11g R1編) #1
VirtualBox de RAC (Oracle11g R1編) #2



VirtualBox de Oracle11g R2 RAC #1
VirtualBox de Oracle11g R2 RAC #2 - 事前調査など…
VirtualBox de Oracle11g R2 RAC #3
VirtualBox de Oracle11g R2 RAC #4
VirtualBox de Oracle11g R2 RAC #5
VirtualBox de Oracle11g R2 RAC #6
VirtualBox de Oracle11g R2 RAC #7
VirtualBox de Oracle11g R2 RAC #8
VirtualBox de Oracle11g R2 RAC #9
VirtualBox de Oracle11g R2 RAC #10
VirtualBox de Oracle11g R2 RAC #11
VirtualBox de Oracle11g R2 RAC #12
VirtualBox de Oracle11g R2 RAC #13
VirtualBox de Oracle11g R2 RAC #14
VirtualBox de Oracle11g R2 RAC #15
VirtualBox de Oracle11g R2 RAC #16
VirtualBox de Oracle11g R2 RAC #17

| | コメント (0) | トラックバック (0)

VirtualBox de Oracle11g R2 RAC #17

VirtualBox de Oracle11g R2 RACのつづきです。

つづいてOracle11g R2 11.2.0.1.0 Database Installのインストール。
データベースは作成しないでソフトウェアだけのインストールを行います。

  1. ハードウェア構成(VMなのでVMの構成も含めて)、ソフトウェア構成など
  2. Linux (CentOS 5.5 x86_64)のインストール
  3. Openfiler2.3 x86のインストール
  4. Openfiler2.3 x86によるiSCSIボリュームの構成
  5. Oracle RACノードでのiSCSIボリュームの構成 その1その2その3
  6. Oracle所有者、Oracle Grid Infrastructureユーザの作成と関連ディレクトリの作成及び環境変数の設定
  7. Oracle向けLinuxサーバーの構成(カーネルパラメータの設定)
  8. Oracle RACノード間リモートアクセスの構成とntpの構成
    sshの構成は念のために行った、多分、実施しなくても大丈夫だと思うけど…ついでなので、ちょいと意地悪な実験をしてみた)
  9. ローカルネームサーバの構成
  10. Oracle RACノード構成ファイルの確認
  11. Oracle Automatic Storage Management(ASMLib 2.0.5 x84_64)のインストール及び構成
  12. Oracle11g R2 11.2.0.1.0 RACインストール事前作業
  13. Oracle11g R2 11.2.0.1.0 Grid Infrastractureのインストール
  14. Oracle11g R2 11.2.0.1.0 Database softwareのインストール
  15. Oracle11g R2 11.2.0.1.0 examplesのインストール
  16. Oracle Cluster databaseの作成
  17. Net Serviceの確認
  18. Oralce Grid InsfastructureとDatabase構成の確認
  19. Clusterの開始と停止の確認
  20. 簡単なTransparent Application Failover (TAF)の確認

ASMディスクグループの作成

Grid Infrastructureのインストール同様、Oracle所有者でもsshはパスフレーズありであらかじめ作成しておきます。OUIが作ってくれるだろうということを期待してね。

と、その前に、asmcaでOracleデータファイル及び、フラッシュ・リカバリ・エリア向けASMディスクグループを作成しておきました。
データファイル向けに+DATA、フラッシュ・リカバリ・エリア向けに+FRAというASMディスクグループを作成します。


Oracle11g R2 11.2.0.1.0 Database softwareのインストール

次に、Oracle Database 11g R2 11.2.0.1.0をインストールします。データベースは作成せず、別途dbcaを利用してデータベースを作成します。

省略していますが、お約束、root.shの実行もお忘れなく!



次回へつづく。






これまでのあらすじ
Mac de Oracle - 10万円未満 de RAC (11g編)#28

VirtualBox de RAC (Oracle11g R1編) #1
VirtualBox de RAC (Oracle11g R1編) #2



VirtualBox de Oracle11g R2 RAC #1
VirtualBox de Oracle11g R2 RAC #2 - 事前調査など…
VirtualBox de Oracle11g R2 RAC #3
VirtualBox de Oracle11g R2 RAC #4
VirtualBox de Oracle11g R2 RAC #5
VirtualBox de Oracle11g R2 RAC #6
VirtualBox de Oracle11g R2 RAC #7
VirtualBox de Oracle11g R2 RAC #8
VirtualBox de Oracle11g R2 RAC #9
VirtualBox de Oracle11g R2 RAC #10
VirtualBox de Oracle11g R2 RAC #11
VirtualBox de Oracle11g R2 RAC #12
VirtualBox de Oracle11g R2 RAC #13
VirtualBox de Oracle11g R2 RAC #14
VirtualBox de Oracle11g R2 RAC #15
VirtualBox de Oracle11g R2 RAC #16

| | コメント (0) | トラックバック (0)

VirtualBox de Oracle11g R2 RAC #16

VirtualBox de Oracle11g R2 RACのつづきです。

いよいよOracle11g R2 11.2.0.1.0 Grid Infrastractureのインストール♪

  1. ハードウェア構成(VMなのでVMの構成も含めて)、ソフトウェア構成など
  2. Linux (CentOS 5.5 x86_64)のインストール
  3. Openfiler2.3 x86のインストール
  4. Openfiler2.3 x86によるiSCSIボリュームの構成
  5. Oracle RACノードでのiSCSIボリュームの構成 その1その2その3
  6. Oracle所有者、Oracle Grid Infrastructureユーザの作成と関連ディレクトリの作成及び環境変数の設定
  7. Oracle向けLinuxサーバーの構成(カーネルパラメータの設定)
  8. Oracle RACノード間リモートアクセスの構成とntpの構成
    sshの構成は念のために行った、多分、実施しなくても大丈夫だと思うけど…ついでなので、ちょいと意地悪な実験をしてみた)
  9. ローカルネームサーバの構成
  10. Oracle RACノード構成ファイルの確認
  11. Oracle Automatic Storage Management(ASMLib 2.0.5 x84_64)のインストール及び構成
  12. Oracle11g R2 11.2.0.1.0 RACインストール事前作業
  13. Oracle11g R2 11.2.0.1.0 Grid Infrastractureのインストール
  14. Oracle11g R2 11.2.0.1.0 Database softwareのインストール
  15. Oracle11g R2 11.2.0.1.0 examplesのインストール
  16. Oracle Cluster databaseの作成
  17. Net Serviceの確認
  18. Oralce Grid InsfastructureとDatabase構成の確認
  19. Clusterの開始と停止の確認
  20. 簡単なTransparent Application Failover (TAF)の確認

Oracle11g R2 11.2.0.1.0 Grid Infrastractureのインストール

今回、確かめたかったこともあり、意図的にパスフレーズ付きでsshを手動構成しておいた。
その結果は…CVUの検査はパスするもののOUI上ではsshの構成がNGとなりOUIからsshの構成を行った。その後は問題なくインストールできた :) 便になったねOUI.

[grid@discus164 grid]$ ./runInstaller 
[1] 4417
[grid@discus164 grid]$ Oracle Universal Installerを起動中です...

一時領域の確認中: 120MBを超えている必要があります. 実際 32846MB 問題なし
スワップ領域の確認中: 150MBを超えている必要があります. 実際 5951MB 問題なし
モニターの確認中: 少なくとも256色表示するよう設定されている必要があります. 実際 16777216 問題なし
Oracle Universal Installerの起動を準備中 /tmp/OraInstall2010-11-29_01-51-19PM. お待ちください...


Root_shell



インストールの後半で、上記画面が表示されたら、いつものお約束、orainstRoot.shの実行とroot.shスクリプトの実行です!
RACを構成する全ノードのrootユーザで。最初にOUIを実行したノードで実行。成功したら以後残りのノードで実施(残りのノードでは平行実行可能だとか…今回は2ノードなので確認できず…)。

まず、OUIを実行したノードで実行!

[root@discus164 ˜]#
[root@discus164 ˜]# /u01/app/oraInventory/orainstRoot.sh
権限を変更中 /u01/app/oraInventory.
グループの読取り/書込み権限を追加中。
全ユーザーの読取り/書込み/実行権限を削除中。

グループ名の変更 /u01/app/oraInventory 宛先 oinstall.
スクリプトの実行が完了しました。

[root@discus164 ˜]#
[root@discus164 ˜]#
[root@discus164 ˜]# /u01/app/11.2.0/grid/root.sh
Running Oracle 11g root.sh script...

The following environment variables are set as:
ORACLE_OWNER= grid
ORACLE_HOME= /u01/app/11.2.0/grid

Enter the full pathname of the local bin directory: [/usr/local/bin]:
Copying dbhome to /usr/local/bin ...
Copying oraenv to /usr/local/bin ...
Copying coraenv to /usr/local/bin ...


Creating /etc/oratab file...

・・・中略・・・

profile reader pa cert TP
profile reader peer cert TP
peer user cert
pa user cert
Adding daemon to inittab
CRS-4123: Oracle High Availability Services has been started.
ohasd is starting
ADVM/ACFS is not supported on centos-release-5-5.el5.centos

CRS-2672: 'ora.gipcd'('discus164')の起動を試行しています

・・・中略・・・

CRS-2676: 'ora.ctssd'('discus164')の起動が成功しました

ASMは正常に作成され、起動しました。

ディスク・グループCRSは正常に作成されました。

clscfg: -install mode specified
Successfully accumulated necessary OCR keys.
Creating OCR keys for user 'root', privgrp 'root'..
Operation successful.
CRS-2672: 'ora.crsd'('discus164')の起動を試行しています
CRS-2676: 'ora.crsd'('discus164')の起動が成功しました
CRS-4256: Updating the profile
Successful addition of voting disk 5d6c953bf3aa4fe6bfff2a0f9b1e0d37.
Successfully replaced voting disk group with +CRS.
CRS-4256: Updating the profile
CRS-4266: Voting file(s) successfully replaced
## STATE File Universal Id File Name Disk group
-- ----- ----------------- --------- ---------
1. ONLINE 5d6c953bf3aa4fe6bfff2a0f9b1e0d37 (ORCL:CRSVOL1) [CRS]
Located 1 voting disk(s).
CRS-2673: 'ora.crsd'('discus164')の停止を試行しています

・・・中略・・・

CRS-2676: 'ora.asm'('discus164')の起動が成功しました
CRS-2672: 'ora.CRS.dg'('discus164')の起動を試行しています
CRS-2676: 'ora.CRS.dg'('discus164')の起動が成功しました

discus164 2010/11/29 14:21:13 /u01/app/11.2.0/grid/cdata/discus164/backup_20101129_142113.olr
Configure Oracle Grid Infrastructure for a Cluster ... succeeded
クラスタウェアのインベントリ・プロパティの更新中
Oracle Universal Installerを起動中です...

スワップ領域の確認中: 500MBを超えている必要があります. 実際 5951MB 問題なし
The inventory pointer is located at /etc/oraInst.loc
The inventory is located at /u01/app/oraInventory
'UpdateNodeList'が成功しました。
[root@discus164 ˜]#

ADVM/ACFS is not supported on centos-release-5-5.el5.centosという気になるメッセージがあったがこれはCentOSが正式にサポートされていないことが影響している。
一昨年暮れのエントリだけど、以下のブログが参考になるかも。

参考:
http://brianbontrager.blogspot.com/2009/09/learning-asm-breakin-rules-or-running.html

2011/1/4追記:
http://ivan.kartik.sk/index.php?show_article=49
リリースを偽装する方法もあるんだけどね。後者の方が楽は楽だけど元に戻すのが面倒だから今回はパスした。

簡単にリカバル方法がよくわかんなかったんでOracle Grid Infrastructureを一旦deinstallした。(これが一番わかりやすい!)
Oracle Grid Infrastructureをdeinstallコマンドで削除した記録は別途書くとして、一旦deinstallしたと思ってください!!!

ということで、OUIでOracle Grid Infrastractureをインストール。

orainstRoot.shを実行したところで、前述の参考ブログに記載されていたCentOS向け手当を行う。手当を行ってからroot.shを実行する。

orainstRoot.shを実行したところで、前述の参考ブログに記載されていたCentOS向け手当を行う。手当を行ってからroot.shを実行する。

CentOS上へのOracle Grid Infrastructureインストールでは大切(らしい)なので2度、書きましたよw

Oracle Grid Infrastructureユーザの$ORACLE_HOME/lib/osds_acfslib.pmの278行目以下にCentOSも正常に処理できるよう修正を加える。

[grid@discus164 ˜]$ su -
パスワード:
[root@discus164 ˜]# cd /u01/app/11.2.0/grid/lib
[root@discus164 lib]#
[root@discus164 lib]# cp -p osds_acfslib.pm osds_acfslib.pm.org
[root@discus164 lib]#
[root@discus164 lib]# vi osds_acfslib.pm
[root@discus164 lib]#
[root@discus164 lib]# diff -u osds_acfslib.pm osds_acfslib.pm.org
--- osds_acfslib.pm 2010/11/29 17:19:00.000000000 +0900
+++ osds_acfslib.pm.org 2009-07-02 11:13:48.000000000 +0900
@@ -278,8 +278,7 @@
# OK, now check to see if we support this release
$supported = 0;
if (($release =˜ /enterprise-release-5/) ||
- ($release =˜ /redhat-release-5/) ||
- ($release =˜ /centos-release-5/))
+ ($release =˜ /redhat-release-5/))
{
# Redhat 5
$supported = 1;
[root@discus164 lib]#

多分上記の修正だけで対処できると思うのだが、自信がないので以下のこともやっておいた… 写経になっております。m(_ _)m (RACを構成する全ノードのrootユーザで実施)

[root@discus164 ˜]# mkdir /lib/modules/2.6.18-194.17.1.el5/extra/usm
[root@discus164 ˜]#
[root@discus164 ˜]#
[root@discus164 ˜]# ls /u01/app/11.2.0/grid/install/usm/EL5/x86_64/2.6.18-8/2.6.18-8.el5-x86_64/bin/*ko
/u01/app/11.2.0/grid/install/usm/EL5/x86_64/2.6.18-8/2.6.18-8.el5-x86_64/bin/oracleacfs.ko
/u01/app/11.2.0/grid/install/usm/EL5/x86_64/2.6.18-8/2.6.18-8.el5-x86_64/bin/oracleadvm.ko
/u01/app/11.2.0/grid/install/usm/EL5/x86_64/2.6.18-8/2.6.18-8.el5-x86_64/bin/oracleoks.ko
[root@discus164 ˜]#
[root@discus164 ˜]#
[root@discus164 ˜]# cp /u01/app/11.2.0/grid/install/usm/EL5/x86_64/2.6.18-8/2.6.18-8.el5-x86_64/bin/*ko /lib/modules/2.6.18-194.17.1.el5/extra/usm
[root@discus164 ˜]# chmod 744 /lib/modules/2.6.18-194.17.1.el5/extra/usm
[root@discus164 ˜]#
[root@discus164 ˜]# depmod
[root@discus164 ˜]#
[root@discus164 ˜]# cp /u01/app/11.2.0/grid/install/usm/EL5/x86_64/2.6.18-8/2.6.18-8.el5-x86_64/bin/acfsdbg /sbin
[root@discus164 ˜]# chmod 755 /sbin/acfsdbg


ここまでの作業を終えたらOUIでOracle Grid InfrastructureをOUIでインストールする。手順は前述の映像を見てくださいね。

お約束のorainstRoot.shそれに続いて、root.shをOUIを起動したノードで実施、その後、残りのノードでも同様にrootユーザで実施する。

root.shの実行。こんどは大丈夫でしょうか〜〜〜〜。

[root@discus164 grid]# ./root.sh
Running Oracle 11g root.sh script...

The following environment variables are set as:
ORACLE_OWNER= grid
ORACLE_HOME= /u01/app/11.2.0/grid

Enter the full pathname of the local bin directory: [/usr/local/bin]:
The file "dbhome" already exists in /usr/local/bin. Overwrite it? (y/n)
[n]: y
Copying dbhome to /usr/local/bin ...
The file "oraenv" already exists in /usr/local/bin. Overwrite it? (y/n)
[n]: y
Copying oraenv to /usr/local/bin ...
The file "coraenv" already exists in /usr/local/bin. Overwrite it? (y/n)
[n]: y
Copying coraenv to /usr/local/bin ...


Creating /etc/oratab file...
Entries will be added to the /etc/oratab file as needed by
Database Configuration Assistant when a database is created
Finished running generic part of root.sh script.
Now product-specific root actions will be performed.
2010-11-29 17:23:44: Parsing the host name
2010-11-29 17:23:44: Checking for super user privileges
2010-11-29 17:23:44: User has super user privileges

Using configuration parameter file: /u01/app/11.2.0/grid/crs/install/crsconfig_params
Creating trace directory
LOCAL ADD MODE
Creating OCR keys for user 'root', privgrp 'root'..
Operation successful.
root wallet
root wallet cert
root cert export
peer wallet
profile reader wallet
pa wallet
peer wallet keys
pa wallet keys
peer cert request
pa cert request
peer cert
pa cert
peer root cert TP
profile reader root cert TP
pa root cert TP
peer pa cert TP
pa peer cert TP
profile reader pa cert TP
profile reader peer cert TP
peer user cert
pa user cert
Adding daemon to inittab
CRS-4123: Oracle High Availability Services has been started.
ohasd is starting
CRS-2672: 'ora.gipcd'('discus164')の起動を試行しています
CRS-2672: 'ora.mdnsd'('discus164')の起動を試行しています
CRS-2676: 'ora.gipcd'('discus164')の起動が成功しました
CRS-2676: 'ora.mdnsd'('discus164')の起動が成功しました
CRS-2672: 'ora.gpnpd'('discus164')の起動を試行しています
CRS-2676: 'ora.gpnpd'('discus164')の起動が成功しました
CRS-2672: 'ora.cssdmonitor'('discus164')の起動を試行しています
CRS-2676: 'ora.cssdmonitor'('discus164')の起動が成功しました
CRS-2672: 'ora.cssd'('discus164')の起動を試行しています
CRS-2672: 'ora.diskmon'('discus164')の起動を試行しています
CRS-2676: 'ora.diskmon'('discus164')の起動が成功しました
CRS-2676: 'ora.cssd'('discus164')の起動が成功しました
CRS-2672: 'ora.ctssd'('discus164')の起動を試行しています
CRS-2676: 'ora.ctssd'('discus164')の起動が成功しました

ASMは正常に作成され、起動しました。

ディスク・グループCRSは正常に作成されました。

clscfg: -install mode specified
Successfully accumulated necessary OCR keys.
Creating OCR keys for user 'root', privgrp 'root'..
Operation successful.
CRS-2672: 'ora.crsd'('discus164')の起動を試行しています
CRS-2676: 'ora.crsd'('discus164')の起動が成功しました
CRS-4256: Updating the profile
Successful addition of voting disk 8f431fe5d1304fd9bf6ad331d3aef536.
Successfully replaced voting disk group with +CRS.
CRS-4256: Updating the profile
CRS-4266: Voting file(s) successfully replaced
## STATE File Universal Id File Name Disk group
-- ----- ----------------- --------- ---------
1. ONLINE 8f431fe5d1304fd9bf6ad331d3aef536 (ORCL:CRSVOL1) [CRS]
Located 1 voting disk(s).
CRS-2673: 'ora.crsd'('discus164')の停止を試行しています
CRS-2677: 'ora.crsd'('discus164')の停止が成功しました
CRS-2673: 'ora.asm'('discus164')の停止を試行しています
CRS-2677: 'ora.asm'('discus164')の停止が成功しました
CRS-2673: 'ora.ctssd'('discus164')の停止を試行しています
CRS-2677: 'ora.ctssd'('discus164')の停止が成功しました
CRS-2673: 'ora.cssdmonitor'('discus164')の停止を試行しています
CRS-2677: 'ora.cssdmonitor'('discus164')の停止が成功しました
CRS-2673: 'ora.cssd'('discus164')の停止を試行しています
CRS-2677: 'ora.cssd'('discus164')の停止が成功しました
CRS-2673: 'ora.gpnpd'('discus164')の停止を試行しています
CRS-2677: 'ora.gpnpd'('discus164')の停止が成功しました
CRS-2673: 'ora.gipcd'('discus164')の停止を試行しています
CRS-2677: 'ora.gipcd'('discus164')の停止が成功しました
CRS-2673: 'ora.mdnsd'('discus164')の停止を試行しています
CRS-2677: 'ora.mdnsd'('discus164')の停止が成功しました
CRS-2672: 'ora.mdnsd'('discus164')の起動を試行しています
CRS-2676: 'ora.mdnsd'('discus164')の起動が成功しました
CRS-2672: 'ora.gipcd'('discus164')の起動を試行しています
CRS-2676: 'ora.gipcd'('discus164')の起動が成功しました
CRS-2672: 'ora.gpnpd'('discus164')の起動を試行しています
CRS-2676: 'ora.gpnpd'('discus164')の起動が成功しました
CRS-2672: 'ora.cssdmonitor'('discus164')の起動を試行しています
CRS-2676: 'ora.cssdmonitor'('discus164')の起動が成功しました
CRS-2672: 'ora.cssd'('discus164')の起動を試行しています
CRS-2672: 'ora.diskmon'('discus164')の起動を試行しています
CRS-2676: 'ora.diskmon'('discus164')の起動が成功しました
CRS-2676: 'ora.cssd'('discus164')の起動が成功しました
CRS-2672: 'ora.ctssd'('discus164')の起動を試行しています
CRS-2676: 'ora.ctssd'('discus164')の起動が成功しました
CRS-2672: 'ora.asm'('discus164')の起動を試行しています
CRS-2676: 'ora.asm'('discus164')の起動が成功しました
CRS-2672: 'ora.crsd'('discus164')の起動を試行しています
CRS-2676: 'ora.crsd'('discus164')の起動が成功しました
CRS-2672: 'ora.evmd'('discus164')の起動を試行しています
CRS-2676: 'ora.evmd'('discus164')の起動が成功しました
CRS-2672: 'ora.asm'('discus164')の起動を試行しています
CRS-2676: 'ora.asm'('discus164')の起動が成功しました
CRS-2672: 'ora.CRS.dg'('discus164')の起動を試行しています
CRS-2676: 'ora.CRS.dg'('discus164')の起動が成功しました
CRS-2672: 'ora.registry.acfs'('discus164')の起動を試行しています
CRS-2676: 'ora.registry.acfs'('discus164')の起動が成功しました

discus164 2010/11/29 17:30:15 /u01/app/11.2.0/grid/cdata/discus164/backup_20101129_173015.olr
パッケージインストールの準備中...
cvuqdisk-1.0.7-1
Configure Oracle Grid Infrastructure for a Cluster ... succeeded
クラスタウェアのインベントリ・プロパティの更新中
Oracle Universal Installerを起動中です...

スワップ領域の確認中: 500MBを超えている必要があります. 実際 5951MB 問題なし
The inventory pointer is located at /etc/oraInst.loc
The inventory is located at /u01/app/oraInventory
'UpdateNodeList'が成功しました。
[root@discus164 grid]#

お〜〜、でけた。

では、他のノードでも実行
残りのノードでも同様の操作実施後root.sh実行

[root@discus264 grid]# ./root.sh
Running Oracle 11g root.sh script...

The following environment variables are set as:
ORACLE_OWNER= grid
ORACLE_HOME= /u01/app/11.2.0/grid

Enter the full pathname of the local bin directory: [/usr/local/bin]:
The file "dbhome" already exists in /usr/local/bin. Overwrite it? (y/n)
[n]: y
Copying dbhome to /usr/local/bin ...
The file "oraenv" already exists in /usr/local/bin. Overwrite it? (y/n)
[n]: y
Copying oraenv to /usr/local/bin ...
The file "coraenv" already exists in /usr/local/bin. Overwrite it? (y/n)
[n]: y
Copying coraenv to /usr/local/bin ...


Creating /etc/oratab file...
Entries will be added to the /etc/oratab file as needed by
Database Configuration Assistant when a database is created
Finished running generic part of root.sh script.
Now product-specific root actions will be performed.
2010/11/29 17:45:30: Parsing the host name
2010/11/29 17:45:30: Checking for super user privileges
2010/11/29 17:45:30: User has super user privileges
Using configuration parameter file: /u01/app/11.2.0/grid/crs/install/crsconfig_params
Creating trace directory
LOCAL ADD MODE
Creating OCR keys for user 'root', privgrp 'root'..
Operation successful.
Adding daemon to inittab
CRS-4123: Oracle High Availability Services has been started.
ohasd is starting
CRS-4402: CSSデーモンが排他モードで開始されましたが、ノードdiscus164、番号1のアクティブCSSデーモンが検出されたため中断します
CRS-2673: 'ora.cssdmonitor'('discus264')の停止を試行しています
CRS-2677: 'ora.cssdmonitor'('discus264')の停止が成功しました
CRS-2673: 'ora.gpnpd'('discus264')の停止を試行しています
CRS-2677: 'ora.gpnpd'('discus264')の停止が成功しました
CRS-2673: 'ora.gipcd'('discus264')の停止を試行しています
CRS-2677: 'ora.gipcd'('discus264')の停止が成功しました
CRS-2673: 'ora.mdnsd'('discus264')の停止を試行しています
CRS-2677: 'ora.mdnsd'('discus264')の停止が成功しました
An active cluster was found during exclusive startup, restarting to join the cluster
CRS-2672: 'ora.mdnsd'('discus264')の起動を試行しています
CRS-2676: 'ora.mdnsd'('discus264')の起動が成功しました
CRS-2672: 'ora.gipcd'('discus264')の起動を試行しています
CRS-2676: 'ora.gipcd'('discus264')の起動が成功しました
CRS-2672: 'ora.gpnpd'('discus264')の起動を試行しています
CRS-2676: 'ora.gpnpd'('discus264')の起動が成功しました
CRS-2672: 'ora.cssdmonitor'('discus264')の起動を試行しています
CRS-2676: 'ora.cssdmonitor'('discus264')の起動が成功しました
CRS-2672: 'ora.cssd'('discus264')の起動を試行しています
CRS-2672: 'ora.diskmon'('discus264')の起動を試行しています
CRS-2676: 'ora.diskmon'('discus264')の起動が成功しました
CRS-2676: 'ora.cssd'('discus264')の起動が成功しました
CRS-2672: 'ora.ctssd'('discus264')の起動を試行しています
CRS-2676: 'ora.ctssd'('discus264')の起動が成功しました
CRS-2672: 'ora.drivers.acfs'('discus264')の起動を試行しています
CRS-2676: 'ora.drivers.acfs'('discus264')の起動が成功しました
CRS-2672: 'ora.asm'('discus264')の起動を試行しています
CRS-2676: 'ora.asm'('discus264')の起動が成功しました
CRS-2672: 'ora.crsd'('discus264')の起動を試行しています
CRS-2676: 'ora.crsd'('discus264')の起動が成功しました
CRS-2672: 'ora.evmd'('discus264')の起動を試行しています
CRS-2676: 'ora.evmd'('discus264')の起動が成功しました

discus264 2010/11/29 17:48:45 /u01/app/11.2.0/grid/cdata/discus264/backup_20101129_174845.olr
パッケージインストールの準備中...
cvuqdisk-1.0.7-1
Configure Oracle Grid Infrastructure for a Cluster ... succeeded
クラスタウェアのインベントリ・プロパティの更新中
Oracle Universal Installerを起動中です...

スワップ領域の確認中: 500MBを超えている必要があります. 実際 5951MB 問題なし
The inventory pointer is located at /etc/oraInst.loc
The inventory is located at /u01/app/oraInventory
'UpdateNodeList'が成功しました。
[root@discus264 grid]#


root.sh実行おわり!


Grid Infrastructureインストール後の簡単な確認(RACを構成する全ノードのgrid infrastructureユーザ及び、rootユーザで実施)

crsの状態確認(RACを構成する全ノードのGrid Infrastructureユーザで