2017年4月23日 (日)

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

Previously on Mac De Oracle

前回は、Data PumpのschemaモードでschemaごとまるっとMviewサイトを複製してみたところまで、でした。

エントリには記載していなかったログを見ていて驚いた!ことを調査してみる回として”その4と1/2”にしてみましたw

ほんと、癖モノですよねーMviewも!w



なに驚いたのか、その内容から

Data Pumpを利用しMviewを複製する今回の目的の一つである、完全リフレッシュしないでMviewを複製するという目論見が外れていた!!!?

と思われるログが残っていました。

以下のログは、Data Pumpのインポートログとその後のMview関連ビューをリストしたものですが、赤字部分に注目

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/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/MATERIALIZED_VIEW
Processing object type SCHEMA_EXPORT/JOB
Processing object type SCHEMA_EXPORT/REFRESH_GROUP
Job "SYSTEM"."SYS_IMPORT_FULL_01" successfully completed at Sun Apr 23 20:30:19 2017 elapsed 0 00:00:28

インポート直後、2つのMviewの状態を確認したログですが、B列(DBA_REFRESH.BROKEN列)はどちらも”N"となっておりリフレッシュジョブは停止中です。問題は下のLAST_REF列(DBA_MVIEWS.LAST_REFRESH_TYPE列)がCOMPLETEとなっているというところです。
CON_ID=5は、PDB:ORCL2なのでインポートを行ったPDBを指します。DBA_MVIEWS.LAST_REFRESH_TYPE列は、「最新のリフレッシュに使用されるメソッド:COMPLETE- 最新のリフレッシュが完了した。」と説明されています。??
完全リフレッシュされちゃったの??? 

こうなったらData PumpでMviewが作成された時に完全リフレッシュされちゃうのか、されないのか確認するしかありませんねw。

ROWNER               RNAME                  REFGROUP        JOB B INTERVAL             NEXT_DATE               CON_ID
-------------------- -------------------- ---------- ---------- - -------------------- ------------------- ----------
MVIEW_SCHEMA1 MV_MASTER 61 81 N sysdate+5/1440 2017/04/23 20:38:31 5
MVIEW_SCHEMA1 MV_MASTER 61 81 N sysdate+5/1440 2017/04/23 20:43:30 3

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

ということで、確認してみました。

最初は、前回と同じPDB:ORCLのスキーマ間で基本レプリケーション環境を作成し、リフレッシュジョブを停止するところまで(何をやっているかはDDLやSQL文を見ればわかると思うので略。わからないと言う方は前回の内容で確認ください。)

orcl12c@SYS> show pdbs

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

orcl@SYS> create directory workdir as '/u01/userhome/oracle';

Directory created.

orcl@SYS> create user master_schema identified by welcome1
2 default tablespace users
3 temporary tablespace temp
4 quota unlimited on users;

User created.

orcl@SYS> grant create session, create table to master_schema;

Grant succeeded.

orcl@SYS> create user mview_schema1 identified by welcome1
2 default tablespace users
3 temporary tablespace temp
4 quota unlimited on users;

User created.

orcl@SYS> grant create session, create table, create database link, create materialized view to mview_schema1;

Grant succeeded.

orcl@SYS> conn master_schema/welcome1@orcl
Connected.
orcl@MASTER_SCHEMA> create table master (
2 id number primary key
3 ,foo varchar2(100));

Table created.

orcl@MASTER_SCHEMA> insert into master values(1,'foo');

1 row created.

orcl@MASTER_SCHEMA> insert into master values(2,'bar');

1 row created.

orcl@MASTER_SCHEMA> commit;

Commit complete.

orcl@MASTER_SCHEMA> create materialized view log on master;

Materialized view log created.

orcl@MASTER_SCHEMA> conn mview_schema1/welcome1@orcl
Connected.
orcl@MVIEW_SCHEMA1> create database link to_master_schema
2 connect to master_schema identified by welcome1
3 using 'ORCL';

Database link created.

orcl@MVIEW_SCHEMA1> select count(*) from master@to_master_schema;

COUNT(*)
----------
2

orcl@MVIEW_SCHEMA1> create materialized view mv_master
2 refresh fast on demand
3 start with sysdate next sysdate+5/1440
4 as select * from master@to_master_schema;

Materialized view created.

orcl@MVIEW_SCHEMA1> select count(1) from mv_master;

COUNT(1)
----------
2

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/04/23 20:12:06 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/04/23 20:07:06 2017/04/23 20:12:06 sysdate+5/1440 0 dbms_refresh.refresh('"MVIEW_SCHEMA1"."MV_MASTER"');

orcl12c@SYS> conn mview_schema1/welcome1@orcl
Connected.
orcl@MVIEW_SCHEMA1> exec dbms_job.broken(job=>81,broken=>true);

PL/SQL procedure successfully completed.

orcl@MVIEW_SCHEMA1> @mview_info_c

Session altered.

ROWNER RNAME REFGROUP JOB B INTERVAL NEXT_DATE CON_ID
-------------------- -------------------- ---------- ---------- - -------------------- ------------------- ----------
MVIEW_SCHEMA1 MV_MASTER 61 81 Y sysdate+5/1440 4000/01/01 00:00:00 3

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

JOB LOG_USER SCHEMA_USER LAST_DATE NEXT_DATE INTERVAL FAILURES WHAT    CON_ID
---------- -------------------- -------------------- ------------------- ------------------- -------------------- ---------- ------------------------------------------------------------ ----------
81 MVIEW_SCHEMA1 MVIEW_SCHEMA1 2017/04/23 20:07:06 4000/01/01 00:00:00 sysdate+5/1440 0 dbms_refresh.refresh('"MVIEW_SCHEMA1"."MV_MASTER"'); 3


ここまでは同じなのですが、Data PumpでMviewをインポートする際に完全リフレッシュしているのか?どうかを確認するため、リフレッシュジョブ停止後、マスター表を100行に増幅しておきます。
こうしておけば、Data PumpでMviewがインポートされる際、完全リフレッシュが行われていたとしたら、インポート後のMviewは100行になっているはずだし、
 逆に2行のままなら、LAST_REFRESH_TYPE=COMPLETEにはなっているものの実際には完全リフレッシュしなていない、という、なんともわかりづらい状況になるから気にすんな、ってことが見えてくるはず。

orcl12c@SYS> conn master_schema/welcome1@orcl
Connected.
orcl@MASTER_SCHEMA> begin for i in 3..100 loop insert into master values(i,'data#'||i); end loop; end;
2 /

PL/SQL procedure successfully completed.

orcl@MASTER_SCHEMA> commit;

Commit complete.

orcl@MASTER_SCHEMA> select count(1) from master;

COUNT(1)
----------
100

orcl@MASTER_SCHEMA> conn mview_schema1/welcome1@orcl
Connected.
orcl@MVIEW_SCHEMA1> select count(1) from mv_master;

COUNT(1)
----------
2

エクスポートは2行となっているので、Mviewから2行エクスポートされているのは間違いない!(マスター表は100行!)

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 Sun Apr 23 20:28:25 2017 elapsed 0 00:00:54

PDB:ORCL2にて、Data Pump作業向けディレクトリオブジェクトを作成

[oracle@vbgeneric oracle]$ sqlplus sys/oracle@orcl2 as sysdba

SQL*Plus: Release 12.1.0.2.0 Production on Sun Apr 23 20:29:07 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@SYS> create directory workdir as '/u01/userhome/oracle';

Directory created.


インポートでも見ての通り、2行だけインポートされています!(ステータスが紛らわしい説が強くなってきました!!!)

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 Sun Apr 23 20:30:19 2017 elapsed 0 00:00:28


インポート後、どちらのリフレッシュジョブも停止中ですが、1箇所違いがみられます。
そう、インポートしたMviewのLAST_REF(DBA_MVIEWS.LAST_REFRESH_TYPE)がCOMPLETEになっています。前半に書いたとおりの状態が再現!!! なにっ!!

orcl12c@SYS> @mview_info_c
Connected.

Session altered.

ROWNER RNAME REFGROUP JOB B INTERVAL NEXT_DATE CON_ID
-------------------- -------------------- ---------- ---------- - -------------------- ------------------- ----------
MVIEW_SCHEMA1 MV_MASTER 61 81 Y sysdate+5/1440 4000/01/01 00:00:00 3
MVIEW_SCHEMA1 MV_MASTER 61 81 Y sysdate+5/1440 4000/01/01 00:00:00 5

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

JOB LOG_USER SCHEMA_USER LAST_DATE NEXT_DATE INTERVAL FAILURES WHAT CON_ID
---------- -------------------- -------------------- ------------------- ------------------- -------------------- ---------- ------------------------------------------------------------ ----------
81 MVIEW_SCHEMA1 MVIEW_SCHEMA1 2017/04/23 20:07:06 4000/01/01 00:00:00 sysdate+5/1440 0 dbms_refresh.refresh('"MVIEW_SCHEMA1"."MV_MASTER"'); 3
81 MVIEW_SCHEMA1 MVIEW_SCHEMA1 4000/01/01 00:00:00 sysdate+5/1440 dbms_refresh.refresh('"MVIEW_SCHEMA1"."MV_MASTER"'); 5

PDB_NAME CON_ID
------------------------------ ----------
PDB$SEED 2
ORCL 3
ORDS 4
ORCL2 5

DBA_MVIEWSビューのLAST_REFRESH_TYPEはCOMPLETE(完全リフレッシュされた)と設定されていますが、本当なのでしょうか? PDB:ORCL2のMV_MASTER表が本当に完全リフレッシュされていたとしたら100行になっているはずですが。。。。

PDB:ORCLのMViewの行数をカウント、2行です(リフレッシュジョブが停止しているので変化なし)

orcl12c@SYS> conn mview_schema1/welcome1@orcl
Connected.
orcl@MVIEW_SCHEMA1> show con_id

CON_ID
------------------------------
3

orcl@MVIEW_SCHEMA1> show con_name

CON_NAME
------------------------------
ORCL

orcl@MVIEW_SCHEMA1> select count(1) from mv_master;

COUNT(1)
----------
2


さて、問題のPDB:ORCL2。。。。2行のまま!!!!! 
ということは、Data PumpによるMviewのインポートでは完全リフレッシュは行われず、エクスポートされた行数がそのままインポートされている!! ステータスが紛らわしい!! だけというのが真相のようです!

orcl@MVIEW_SCHEMA1> conn mview_schema1/welcome1@orcl2
Connected.
orcl2@MVIEW_SCHEMA1> show con_id

CON_ID
------------------------------
5

orcl2@MVIEW_SCHEMA1> show con_name

CON_NAME
------------------------------
ORCL2

orcl2@MVIEW_SCHEMA1> select count(1) from mv_master;

COUNT(1)
----------
2


ジョブを再開すると。。。マスターサイトと同期され各MViewは100行なっています。めでたしめでたし。

@> conn mview_schema1/welcome1@orcl
Connected.
orcl@MVIEW_SCHEMA1> exec dbms_job.broken(job=>81,broken=>false,next_date=>sysdate);

PL/SQL procedure successfully completed.

orcl@MVIEW_SCHEMA1> conn mview_schema1/welcome1@orcl2
Connected.
orcl2@MVIEW_SCHEMA1> exec dbms_job.broken(job=>81,broken=>false,next_date=>sysdate);

PL/SQL procedure successfully completed.

orcl12c@SYS> @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/04/23 20:44:05 5
MVIEW_SCHEMA1 MV_MASTER 61 81 N sysdate+5/1440 2017/04/23 20:43:30 3

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

JOB LOG_USER SCHEMA_USER LAST_DATE NEXT_DATE INTERVAL FAILURES WHAT CON_ID
---------- -------------------- -------------------- ------------------- ------------------- -------------------- ---------- ------------------------------------------------------------ ----------
81 MVIEW_SCHEMA1 MVIEW_SCHEMA1 2017/04/23 20:38:30 2017/04/23 20:43:30 sysdate+5/1440 0 dbms_refresh.refresh('"MVIEW_SCHEMA1"."MV_MASTER"'); 3
81 MVIEW_SCHEMA1 MVIEW_SCHEMA1 2017/04/23 20:39:05 2017/04/23 20:44:05 sysdate+5/1440 0 dbms_refresh.refresh('"MVIEW_SCHEMA1"."MV_MASTER"'); 5

orcl12c@SYS> conn mview_schema1/welcome1@orcl
Connected.
orcl@MVIEW_SCHEMA1> select count(1) from mv_master;

COUNT(1)
----------
100

orcl@MVIEW_SCHEMA1> conn mview_schema1/welcome1@orcl2
Connected.
orcl2@MVIEW_SCHEMA1> select count(1) from mv_master;

COUNT(1)
----------
100

やれやれ、お騒がせすぎるw 

次回へつづく。


参考:ログ中で利用したSQLスクリプト(mview_info_c.sql)のソース

conn sys/oracle@orcl12c as sysdba

col rowner for a20
col rname for a20
col mview_name for a30
col log_user for a20
col schema_user for a20
col interval for a20
col what for a60
alter session set nls_date_format='yyyy/mm/dd hh24:mi:ss';
select rowner,rname,refgroup,job,broken,interval,next_date,con_id from containers(dba_refresh) where rowner='MVIEW_SCHEMA1';
select mview_name,refresh_mode,refresh_method,last_refresh_type,after_fast_refresh,compile_state from containers(dba_mviews) where mview_name='MV_MASTER';
select job,log_user,schema_user,last_date,next_date,interval,failures,what from containers(dba_jobs) where log_user='MVIEW_SCHEMA1';




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へ複製

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

2017年4月22日 (土)

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

一回、おやすみしましたが、Previously on Mac De Oracle

前々回は、Data Pump、dbms_jobとdbms_schedulerの複雑な関係を紐解いてみました。

今回は、箸休めとして、schemaモードより上位のモードならMviewはMviewのまま複製や移行することは簡単に行えるよね。という確認だけしておこうと思います。
シンプルだと思わせておいて、細けーことやろうとすると一癖ある、まさに癖モノw ということで :)


まずは、おさらいから

data pumpのschemaモード向けSCHEMA_EXPORT_OBJECTSにはオブジェクトパスの定義でMviewに関連するオブジェクト全てが定義されています。

OBJECT_PATH                     COMMENTS
------------------------------- ------------------------------------------------------------
SCHEMA_EXPORT/DB_LINK Private database links in the selected schemas
SCHEMA_EXPORT/TABLE Tables in the selected schemas and their dependent objects
SCHEMA_EXPORT/MATERIALIZED_VIEW Materialized views
SCHEMA_EXPORT/JOB Jobs in the selected schemas
SCHEMA_EXPORT/REFRESH_GROUP Refresh groups in the selected schemas

一方、tableモード向けTABLE_EXPORT_OBJECTSには、Mview、リフレッシュに必要なJOBやREFRESH GROUPなどのオブジェクトパスが定義されていません。
tableモードでMviewを複製しようとすること自体に無理があるのは明らかですね。MViewとしてエクスポートしたくてもオプジェクトパスが定義されていないのですから。
表を対象としているモードだからそれ以外のオブジェクトパスが定義されていないんだよね〜と、無理やり納得しています:)

orcl@SYSTEM> r
1 select * from TABLE_EXPORT_OBJECTS where
2 object_path like '%/JOB'
3 or object_path like '%/MATERIALIZED_VIEW'
4* or object_path like '%/REFRESH_GROUP'

no rows selected

おさらいはこれくらいにして、schemaモードエクスポートで以下の図に示したようなMviewの複製が行えるか確認しておきます。

ポンチ絵のとおりではあるのですが、簡単に説明すると、
PDB:ORCLの異なるschema間で高速リフレッシュ可能なMviewがあり、Data Pumpのschemaモードを利用して異なるPDBにMviewを複製するというシナリオです。
複製後はMviewサイトが2つになります。

20170415_14044


なぜ、異なるDB(PDB)にMVIEWを複製するシナリオにしたかって?
理由は、DBMS_JOBのジョブは、同一データベース(MTA構成であればPDB毎)でJOB番号により一意に管理されています。
DBMS_JOBのジョブを同一データベース内でexport/importした場合、ジョブが単純に複製される事になりJOB番号の一意制約エラーとなりimportに失敗します。
importできなければ再作成すれば問題ないわけですが、MTA環境なのでわざわざ同一PDB内に作成する必要はないわけです。(手数を減らせるならその方が楽ですから)

エクスポートする前にリフレッシュジョブを一時停止する理由は?
一時停止している理由は静止点を作りたいこともありますが、それをサボると、なかなか理解しにくいタイミングイシューと言われてる事象に遭遇しやすくなるんですよ。(感覚的に)
前述の状況になると高速リフレッシュを再開するには、一度、完全リフレッシュする必要があります。
ここで利用するMviewは2行しかないので完全リフレッシュは苦でもないですが、巨大サイズの表だったら完全リフレッシュはできることなら避けたいですよね。


PDB:ORCLの異なるschema間でmaster表→mv_master表で基本レプリケーション環境作成からData PumpでOmv_master表のオーナースキーマごとPDB:ORCL2へ複製までをつらつらと記録してあります。:)

MTA環境となっています。PDB:ORCL内で基本レプリケーション環境を作り、PDB:ORCL2にDBリンクやMVIEW等関連オブジェクトをData Pumpを利用して複製します。

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

orcl12c@SYS> show pdbs

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


PDB:ORCLデータベースにディレクトリオブジェクトを作成します。(Data Pump向け作業ディレクトリ)

orcl@SYS> create directory workdir as '/u01/userhome/oracle';

Directory created.

PDB:ORCLデータベースにマスターサイト向けユーザを作成し、必要最低限の権限を付与

orcl@SYS> create user master_schema identified by welcome1
2 default tablespace users
3 temporary tablespace temp
4 quota unlimited on users;

User created.

orcl@SYS> grant create session, create table to master_schema;

Grant succeeded.

PDB:ORCL、作成したユーザに接続し、マスター表を作成

orcl@SYS> conn master_schema/welcome1@orcl
Connected.
orcl@MASTER_SCHEMA> create table master (
2 id number primary key
3 ,foo varchar2(100));

Table created.

orcl@MASTER_SCHEMA> insert into master values(1,'foo');

1 row created.

orcl@MASTER_SCHEMA> insert into master values(2,'bar');

1 row created.

orcl@MASTER_SCHEMA> commit;

Commit complete.


PDB:ORCL、高速リフレッシュに必要なMaterialized View LogをMaster表に作成します。

orcl@MASTER_SCHEMA> create materialized view log on master;

Materialized view log created.


同じくPDB:ORCLデータベースにMviewサイト向けユーザを作成し、必要最低限の権限を付与します。

orcl@SYS> create user mview_schema1 identified by welcome1
2 default tablespace users
3 temporary tablespace temp
4 quota unlimited on users;

User created.

orcl@SYS> grant create session, create table, create database link, create materialized view to mview_schema1;

Grant succeeded.


PDB:ORCL、Mviewサイト向けに作成したユーザに接続し、マスターサイトへのデータベースリンクとMaterialized Viewを作成します。

orcl@SYS> conn mview_schema1/welcome1@orcl
Connected.
orcl@MVIEW_SCHEMA1> create database link to_master_schema
2 connect to master_schema identified by welcome1
3 using 'ORCL';

Database link created.

orcl@MVIEW_SCHEMA1> select count(*) from master@to_master_schema;

COUNT(*)
----------
2

orcl@MVIEW_SCHEMA1> create materialized view mv_master
2 refresh fast on demand
3 start with sysdate next sysdate+5/1440
4 as select * from master@to_master_schema;

Materialized view created.


PDB:ORCL、MViewサイトのオブジェクト確認からDBMS_JOBとリフレッシュグループの高速リフレッシュされているところまでを確認しています。

Mviewを作成すると、作成したMviewは、TABLEでもあり、MVIEWでもある。ということが確認できます。これ重要ですよ!
data pumpのschemaモード向けSCHEMA_EXPORT_OBJECTSビューにTABLEとMATERIALIZED_VIEWの2つのオブジェクトパスがあるにも関わらず、
tableモードのTABLE_EXPORT_OBJECTSビューにはTABLEオブジェクトパスは定義されているのにMATERIALIZED_VIEWオブジェクトパスされていないからMVIEWとしてはエクポートできないと言っていた理由なんですよ!!!!

orcl@MVIEW_SCHEMA1> select object_name,object_type from user_objects;

OBJECT_NAME OBJECT_TYPE
------------------------------ -----------------------
MV_MASTER TABLE
SYS_C0014880 INDEX
MV_MASTER MATERIALIZED VIEW
TO_MASTER_SCHEMA DATABASE LINK

次はuser_jobsからリフレッシュジョブを確認しておきます。これもMviewをリフレッシュするのに必要なオブジェクトです。
data pumpのschemaモード向けSCHEMA_EXPORT_OBJECTSビューでJOBオブジェクトパスとして定義されています。これも重要なんです。
前回JOBオブジェクトパスに対応するオブジェクトは、DBMS_JOBのJOBだということを書きましたが、思い出していただけましたか? 

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/04/15 00:09:04 2017/04/15 00:14:04 sysdate+5/1440 0 dbms_refresh.refresh('"MVIEW_SCHEMA1"."MV_MASTER"');

最後にリフレッシュグループの確認、意外とこれの存在を忘れてしまうんですよ。私もそうでした。
単一MVIEWのリフレッシュでもリフレッシュグループが自動的に作成されてしまうことを...複数のMVIEWをリフレッシュする時だけに必要なのかと思ったら大間違いw
いつも、つい、忘れちゃいますw 影薄過ぎ! ですが、前述のWHAT列の内容を見れば、なるほど! となるはずです。
dbms_refresh.refreshプロシージャは、リフレッシュグループ名が引数!!

orcl@MVIEW_SCHEMA1> select rowner,rname,refgroup,job,broken,interval,next_date from user_refresh;

ROWNER RNAME REFGROUP JOB B INTERVAL NEXT_DATE
-------------------- -------------------- ---------- ---------- - -------------------- -------------------
MVIEW_SCHEMA1 MV_MASTER 61 81 N sysdate+5/1440 2017/04/15 00:29:29


PDB:ORCL、リフレッシュジョブを一時停止し、expdpのschemaモードでMviewサイト向けスキーマを丸ごとエクスポートします。

orcl@MVIEW_SCHEMA1> exec dbms_job.broken(job=>81,broken=>true);

PL/SQL procedure successfully completed.

orcl@MVIEW_SCHEMA1> select rowner,rname,refgroup,job,broken,interval,next_date from user_refresh;

ROWNER RNAME REFGROUP JOB B INTERVAL NEXT_DATE
-------------------- -------------------- ---------- ---------- - -------------------- -------------------
MVIEW_SCHEMA1 MV_MASTER 61 81 Y sysdate+5/1440 4000/01/01 00:00:00


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 Sat Apr 15 00:30:55 2017 elapsed 0 00:00:55


無事エクスポートできたようなので、次は、
PDB:ORCL2データベースで、ディレクトリオブジェクトを作成します。2つめのMviewサイトの準備です。

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

Directory created.


PDB:ORCL2、schemaモードでインポート。(対象PDB:ORCL2には同一スキーマは存在しない状態で実施)

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 Sat Apr 15 00:39:00 2017 elapsed 0 00:00:23

と、すんなり終了w

PDB:ORCL2、インポートで複製されたMVIEW_SCHEMA1ユーザに接続しオブジェクトを確認
リフレッシュジョブは、エクスポート元と同一ジョブ番号でインポートされ、停止状態。想定通りで一安心:)

orcl2@MVIEW_SCHEMA1> select object_name,object_type from user_objects;

OBJECT_NAME OBJECT_TYPE
------------------------------ -----------------------
MV_MASTER TABLE
SYS_C0014884 INDEX
MV_MASTER MATERIALIZED VIEW
TO_MASTER_SCHEMA DATABASE LINK

orcl2@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 4000/01/01 00:00:00 sysdate+5/1440 dbms_refresh.refresh('"MVIEW_SCHEMA1"."MV_MASTER"');

orcl2@MVIEW_SCHEMA1> select rowner,rname,refgroup,job,broken,interval,next_date from user_refresh;

ROWNER RNAME REFGROUP JOB B INTERVAL NEXT_DATE
-------------------- -------------------- ---------- ---------- - -------------------- -------------------
MVIEW_SCHEMA1 MV_MASTER 61 81 Y sysdate+5/1440 4000/01/01 00:00:00


PDB:ORCLとORCL2、両MViewサイトのリフレッシュジョブを再開

orcl2@MVIEW_SCHEMA1> conn mview_schema1/welcome1@orcl2
Connected.
orcl2@MVIEW_SCHEMA1> exec dbms_job.broken(job=>81,broken=>false,next_date=>sysdate);

PL/SQL procedure successfully completed.

orcl2@MVIEW_SCHEMA1> conn mview_schema1/welcome1@orcl
Connected.
orcl@MVIEW_SCHEMA1> exec dbms_job.broken(job=>81,broken=>false,next_date=>sysdate);

PL/SQL procedure successfully completed.

最後に、containers句を使って全体を確認っと!

orcl2@MVIEW_SCHEMA1> conn sys/oracle@orcl12c as sysdba
Connected.
orcl12c@SYS> select rowner,rname,refgroup,job,broken,interval,next_date,con_id from containers(dba_refresh) where rowner='MVIEW_SCHEMA1';

ROWNER RNAME REFGROUP JOB B INTERVAL NEXT_DATE CON_ID
-------------------- -------------------- ---------- ---------- - -------------------- ------------------- ----------
MVIEW_SCHEMA1 MV_MASTER 61 81 N sysdate+5/1440 2017/04/15 22:25:47 5
MVIEW_SCHEMA1 MV_MASTER 61 81 N sysdate+5/1440 2017/04/15 22:26:52 3

orcl12c@SYS> select mview_name,refresh_mode,refresh_method,last_refresh_type,after_fast_refresh,compile_state from containers(dba_mviews) where mview_name='MV_MASTER';
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

orcl12c@SYS> select job,log_user,schema_user,last_date,next_date,interval,failures,what from containers(dba_jobs) where log_user='MVIEW_SCHEMA1';
JOB LOG_USER SCHEMA_USER LAST_DATE NEXT_DATE INTERVAL FAILURES WHAT
---------- -------------------- -------------------- ------------------- ------------------- -------------------- ---------- ------------------------------------------------------------
81 MVIEW_SCHEMA1 MVIEW_SCHEMA1 2017/04/15 22:20:47 2017/04/15 22:25:47 sysdate+5/1440 0 dbms_refresh.refresh('"MVIEW_SCHEMA1"."MV_MASTER"');
81 MVIEW_SCHEMA1 MVIEW_SCHEMA1 2017/04/15 22:21:52 2017/04/15 22:26:52 sysdate+5/1440 0 dbms_refresh.refresh('"MVIEW_SCHEMA1"."MV_MASTER"');

何事もなく複製できたところで、次回へ続く。

あ、その前に、環境を初期状態に戻さないと。。


Data Pumpも癖モノだよね〜w その1 - queryパラメーターの解析タイミング
Data Pumpも癖モノだよね〜w その2 - Materialized ViewをTableとして移行する
Data Pumpも癖モノだよね〜w その3 - dbms_job と dbms_scheduler との複雑な関係

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

2017年4月10日 (月)

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

Previously on Mac De Oracle

前回は、Data PumpとMaterialized Viewという癖モノ二大巨頭を絡ませて見ました。

今回は、三つ巴?な感じでお送りしたいと思います。:)



以下は、Materialized ViewをリフレッシュするDBMS_JOBです。

今頃気づいたか! という感じですが、dbms_job で作成されるJOBは、ALL/DBA/USER_OBJECTSには含まれないのです!!

orcl@USERS> 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
---------- -------------------- -------------------- ------------------- ------------------- -------------------- ---------- ------------------------------------------------------------
21 USERS USERS 2017/04/09 19:18:34 2017/04/09 19:19:34 sysdate+1/1440 0 dbms_refresh.refresh('"USERS"."MVIEW_MASTER"');

orcl@USERS> select object_name,object_type from user_objects;

OBJECT_NAME OBJECT_TYPE
------------------------------ -----------------------
MVIEW_MASTER MATERIALIZED VIEW
SYS_C0014637 INDEX
MVIEW_MASTER TABLE
TOUSERM DATABASE LINK


ここで、注目!!
dbms_jobは、dba_objectsにはカウントされませんが、dbms_schedulerは、object_type=JOBとしてdba_objectsにカウントされるということ!!
以下にある、OBJECT_TYPE=JOBは、OBJECT_NAME=TESTという直前に作成されたdbms_schedulerのJOBだということ!!

ORCL@USERS> begin
dbms_scheduler.create_job (
job_name=>'test'
,job_type=>'PLSQL_BLOCK'
,job_action=>'BEGIN dbms_refresh.refresh(''USERS.MVIEW_MASTER''); END;'
,start_date=>systimestamp
,repeat_interval=>'FREQ=MONTHLY'
,end_date=>systimestamp + interval '1' year
,enabled=>true
,comments=>null
);
end;
/

PL/SQL procedure successfully completed.


なんとまぁ、面倒くさい、DBMS_JOBのJOBも、DBMS_SCHEDULERのJOBも、同じ初期化パラメータ(job_queue_processes)を利用するのにオブジェクト扱いされたりされなかったり、面倒くさい癖モノです。注意しましょうね!!

Oracle® Databaseリファレンス 12c リリース1 (12.1) 1.126 JOB_QUEUE_PROCESSES
https://docs.oracle.com/cd/E57425_01/121/REFRN/GUID-B8B68D16-00A3-43DD-BE39-01F877880955.htm

ORCL@USERS> select object_name,object_type from user_objects;

OBJECT_NAME OBJECT_TYPE
------------------------------ -----------------------
MVIEW_MASTER TABLE
SYS_C0014637 INDEX
MVIEW_MASTER MATERIALIZED VIEW
TEST JOB
TOUSERM DATABASE LINK

という準備運動が終わったところで、本題の Data Pumpでのお話です。
癖モノData Pumpと癖モノ感たっぷりの2種類のJOB、2時間ドラマの複雑でドロドロした関係が予想される展開になってきましたw

orcl@USERS> 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
---------- -------------------- -------------------- ------------------- ------------------- -------------------- ---------- ------------------------------------------------------------
21 USERS USERS 2017/04/09 19:18:34 2017/04/09 19:19:34 sysdate+1/1440 0 dbms_refresh.refresh('"USERS"."MVIEW_MASTER"');

orcl@USERS> select job_name,job_action,repeat_interval,start_date from user_scheduler_jobs;

JOB_NAME JOB_ACTION REPEAT_INTERVAL START_DATE
---------- ------------------------------------------------------------------- -------------------- ----------------------------------------
TEST BEGIN dbms_refresh.refresh('USERS.MVIEW_MASTER'); END; FREQ=MONTHLY 09-APR-17 10.36.05.814317 PM +09:00


まず、Data Pumpで扱える"OBJECT”が定義されているSCHEMA_EXPORT_OBJECTSをみると以下の"OBJECT”定義が見つかります。
JOBというオブジェクトのコメントを読んでも、2種類あるJOBのどちらを指しているのか、はたまた、いずれか一つなのかさっぱりわかりません。

OBJECT_PATH                     COMMENTS
------------------------------- ------------------------------------------------------------
SCHEMA_EXPORT/DB_LINK Private database links in the selected schemas
SCHEMA_EXPORT/TABLE Tables in the selected schemas and their dependent objects
SCHEMA_EXPORT/MATERIALIZED_VIEW Materialized views
SCHEMA_EXPORT/JOB Jobs in the selected schemas
SCHEMA_EXPORT/REFRESH_GROUP Refresh groups in the selected schemas

これは試して、ガッテン!! するしかありません!!!

schemaモードでエクスポートします。このとき、includeパラメータでJOBだけをエクスポートするよう指定します!! 

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=homedir dumpfile=jobs.dmp logfile=jobsexp.log schemas=users include=job
Estimate in progress using BLOCKS method...
Total estimation using BLOCKS method: 0 KB
Processing object type SCHEMA_EXPORT/JOB
Master table "SYSTEM"."SYS_EXPORT_SCHEMA_01" successfully loaded/unloaded
******************************************************************************
Dump file set for SYSTEM.SYS_EXPORT_SCHEMA_01 is:
/home/oracle/jobs.dmp
Job "SYSTEM"."SYS_EXPORT_SCHEMA_01" successfully completed at Sun Apr 9 23:13:47 2017 elapsed 0 00:00:04

SQLFILEパラメータを指定して内容を確認してみます。(SQLFILEパラメータを指定したimpdpコマンドでは実際にインポートは行われません)

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_SQL_FILE_SCHEMA_01" successfully loaded/unloaded
Starting "SYSTEM"."SYS_SQL_FILE_SCHEMA_01": system/********@orcl directory=homedir dumpfile=jobs.dmp logfile=jobsexp.log schemas=users sqlfile=jobsexp_ddl.txt
Processing object type SCHEMA_EXPORT/JOB
Job "SYSTEM"."SYS_SQL_FILE_SCHEMA_01" successfully completed at Sun Apr 9 23:20:44 2017 elapsed 0 00:00:03


おおおおお、これは!!! 

なんということでしょう!
Data Pumpでは、JOBオブジェクトは、DBMS_JOBのJOBオブジェクト(dba_objectsではオブジェクト扱いされていないのに!!)

だとすると、dba_objectsでは”OBJECT"として扱われている、DBMS_SCHEDULERのJOBはの扱いはいかに。。。

以下のとおり、DBMS_IJOBと内部的プロリージャに置き換わっていますが、パラメータを見れば一目瞭然、DBMS_JOBの定義しかありません。
つまり、Data PumpのJOBオブジェクトは、DBMS_JOBのJOBであることがわかりました!!

[oracle@catfish ˜]$ cat jobsexp_ddl.txt 

・・・中略・・・

-- new object type path: SCHEMA_EXPORT/JOB
BEGIN SYS.DBMS_IJOB.SUBMIT(
JOB=> 21,
LUSER=> 'USERS',
PUSER=> 'USERS',
CUSER=> 'USERS',
NEXT_DATE=> TO_DATE('2017-04-09 23:13:51', 'YYYY-MM-DD:HH24:MI:SS'),
INTERVAL=> 'sysdate+1/1440',
BROKEN=> FALSE,
WHAT=> 'dbms_refresh.refresh(''"USERS"."MVIEW_MASTER"'');',

・・・中略・・・

では、DBMS_SCHEDULERのJOBは。。。それは。。。PROCOBJというOBJECT_PATHに含まれているようで(ほぼ誰にも読み取れないw)。。。

MOSにもありそうだけど、この辺りをまとめてて疲れて、めんどくさい病の発作がw 
もっと深掘りする気力があったら探すかもw
Export/Import Scheduler Jobs


手取り早く、試して、ガッテン! includeパラメータで”PROCOBJ”を指定します。

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=homedir dumpfile=scheduler_jobs.dmp logfile=scheduler_jobsexp.log schemas=users include=procobj
Estimate in progress using BLOCKS method...
Total estimation using BLOCKS method: 0 KB
Processing object type SCHEMA_EXPORT/POST_SCHEMA/PROCOBJ
Master table "SYSTEM"."SYS_EXPORT_SCHEMA_01" successfully loaded/unloaded
******************************************************************************
Dump file set for SYSTEM.SYS_EXPORT_SCHEMA_01 is:
/home/oracle/scheduler_jobs.dmp
Job "SYSTEM"."SYS_EXPORT_SCHEMA_01" successfully completed at Sun Apr 9 23:49:20 2017 elapsed 0 00:00:04

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_SQL_FILE_SCHEMA_01" successfully loaded/unloaded
Starting "SYSTEM"."SYS_SQL_FILE_SCHEMA_01": system/********@orcl directory=homedir dumpfile=scheduler_jobs.dmp logfile=jobsddldump.log schemas=users sqlfile=jobsexp2_ddl.txt
Processing object type SCHEMA_EXPORT/POST_SCHEMA/PROCOBJ
Job "SYSTEM"."SYS_SQL_FILE_SCHEMA_01" successfully completed at Sun Apr 9 23:50:05 2017 elapsed 0 00:00:02


確かに、PROCOBJにDBMS_SCHEDULERのJOBが含まれている!!

[oracle@catfish ˜]$ cat jobsexp2_ddl.txt

・・・中略・・・

BEGIN
dbms_scheduler.create_job('"TEST"',
job_type=>'PLSQL_BLOCK'
, job_action=>'BEGIN dbms_refresh.refresh(''USERS.MVIEW_MASTER''); END;'
, number_of_arguments=>0
, start_date=>TO_TIMESTAMP_TZ('09-APR-2017 10.36.05.814317000 PM +09:00','DD-MON-RRRR HH.MI.SSXFF AM TZR','NLS_DATE_LANGUAGE=english')
, repeat_interval=> 'FREQ=MONTHLY'
, end_date=>TO_TIMESTAMP_TZ('09-APR-2018 10.36.05.814344000 PM +09:00','DD-MON-RRRR HH.MI.SSXFF AM TZR','NLS_DATE_LANGUAGE=english')
, job_class=>'"DEFAULT_JOB_CLASS"'
, enabled=>FALSE
, auto_drop=>TRUE
,comments=>NULL
);
dbms_scheduler.enable('"TEST"');
COMMIT;
END;
/

・・・中略・・・

登場人物の関係が複雑すぎてよくわからなくなってきたので、まとめ。

DBMS_JOBのJOBは、DBA_OBJECTS上、オブジェクトとは扱われていない。
DBMS_SCHEDULEのJOBは、DBA_OBJECTS上、オブジェクトとして扱われている。
どちらのJOBも、初期化パラメータ、job_queue_processesにより制御されている。
Data PumpのSCHEMA_EXPORT_OBJECTSにて定義されているJOBオブジェクトは、DBMS_JOBのJOBのことである。
Data PumpのSCHEMA_EXPORT_OBJECTSにて定義されているPROCOBJオブジェクトが、DBMS_SCHEDULERのJOBのこと!?であるようだ。
(オブジェクト名からは想像できない可読性の悪さはなんとかしてくれ!)

DBMS_SCHEDULERへの移行が推奨されながらDBMS_JOBが未だに存在していることの弊害のようにも思えてきた。
このあたり、理解しやすいように改善してもらいたい癖モノの一つとしてリストに加えておこう。


満開の桜なのに残念な天気の日曜日終わってしまった!! ということで今日はここまで。




Data Pumpも癖モノだよね〜w その1 - queryパラメーターの解析タイミング
Data Pumpも癖モノだよね〜w その2 - Materialized ViewをTableとして移行する

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

2017年4月 9日 (日)

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

Previously on Mac De Oracle

前回はMac De OracleはData Pumpのqueryパラメーターの解析タイミングについて調べたメモでした。

今回はタイトルのとおり、Materialized ViewをTableとして移行していしまおうというお題。
実は、Materialized Viewとして移行しようとして失敗ったのがきっかけで知ったんですけど、あまり書かれていないので仕様だとは思うんですが(そうなんですよね?w)
(癖モノData Pumpと癖モノMaterialized Viewを扱おうとする時点で、すんなり行くわけがない、ぐらいの覚悟はしておいたほうが無難でしょうけど)


ちなみに、今回の内容とは関係ないですが、ViewをTableとしてエクスポートする機能も12cR1から提供されていますね(使ったことはまだないですが)
VIEWS_AS_TABLES
https://docs.oracle.com/database/121/SUTIL/GUID-E4E45E81-5391-43BE-B27D-B763EF79A885.htm#SUTIL3904

Exporting views as tables Oracle Database 12C release 1 (12.1)
http://dbaora.com/exporting-views-as-tables-oracle-database-12c-release-1-12-1/



以下のようなMVIEWがあります。
エクスポート側ではMaterialize Viewとして定義され、自動的にリフレッシュされています。

orcl@USERS>  select object_name,object_type from user_objects where object_name='MVIEW_MASTER';

OBJECT_NAME OBJECT_TYPE
------------------------------ ------------------------------
MVIEW_MASTER MATERIALIZED VIEW
VIEW_MASTER TABLE

orcl@USERS> select job,log_user,last_date,next_date,interval,failures,broken,what from user_jobs;

JOB LOG_USER LAST_DATE NEXT_DATE INTERVAL FAILURES B WHAT
---------- ------------------------------ ------------------- ------------------- -------------------- ---------- - --------------------------------------------------
21 USERS 2017/04/09 14:16:53 2017/04/09 14:17:53 sysdate+1/1440 0 N dbms_refresh.refresh('"USERS"."MVIEW_MASTER"');

表モードでMviewからTableへの変換!
tablesパラメータでMviewを指定しているところがポイント! MVIEWでもありTABLEでもあるのでTABLEとしてエクスポートができます。

表モードで有効なオブジェクトをTABLE_EXPORT_OBJECTSで確認してみて気づいたのですが、TABLE_EXPORT_OBJECTSには MATERIALIZED_VIEW は存在しません。

orcl@SYSTEM^> r
1 select * from TABLE_EXPORT_OBJECTS where
2 object_path like '%/JOB'
3 or object_path like '%/MATERIALIZED_VIEW'
4* or object_path like '%/REFRESH_GROUP'

no rows selected


つまり、表モードではMaterialized ViewをMaterizlized Viewとしてエクスポート/インポートすることはできないということ!!(?)のようです。

[oracle@catfish ˜]$ expdp users/********@orcl directory=homedir dumpfile=mv2table.dmp logfile=mv2table.log tables=mview_master

Export: Release 12.1.0.2.0 - Production on Sun Apr 9 14:46:27 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
Starting "USERS"."SYS_EXPORT_TABLE_01": users/********@orcl directory=homedir dumpfile=mv2table.dmp logfile=mv2table.log tables=mview_master
Estimate in progress using BLOCKS method...
Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
Total estimation using BLOCKS method: 64 KB
Processing object type TABLE_EXPORT/TABLE/TABLE
Processing object type TABLE_EXPORT/TABLE/COMMENT
Processing object type TABLE_EXPORT/TABLE/CONSTRAINT/CONSTRAINT
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 "USERS"."MVIEW_MASTER" 5.492 KB 2 rows
Master table "USERS"."SYS_EXPORT_TABLE_01" successfully loaded/unloaded
******************************************************************************
Dump file set for USERS.SYS_EXPORT_TABLE_01 is:
/home/oracle/mv2table.dmp
Job "USERS"."SYS_EXPORT_TABLE_01" successfully completed at Sun Apr 9 14:47:09 2017 elapsed 0 00:00:38

同一DB(PDB)の異なるschemaへ表としてインポート(異なるschemaへインポートするのでremap_schamaパラメータをお忘れなく)

[oracle@catfish ˜]$ impdp hr/********@orcl directory=homedir dumpfile=mv2table.dmp logfile=mv2table.log remap_schema=users:hr

Import: Release 12.1.0.2.0 - Production on Sun Apr 9 14:49:56 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 "HR"."SYS_IMPORT_FULL_01" successfully loaded/unloaded
Starting "HR"."SYS_IMPORT_FULL_01": hr/********@orcl directory=homedir dumpfile=mv2table.dmp logfile=mv2table.log remap_schema=users:hr
Processing object type TABLE_EXPORT/TABLE/TABLE
Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
. . imported "HR"."MVIEW_MASTER" 5.492 KB 2 rows
Processing object type TABLE_EXPORT/TABLE/COMMENT
Processing object type TABLE_EXPORT/TABLE/CONSTRAINT/CONSTRAINT
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
Job "HR"."SYS_IMPORT_FULL_01" successfully completed at Sun Apr 9 14:50:19 2017 elapsed 0 00:00:22


表としてインポートされています!

orcl@HR> select object_name,object_type from user_objects where object_name='MVIEW_MASTER';

OBJECT_NAME OBJECT_TYPE
------------------------------ -----------------------
MVIEW_MASTER TABLE

orcl@HR> select job,log_user,last_date,next_date,interval,failures,broken,what from user_jobs;

no rows selected

orcl@HR> select count(1) from mview_master;

COUNT(1)
----------
2


さて、お次、
表モードとは異なり、schemaモードのオブジェクトを定義しているSCHEMA_EXPORT_OBJECTSには、Materialized ViewをMaterialized Viewとしてエクスポート/インポートするために必要な以下のオブジェクト定義が存在します。
ということは、schemaモードではMviewをMviewとして移行することも、MviewをTableとして移行することもできそうな設定になっているようです、

OBJECT_PATH                     COMMENTS
------------------------------- ------------------------------------------------------------
SCHEMA_EXPORT/DB_LINK Private database links in the selected schemas
SCHEMA_EXPORT/TABLE Tables in the selected schemas and their dependent objects
SCHEMA_EXPORT/MATERIALIZED_VIEW Materialized views
SCHEMA_EXPORT/JOB Jobs in the selected schemas
SCHEMA_EXPORT/REFRESH_GROUP Refresh groups in the selected schemas


ということで、schemaモードでも同様の変換が可能かためしてみます。
schemaモードでinclude=TABLEとして表関連オブジェクトのみエクスポート。
schemaモードを選択した場合は、materialized view、job、refresh groupもスコープに入ってしまうので、余分なオブジェクトや定義を取り込まないようにするのがポイント(でした)

[oracle@catfish ˜]$ expdp users/******** directory=homedir dumpfile=test.dmp logfile=testexp.log include=TABLE

Export: Release 12.1.0.2.0 - Production on Wed Apr 5 00:40:17 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
Starting "USERS"."SYS_EXPORT_SCHEMA_01": users/******** directory=homedir dumpfile=test.dmp logfile=testexp.log include=TABLE
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/TABLE/TABLE
Processing object type SCHEMA_EXPORT/TABLE/COMMENT
Processing object type SCHEMA_EXPORT/TABLE/INDEX/INDEX
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
. . exported "USERS"."MVIEW_MASTER" 5.484 KB 1 rows
Master table "USERS"."SYS_EXPORT_SCHEMA_01" successfully loaded/unloaded
******************************************************************************
Dump file set for USERS.SYS_EXPORT_SCHEMA_01 is:
/home/oracle/test.dmp
Job "USERS"."SYS_EXPORT_SCHEMA_01" successfully completed at Wed Apr 5 00:40:43 2017 elapsed 0 00:00:25

同一DB(PDB)の異なるschemaへ表としてインポート(異なるschemaへインポートするのでremap_schamaパラメータをお忘れなく)

[oracle@catfish ˜]$ impdp users2/******** directory=homedir dumpfile=test.dmp logfile=testexp.log include=TABLE remap_schema=users:users2

Import: Release 12.1.0.2.0 - Production on Wed Apr 5 00:42:18 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 "USERS2"."SYS_IMPORT_FULL_01" successfully loaded/unloaded
Starting "USERS2"."SYS_IMPORT_FULL_01": users2/******** directory=homedir dumpfile=test.dmp logfile=testexp.log include=TABLE remap_schema=users:users2
Processing object type SCHEMA_EXPORT/TABLE/TABLE
Processing object type SCHEMA_EXPORT/TABLE/TABLE_DATA
. . imported "USERS2"."MVIEW_MASTER" 5.484 KB 1 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
Job "USERS2"."SYS_IMPORT_FULL_01" successfully completed at Wed Apr 5 00:42:24 2017 elapsed 0 00:00:05


マスター表からDBリンク経由でCTASするという手もありますが、Materialized ViewではなくTableとして移行する場合、Data Pumpを利用する方法もあるなぁと。
そして、includeパラメータやエクスポートモードには注意しないと、いろいろハマりそうだなぁ、と思ったのでしたw


ということで、schemaモードでもMaterialized ViewをTableとして移行できるよ! めでたしめでたしw (失敗は気づきの母w)

[oracle@catfish ˜]$ sqlplus users2/********

SQL*Plus: Release 12.1.0.2.0 Production on Wed Apr 5 00:42:39 2017

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

Last Successful login time: Wed Apr 05 2017 00:42:18 +09:00

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@USERS2> select object_name,object_type from user_objects where object_name='MVIEW_MASTER';

OBJECT_NAME OBJECT_TYPE
------------------------------ -----------------------
MVIEW_MASTER TABLE

ORCL@USERS2> select * from user_mviews;
no rows selected

ORCL@USERS2> select job,log_user,last_date,next_date,interval,failures,broken,what from user_jobs;

no rows selected

ORCL@USERS2> select * from mview_master;

ID DATA
---------- ----------
1 test1


今日はここまで。


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

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

2017年4月 8日 (土)

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

AWS、MS、Oracle、それぞれのクラウド環境へのデータ移行なんてことも珍しくなくなってきました。
そして移行ツールとしても利用されるData Pump。

でも細かい機能を使おうと調べていると、Data Pump、いろいろ癖があるよなぁ〜。と改めて気づくんですw

ということで、そんな癖もの! Data PumpのFAQっぽいことを備忘録として書いておきますね。(要するに、ハマったこと集w)


 

queryパラメータに記述したwhere句っていつ解析されるかご存知ですか?
expdpコマンドを実行した時点でqueryパラメータのwhere句のシンタックスがチェックされると思う方、手をあげて!

私もそう思ってました、最近までw
あえて書いてるのですから、勘の良いかたなら、ちがうのか! と気づいちゃいますよねw 

そう!ちがうんです!

では、シンタックスエラーのあるqueryパラメータで実行してみますよ。 赤字の部分、where であるべきですが、 while としてあります。パースされればシンタックスエラーとなるはずです!!
いいですか〜〜〜、よ〜〜〜〜く見ててくださいよ〜。みて、みて、みてみてみてみて〜〜〜〜っ

パラメータファイルは以下のとおり

[oracle@crayfish ˜]$ cat query.par
tables=hoge
query=hoge:"while id = 1"


実行してみると、あーら不思議、正常終了してしまいます!

[oracle@crayfish ˜]$ expdp hr/hr@orcl directory=homedir dumpfile=testhr_query45.dmp logfile=testhr_query45.log parfile=query.par

Export: Release 12.1.0.2.0 - Production on Sat Apr 8 00:34:48 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
Starting "HR"."SYS_EXPORT_TABLE_01": hr/********@orcl directory=homedir dumpfile=testhr_query45.dmp logfile=testhr_query45.log parfile=query.par
Estimate in progress using BLOCKS method...
Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
Total estimation using BLOCKS method: 64 KB
Processing object type TABLE_EXPORT/TABLE/TABLE
Processing object type TABLE_EXPORT/TABLE/CONSTRAINT/CONSTRAINT
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 "HR"."HOGE" 0 KB 0 rows
Master table "HR"."SYS_EXPORT_TABLE_01" successfully loaded/unloaded
******************************************************************************
Dump file set for HR.SYS_EXPORT_TABLE_01 is:
/home/oracle/testhr_query45.dmp
Job "HR"."SYS_EXPORT_TABLE_01" successfully completed at Sat Apr 8 00:35:13 2017 elapsed 0 00:00:24

なぜなのかわかりますか????

queryパラメータでデータを選択する対象の表が空だと、queryパラメータに指定したwhere句はパースされない! 
そもそも取り出すデータが無いので無駄なことはしない!
ということのようです。

ということで、queryパラメータのシンタックスチェックだけを事前に行いたい場合、1行以上のデータが必要でっす!
0件の状態で実行してもqueryパラメータのシンタックスチェックにはならないのでご注意を!!

[oracle@crayfish ˜]$ sqlplus hr/hr@orcl

SQL*Plus: Release 12.1.0.2.0 Production on Sat Apr 8 00:36:29 2017

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

Last Successful login time: Sat Apr 08 2017 00:34:48 +09:00

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@HR> insert into hoge values(1,'test');

1 row created.

orcl@HR> commit;

Commit complete.

orcl@HR> select count(1) from hoge;

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

空の表に1行だけデータを登録すると! queryパラメターのwhere句が解析されシンタックスエラーとなります!

[oracle@crayfish ˜]$ cat query.par
tables=hoge
query=hoge:"while id = 1"

[oracle@crayfish ˜]$
[oracle@crayfish ˜]$ expdp hr/hr@orcl directory=homedir dumpfile=testhr_query46.dmp logfile=testhr_query46.log parfile=query.par

Export: Release 12.1.0.2.0 - Production on Sat Apr 8 00:37:08 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
Starting "HR"."SYS_EXPORT_TABLE_01": hr/********@orcl directory=homedir dumpfile=testhr_query46.dmp logfile=testhr_query46.log parfile=query.par
Estimate in progress using BLOCKS method...
Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
Total estimation using BLOCKS method: 64 KB
Processing object type TABLE_EXPORT/TABLE/TABLE
Processing object type TABLE_EXPORT/TABLE/CONSTRAINT/CONSTRAINT
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
ORA-31693: Table data object "HR"."HOGE" failed to load/unload and is being skipped due to error:
ORA-00933: SQL command not properly ended
Master table "HR"."SYS_EXPORT_TABLE_01" successfully loaded/unloaded
******************************************************************************
Dump file set for HR.SYS_EXPORT_TABLE_01 is:
/home/oracle/testhr_query46.dmp
Job "HR"."SYS_EXPORT_TABLE_01" completed with 1 error(s) at Sat Apr 8 00:37:34 2017 elapsed 0 00:00:24

ということで本日はここまで。

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

2017年4月 3日 (月)

CDBとPDBの間で迷子になりそう PART3 - containers clause - その3

Previously on Mac De Oracle.

AWRでなんとか発行したSQL文以外に、containers句を元とする再帰SQL文を捕まえられたのはいいが、その再帰SQL文と元となるcontainers句を紐づけることが難しそう。
また、ヒントでチューニングするのも難しそう(これはそれっぽいのがあるけどまだ調べてないのでどこまでできるのか未知の領域)。
できるとすれば、SPMによるチューニングかな?、というところまではなんとか見えてきました。


AWRではcontainers句で生成される再帰SQL文を特定するのに難ありというところまでは見えてきたので、
最後の希望w SQLトレースはどうなのか、気になっていたので試した見た。
(利用している表とSQL文は多少変えていますが、大きな差はありません)

SQLトレースをセッションレベルで有効化して(トレースファイルを特定しやすくしておくことをお忘れなく)、containers句を含むSQL文を実行して、SQLトレースを無効化。

orcl12c@C##HOGE> alter session set tracefile_identifier=containers;
orcl12c@C##HOGE> exec dbms_monitor.session_trace_enable(waits=>true);

PL/SQL procedure successfully completed.

orcl12c@C##HOGE> select * from containers(hoge) where id in (1,3);

ID DATA CON_ID
---------- -------------- ----------
3 test3 4
1 test1 3

orcl12c@C##HOGE> exec dbms_monitor.session_trace_disable;

ここで、前々回、SQL監視のParallel Execution Detailsセクションをみてみると、スレーブプロセスがどうなっていたかわかりやすいですね!

Parallel Execution Details (DOP=4 , Servers Allocated=4)
==========================================================================================
| Name | Type | Server# | Elapsed | Cpu | Other | Buffer | Wait Events |
| | | | Time(s) | Time(s) | Waits(s) | Gets | (sample #) |
==========================================================================================
| PX Coordinator | QC | | 0.00 | 0.00 | 0.00 | | |
| p000 | Set 1 | 1 | 0.00 | 0.00 | | | |
| p001 | Set 1 | 2 | 0.00 | | 0.00 | | |
| p002 | Set 1 | 3 | 0.00 | | 0.00 | 3 | |
| p003 | Set 1 | 4 | 0.00 | 0.00 | | 3 | |
==========================================================================================


SQLトレースファイルも各プロセスごとの取得されていることがわかります!!!
contrainers句から生成される再帰SQLはAWRレポートより見つけやすいかもしれない(個人差はあると思われるw) :)

Cp000〜p003と前述のSQL監視の情報と合わせて見ると多少は見やすいですよね。(AWRレポートのみで捉えることと比べたら遥かに面倒だとは思いますが)

[oracle@vbgeneric admin]$ cd $ORACLE_BASE/diag/rdbms/orcl12c/orcl12c/trace/
[oracle@vbgeneric trace]$ ls -l *CONTAINERS*
-rw-r----- 1 oracle oinstall 95231 4月 1 11:36 orcl12c_ora_4609_CONTAINERS.trc
-rw-r----- 1 oracle oinstall 875 4月 1 11:36 orcl12c_ora_4609_CONTAINERS.trm
-rw-r----- 1 oracle oinstall 23140 4月 1 11:36 orcl12c_p000_3375_CONTAINERS.trc
-rw-r----- 1 oracle oinstall 197 4月 1 11:36 orcl12c_p000_3375_CONTAINERS.trm
-rw-r----- 1 oracle oinstall 2942 4月 1 11:36 orcl12c_p001_3377_CONTAINERS.trc
-rw-r----- 1 oracle oinstall 149 4月 1 11:36 orcl12c_p001_3377_CONTAINERS.trm
-rw-r----- 1 oracle oinstall 98455 4月 1 11:35 orcl12c_p002_3379_CONTAINERS.trc
-rw-r----- 1 oracle oinstall 705 4月 1 11:35 orcl12c_p002_3379_CONTAINERS.trm
-rw-r----- 1 oracle oinstall 168368 4月 1 11:35 orcl12c_p003_3381_CONTAINERS.trc
-rw-r----- 1 oracle oinstall 1138 4月 1 11:35 orcl12c_p003_3381_CONTAINERS.trm
[oracle@vbgeneric trace]$

とりあえず、のぞいて見ましょう。


[oracle@vbgeneric trace]$ tkprof orcl12c_ora_4609_CONTAINERS.trc orcl12c_ora_4609_container.txt explain=system/oracle@orcl12c sys=yes waits=yes

TKPROF: Release 12.1.0.2.0 - Development on Sat Apr 1 11:47:26 2017

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

[oracle@vbgeneric trace]$ tkprof orcl12c_p000_3375_CONTAINERS.trc container_p000.txt explain=system/oracle@orcl12c sys=yes waits=yes

・・・中略・・・

[oracle@vbgeneric trace]$ tkprof orcl12c_p003_3381_CONTAINERS.trc container_p003.txt explain=system/oracle@orcl12c sys=yes waits=yes

TKPROF: Release 12.1.0.2.0 - Development on Sat Apr 1 11:47:26 2017

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

[oracle@vbgeneric trace]$ ls -l *container*
-rw-r--r-- 1 oracle oinstall 47736 4月 1 11:47 orcl12c_ora_4609_container.txt
-rw-r--r-- 1 oracle oinstall 7104 4月 1 11:47 container_p000.txt
-rw-r--r-- 1 oracle oinstall 5228 4月 1 11:47 container_p001.txt
-rw-r--r-- 1 oracle oinstall 34869 4月 1 11:47 container_p002.txt
-rw-r--r-- 1 oracle oinstall 38321 4月 1 11:48 container_p003.txt
[oracle@vbgeneric trace]$


最初にorcl12c_ora_4609_container.txtから見てみますか。
SQLトレースを有効化して、containers句を含むSQL文を発行、それに伴いいくつかの再帰SQL文、最後にSQLトレースを無効化してる流れは確認できます。
途中、再帰SQLとしてhoge表を問い合わせるために利用すると思われるSQL文をパースだけしているとみられる箇所。興味深いです:)



・・・中略・・・

SQL ID: g2nujq01pmynd Plan Hash: 0

SELECT /* */ *
FROM
"C##HOGE"."HOGE"


call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 0 0.00 0.00 0 0 0 0
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 1 0.00 0.00 0 0 0 0

Misses in library cache during parse: 1
Optimizer mode: CHOOSE
Parsing user id: SYS (recursive depth: 1)
********************************************************************************
・・・中略・・・

この部分実際にPDBで実行される想定の再帰SQL文に近いけど、件数カウントしてるだけ..なんですね。なんで件数が必要なんだろ

SELECT count(*) 
FROM
C##HOGE."HOGE" "HOGE" WHERE "HOGE"."ID"=1 OR "HOGE"."ID"=3


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 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 2 0.00 0.00 0 0 0 0

Misses in library cache during parse: 1
Optimizer mode: CHOOSE
Parsing user id: SYS (recursive depth: 1)
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ---------------------------------------------------
0 0 0 SORT AGGREGATE (cr=0 pr=0 pw=0 time=14 us)
0 0 0 CONCATENATION (cr=0 pr=0 pw=0 time=7 us)
0 0 0 INDEX UNIQUE SCAN SYS_C0010012 (cr=0 pr=0 pw=0 time=4 us)(object id 93050)
0 0 0 INDEX UNIQUE SCAN SYS_C0010012 (cr=0 pr=0 pw=0 time=0 us)(object id 93050)

********************************************************************************
・・・中略・・・


そして実際にタイプしたSQL文の登場
実行計画は実行しているSQL文からは想像できない変わり果てた姿となっていて、実際に参照する表やオペレーションではなく、hoge表をアクセスしてる実行計画ではないのは見ての通り。

SQL ID: 25a37y74xrat4 Plan Hash: 1439328272

select *
from
containers(hoge) where id in (1,3)


call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 3 1 0
Execute 1 0.00 0.01 0 0 0 0
Fetch 2 0.00 0.12 0 0 0 2
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 0.01 0.14 0 3 1 2

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 103 (C##HOGE)
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ---------------------------------------------------
2 2 2 PX COORDINATOR (cr=0 pr=0 pw=0 time=133547 us)
0 0 0 PX SEND QC (RANDOM) :TQ10000 (cr=0 pr=0 pw=0 time=0 us cost=-9223372036854775808 size=78 card=1)
0 0 0 PX PARTITION LIST ALL PARTITION: 1 254 (cr=0 pr=0 pw=0 time=0 us cost=-9223372036854775808 size=78 card=1)
0 0 0 FIXED TABLE FULL X$CDBVW$ (cr=0 pr=0 pw=0 time=0 us cost=-9223372036854775808 size=78 card=1)


パラレルクエリーの各スレーブプロセスはどうかというと...

p000のトレース(抜粋)

rowsが0、Fetch countも0、ふーん、なるほど。

SQL ID: 25a37y74xrat4 Plan Hash: 1439328272

select *
from
containers(hoge) where id in (1,3)


call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.06 0 0 0 0
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 2 0.00 0.06 0 0 0 0

Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 103 (C##HOGE) (recursive depth: 1)
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ---------------------------------------------------
0 0 0 PX COORDINATOR (cr=0 pr=0 pw=0 time=0 us)
0 0 0 PX SEND QC (RANDOM) :TQ10000 (cr=0 pr=0 pw=0 time=0 us cost=-9223372036854775808 size=78 card=1)
0 0 0 PX PARTITION LIST ALL PARTITION: 1 254 (cr=2 pr=0 pw=0 time=56179 us cost=-9223372036854775808 size=78 card=1)
0 0 0 FIXED TABLE FULL X$CDBVW$ (cr=2 pr=0 pw=0 time=53500 us cost=-9223372036854775808 size=78 card=1)

AWR SQLレポートで捕まえた再帰SQL文、これで実際に表をアクセスしてデータを取得していると考えられる。
OR句は、index unique scanをUNION、ヒントだと USE_CONCATヒントを利用したのと同じ実行計画になってる。

Fetch=1で、rows=0、ふふふーん。 0件ということは、これはデータなし!、どちらのPDBにもヒットするデータが1件ある。
データがないのは、SEEDとCDBのみなので、それのいずれかということ。

そして、HOGEという表は、CDB$ROOTと残る2つのPDBにある。また、CDB$ROOTのHOGE表はcontainers句を動作させるための前提条件なので空の表!

なので、p000はROOT$CDBのHOGE表を問い合わせていることになる!!!のか?!

SQL ID: 1u03tbqvywyf8 Plan Hash: 3444470255

SELECT /*+ RESULT_CACHE (SYSOBJ=TRUE SHELFLIFE=30) */ ID,DATA
FROM
"C##HOGE"."HOGE" "HOGE" WHERE "HOGE"."ID"=1 OR "HOGE"."ID"=3


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 1 0.00 0.00 0 2 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 3 0.00 0.00 0 2 0 0

Misses in library cache during parse: 1
Optimizer mode: CHOOSE
Parsing user id: SYS (recursive depth: 2)
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ---------------------------------------------------
0 0 0 RESULT CACHE 2fmgs0vhj7brb4c44nkh7shu6f (cr=2 pr=0 pw=0 time=76 us)
0 0 0 CONCATENATION (cr=2 pr=0 pw=0 time=38 us)
0 0 0 TABLE ACCESS BY INDEX ROWID HOGE (cr=1 pr=0 pw=0 time=19 us)
0 0 0 INDEX UNIQUE SCAN SYS_C0010012 (cr=1 pr=0 pw=0 time=11 us)(object id 93050)
0 0 0 TABLE ACCESS BY INDEX ROWID HOGE (cr=1 pr=0 pw=0 time=10 us)
0 0 0 INDEX UNIQUE SCAN SYS_C0010012 (cr=1 pr=0 pw=0 time=2 us)(object id 93050)

p001のトレース(抜粋)

不思議ですが、これは、元のクエリーがあるけど、データを取得する SQLID=1u03tbqvywyf8(前述したRESULT_CACHEヒントのついてるクエリ)が生成されていない!!
containers句を含むクエリのみあり、rowsも0、HOGEをといあわせる再帰SQL文を生成する必要のない表。HOGE表が存在しないのは今のところSEEDのみ。
HOGE表が存在しないので、 C##HOGE.HOGE表をアクセスするSQL文を実行したらエラーですからねぇ。無駄なことはしないはず。

ふむふむふむ。

・・・中略・・・

SQL ID: 25a37y74xrat4 Plan Hash: 1439328272

select *
from
containers(hoge) where id in (1,3)


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 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 2 0.00 0.00 0 0 0 0

Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 103 (C##HOGE) (recursive depth: 1)
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ---------------------------------------------------
0 0 0 PX COORDINATOR (cr=0 pr=0 pw=0 time=0 us)
0 0 0 PX SEND QC (RANDOM) :TQ10000 (cr=0 pr=0 pw=0 time=0 us cost=-9223372036854775808 size=78 card=1)
0 0 0 PX PARTITION LIST ALL PARTITION: 1 254 (cr=0 pr=0 pw=0 time=189 us cost=-9223372036854775808 size=78 card=1)
0 0 0 FIXED TABLE FULL X$CDBVW$ (cr=0 pr=0 pw=0 time=12 us cost=-9223372036854775808 size=78 card=1)

p002のトレースファイル(抜粋)


・・・中略・・・

SQL ID: 25a37y74xrat4 Plan Hash: 1439328272

select *
from
containers(hoge) where id in (1,3)


call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.05 0 0 0 0
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 2 0.00 0.05 0 0 0 0

Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 103 (C##HOGE) (recursive depth: 1)
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ---------------------------------------------------
0 0 0 PX COORDINATOR (cr=0 pr=0 pw=0 time=0 us)
0 0 0 PX SEND QC (RANDOM) :TQ10000 (cr=0 pr=0 pw=0 time=0 us cost=-9223372036854775808 size=78 card=1)
1 1 1 PX PARTITION LIST ALL PARTITION: 1 254 (cr=961 pr=0 pw=0 time=121936 us cost=-9223372036854775808 size=78 card=1)
1 1 1 FIXED TABLE FULL X$CDBVW$ (cr=961 pr=0 pw=0 time=121610 us cost=-9223372036854775808 size=78 card=1)

・・・中略・・・

お! Fetch=1で、rows=1 HOGE表から1行フェッチしているので2つのPDBのいずれかということになりますね!!
ORのUNION ALLへの書き換えがOR条件の順序通りであれば、以下の赤字部分の結果からみればたぶん、ID=3のでデータが存在している方のPDBであるはず。

SQL ID: 1u03tbqvywyf8 Plan Hash: 1725204971

SELECT /*+ RESULT_CACHE (SYSOBJ=TRUE SHELFLIFE=30) */ ID,DATA
FROM
"C##HOGE"."HOGE" "HOGE" WHERE "HOGE"."ID"=1 OR "HOGE"."ID"=3


call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 1 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 1 0.00 0.00 0 3 0 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 3 0.00 0.00 0 4 0 1

Misses in library cache during parse: 1
Optimizer mode: CHOOSE
Parsing user id: SYS (recursive depth: 2)
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ---------------------------------------------------
1 1 1 RESULT CACHE 6158j5h7rmww7g9fxb6fwawgvy (cr=3 pr=0 pw=0 time=120 us)
1 1 1 CONCATENATION (cr=3 pr=0 pw=0 time=44 us)
0 0 0 TABLE ACCESS BY INDEX ROWID HOGE (cr=1 pr=0 pw=0 time=15 us)
0 0 0 INDEX UNIQUE SCAN SYS_C0014566 (cr=1 pr=0 pw=0 time=9 us)(object id 99927)
1 1 1 TABLE ACCESS BY INDEX ROWID HOGE (cr=2 pr=0 pw=0 time=18 us)
1 1 1 INDEX UNIQUE SCAN SYS_C0014566 (cr=1 pr=0 pw=0 time=5 us)(object id 99927)


p003もp002のトレース同様 Fetch=1で、rows=1 HOGE表から1行フェッチしているので2つのPDBのいずれかということになりますね!!
p003のSQLトレースファイル


・・・中略・・・


SQL ID: 25a37y74xrat4 Plan Hash: 1439328272

select *
from
containers(hoge) where id in (1,3)


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 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 2 0.00 0.00 0 0 0 0

Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 103 (C##HOGE) (recursive depth: 1)
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ---------------------------------------------------
0 0 0 PX COORDINATOR (cr=0 pr=0 pw=0 time=0 us)
0 0 0 PX SEND QC (RANDOM) :TQ10000 (cr=0 pr=0 pw=0 time=0 us cost=-9223372036854775808 size=78 card=1)
1 1 1 PX PARTITION LIST ALL PARTITION: 1 254 (cr=1793 pr=0 pw=0 time=119492 us cost=-9223372036854775808 size=78 card=1)
1 1 1 FIXED TABLE FULL X$CDBVW$ (cr=1793 pr=0 pw=0 time=119279 us cost=-9223372036854775808 size=78 card=1)

・・・中略・・・


plan hash = 0 でParse = 1なのでやはりパースだけ。

SQL ID: g2nujq01pmynd Plan Hash: 0

SELECT /* */ *
FROM
"C##HOGE"."HOGE"


call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 0 0.00 0.00 0 0 0 0
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 1 0.00 0.00 0 0 0 0

Misses in library cache during parse: 1
Optimizer mode: CHOOSE
Parsing user id: SYS (recursive depth: 2)
********************************************************************************

・・・中略・・・

やはり、rows=1 これも1行フェッチしているのでデータ登録済みの2PDBのいずれかで実行されているクエリだという点は間違いないらしい
そして、赤字部分のrowsからORの順番からして、ID=1のデータのあるPDBか。

SQL ID: 1u03tbqvywyf8 Plan Hash: 1990946707

SELECT /*+ RESULT_CACHE (SYSOBJ=TRUE SHELFLIFE=30) */ ID,DATA
FROM
"C##HOGE"."HOGE" "HOGE" WHERE "HOGE"."ID"=1 OR "HOGE"."ID"=3


call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 1 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 1 0.00 0.00 0 3 0 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 3 0.00 0.00 0 4 0 1

Misses in library cache during parse: 1
Optimizer mode: CHOOSE
Parsing user id: SYS (recursive depth: 2)
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ---------------------------------------------------
1 1 1 RESULT CACHE 24q4fuaf71g7jf1upwg76y3a3q (cr=3 pr=0 pw=0 time=94 us)
1 1 1 CONCATENATION (cr=3 pr=0 pw=0 time=49 us)
1 1 1 TABLE ACCESS BY INDEX ROWID HOGE (cr=2 pr=0 pw=0 time=23 us)
1 1 1 INDEX UNIQUE SCAN SYS_C0010048 (cr=1 pr=0 pw=0 time=11 us)(object id 92602)
0 0 0 TABLE ACCESS BY INDEX ROWID HOGE (cr=1 pr=0 pw=0 time=11 us)
0 0 0 INDEX UNIQUE SCAN SYS_C0010048 (cr=1 pr=0 pw=0 time=5 us)(object id 92602)


SQLトレースで見たのが一番追いやすかったのですが(個人的に)、実践でこれをやるのは、少々辛いのでcontainers句を業務APで使っててチューニングという状況には遭遇したくないなw)

containers句の場合、実際にユーザ表にアクセスするために生成される再起SQL部分をいかにして特定するかが、
チューニング前の課題になってくるのは間違いなさそう。(今の所は)
SQLレポートやSQL監視が進化して、containsers句の場合は該当再起SQL文と実行計画も表示してくれたら楽かもしれないですけどね(それはAWRレポートも同様)

ということで、今日はここまで。

CDBとPDBの間で迷子になりそう PART3 - SQL*PlusのAutotrace編
CDBとPDBの間で迷子になりそう PART3 - SQL*PlusのAutotrace編 - その2
CDBとPDBの間で迷子になりそう PART3 - containers clause
CDBとPDBの間で迷子になりそう PART3 - containers clause - その2

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

2017年3月24日 (金)

CDBとPDBの間で迷子になりそう PART3 - containers clause - その2

Previously on Mac De Oracle.
CDBとPDBの間で迷子になりそう PART3 - containers clause

昨日は、AWRで再帰SQL文として各PDBで実行されるSQL文を捉えた!ところまででした。


今日はそのAWRレポートを見てみようと思います。

それらしきSQL文は、AWRレポートのSQL ordered by User I/O Wait Timeなど幾つかのセクションで見つかった!!!(テキストフォーマットで出力しています)

元のSQL文で付加したコメントは再帰SQL文にはまったく引きづがれないので、多くのSQL文をcontainers句で実行していたら紐づけるの大変そうだろうという予感とともに、ヒントによるチューニングってほぼ無理なんじゃないかって思います。
(RDF Graph系の似たような句というか関数だと幾つかのヒントを渡せる仕組みもあるんですがねぇ、これは無理っぽい)

使えるとすればSPMかな。

で、recult cacheも使うようなので、そのあたりの待機イベントも多少気にかける必要もでてくるかもしれない。
と、とーくを見ながら...

どう使うか次第でしょうけど、もし、チューニングが必要な状態になったら辛くなりそうだ!、という気配だけは強く感じたところで、今日は時間切れ。

SQL ordered by User I/O Wait Time       DB/Inst: ORCL12C/orcl12c  Snaps: 71-72
-> Resources reported for PL/SQL code includes the resources used by all SQL
statements called by the code.
-> %Total - User I/O Time as a percentage of Total User I/O Wait time
-> %CPU - CPU Time as a percentage of Elapsed Time
-> %IO - User I/O Time as a percentage of Elapsed Time
-> Captured SQL account for 44.2% of Total User I/O Wait Time (s):
-> Captured PL/SQL account for 39.8% of Total User I/O Wait Time (s):

User I/O UIO per Elapsed
Time (s) Executions Exec (s) %Total Time (s) %CPU %IO SQL Id
---------- ------------ ---------- ------ ---------- ------ ------ -------------

・・・中略・・・

0.0 1 0.00 2.6 0.0 92.9 6.9 fj6g3jvma49dq
Module: SQL*Plus
select /* test01 */ * from containers(emp) where empno=7369

・・・中略・・・

0.0 1 0.00 1.1 0.0 88.2 11.4 0n3ta15r2qc98
Module: SQL*Plus
PDB: PDBORCL12C
SELECT /*+ RESULT_CACHE (SYSOBJ=TRUE SHELFLIFE=30) */ EMPNO,ENAME,JOB,MGR,HIREDA
TE,SAL,COMM,DEPTNO FROM "C##HOGE"."EMP" "EMP" WHERE "EMP"."EMPNO"=7369

0.0 1 0.00 1.1 0.0 88.2 11.4 0n3ta15r2qc98
Module: SQL*Plus
PDB: PDBORCL12C
SELECT /*+ RESULT_CACHE (SYSOBJ=TRUE SHELFLIFE=30) */ EMPNO,ENAME,JOB,MGR,HIREDA
TE,SAL,COMM,DEPTNO FROM "C##HOGE"."EMP" "EMP" WHERE "EMP"."EMPNO"=7369

0.0 1 0.00 1.0 0.0 89.8 12.0 0n3ta15r2qc98
Module: SQL*Plus
PDB: PDBORCL12CLONED
SELECT /*+ RESULT_CACHE (SYSOBJ=TRUE SHELFLIFE=30) */ EMPNO,ENAME,JOB,MGR,HIREDA
TE,SAL,COMM,DEPTNO FROM "C##HOGE"."EMP" "EMP" WHERE "EMP"."EMPNO"=7369

0.0 1 0.00 1.0 0.0 89.8 12.0 0n3ta15r2qc98
Module: SQL*Plus
PDB: PDBORCL12CLONED
SELECT /*+ RESULT_CACHE (SYSOBJ=TRUE SHELFLIFE=30) */ EMPNO,ENAME,JOB,MGR,HIREDA
TE,SAL,COMM,DEPTNO FROM "C##HOGE"."EMP" "EMP" WHERE "EMP"."EMPNO"=7369

参考までに、各SQLの実行計画を(AWR SQLレポートより)

Execution Plan
-----------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost | Pstart| Pstop | TQ |IN-OUT| PQ Distrib |
-----------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 1 | | | | | |
| 1 | PX COORDINATOR | | | | | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10000 | 1 | 100 | | | | Q1,00 | P->S | QC (RAND) |
| 3 | PX PARTITION LIST ALL| | 1 | 100 | | 1 | 254 | Q1,00 | PCWC | |
| 4 | FIXED TABLE FULL | X$CDBVW$ | 1 | 100 | | | | Q1,00 | PCWP | |
-----------------------------------------------------------------------------------------------------------------

Note
-----
- cpu costing is off (consider enabling it)

Full SQL Text

SQL ID SQL Text
------------ -----------------------------------------------------------------
fj6g3jvma49d select /* test01 */ * from containers(emp) where empno=7369



Execution Plan
------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 1 (100)|
| 1 | RESULT CACHE | bxqp7vj85m72tbusfcmqynsj1t | | | |
| 2 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 87 | 0 (0)|
| 3 | INDEX UNIQUE SCAN | PK_EMP | 1 | | 0 (0)|
------------------------------------------------------------------------------------------------

Result Cache Information (identified by operation id):
------------------------------------------------------

1 -

Full SQL Text

SQL ID SQL Text
------------ -----------------------------------------------------------------
0n3ta15r2qc9 SELECT /*+ RESULT_CACHE (SYSOBJ=TRUE SHELFLIFE=30) */ EMPNO, ENAM
E, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO FROM "C##HOGE"."EMP" "EM
P" WHERE "EMP"."EMPNO"=7369

次回でこのシリーズは最終回にするかも。。もう1つ2つ追加するかも。。。

To be continued.


CDBとPDBの間で迷子になりそう PART3 - SQL*PlusのAutotrace編
CDBとPDBの間で迷子になりそう PART3 - SQL*PlusのAutotrace編 - その2
CDBとPDBの間で迷子になりそう PART3 - containers clause

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

2017年3月22日 (水)

CDBとPDBの間で迷子になりそう PART3 - containers clause

Previously on Mac De Oracle.

CDBとPDBの間で迷子になりそう PART3 - SQL*PlusのAutotrace編 - その2
auto traceでcontainers句の実行計画をながめたら、原型を留めないほど、変わり果てた実行計画をみて、ここから原型の実行計画をどうやったら見つけられるんだろうかと、途方にくれたところまででしたw


パラレル実行され、各pdbのemp表からempno=7369のデータがindex range scanで取得されているはず。
そして、再帰SQL文として、原文が各PDBで実行されているんだろうなぁ。
といところまではマニュアルの記述と、変わり果てた実行計画をみて、なんとなくイメージはできるんですが。。。

では、どうやったら各PDBで実行されているはずのSQL文や実行計画が見えるんだろう??

auto traceでは見ることはできなかったので、次!、SQL監視で試してみます。(ダメだと思いますが、念のため)

C##HOGE@orcl12c> select /*+ monitor */ * from containers(emp) where empno=7369;

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO CON_ID
---------- ---------- --------- ---------- -------- ---------- ---------- ---------- ----------
7369 SMITH CLERK 7902 80-12-17 800 20 4
7369 SMITH CLERK 7902 80-12-17 800 20 3


SQL監視をテキストモードで取得する自作スクリプトを実行して、実行計画を見ると....
んーっ。パラレルであるところは気づきやすいですが、やはり、原型を留めぬ変わり果てた実行計画しかみえませんねぇ。

C##HOGE@orcl12c> @show_realplan
1に値を入力してください:
旧 1: select dbms_sqltune.report_sql_monitor('&1') from dual
新 1: select dbms_sqltune.report_sql_monitor('') from dual

DBMS_SQLTUNE.REPORT_SQL_MONITOR('')
--------------------------------------
SQL Monitoring Report

SQL Text
------------------------------
select /*+ monitor */ * from containers(emp) where empno=7369

・・・中略・・・

Global Stats
=================================================
| Elapsed | Cpu | Other | Fetch | Buffer |
| Time(s) | Time(s) | Waits(s) | Calls | Gets |
=================================================
| 0.01 | 0.01 | 0.00 | 2 | 6 |
=================================================

Parallel Execution Details (DOP=4 , Servers Allocated=4)
==========================================================================================
| Name | Type | Server# | Elapsed | Cpu | Other | Buffer | Wait Events |
| | | | Time(s) | Time(s) | Waits(s) | Gets | (sample #) |
==========================================================================================
| PX Coordinator | QC | | 0.00 | 0.00 | 0.00 | | |
| p000 | Set 1 | 1 | 0.00 | 0.00 | | | |
| p001 | Set 1 | 2 | 0.00 | | 0.00 | | |
| p002 | Set 1 | 3 | 0.00 | | 0.00 | 3 | |
| p003 | Set 1 | 4 | 0.00 | 0.00 | | 3 | |
==========================================================================================

SQL Plan Monitoring Details (Plan Hash Value=1439328272)
===================================================================================================================================
| Id | Operation | Name | Rows | Cost | Time | Start | Execs | Rows | Activity | Activity Detail |
| | | | (Estim) | | Active(s) | Active | | (Actual) | (%) | (# samples) |
===================================================================================================================================
| 0 | SELECT STATEMENT | | | | 1 | +0 | 5 | 2 | | |
| 1 | PX COORDINATOR | | | | 1 | +0 | 5 | 2 | | |
| 2 | PX SEND QC (RANDOM) | :TQ10000 | 1 | | 1 | +0 | 4 | 2 | | |
| 3 | PX PARTITION LIST ALL | | 1 | | 1 | +0 | 4 | 2 | | |
| 4 | FIXED TABLE FULL | X$CDBVW$ | 1 | | 1 | +0 | 4 | 2 | | |
===================================================================================================================================

次は、AWRレポートでチャレンジ!

SYS@orcl12c> exec dbms_workload_repository.create_snapshot;

・・・中略・・・

C##HOGE@orcl12c> show con_name

CON_NAME
------------------------------
CDB$ROOT

C##HOGE@orcl12c> select * from containers(emp) where empno=7369;

・・・中略・・・

SYS@orcl12c> exec dbms_workload_repository.create_snapshot;

・・・中略・・・

SYS@orcl12c> @?/rdbms/admin/awrrpt

・・・中略・・・


....おかしいなぁ。捕まえられない!

AWRレポートで捕まえることができなかったのは環境上の影響(Shared Pool Sizeが小さ過ぎでエージアウトしちゃった、とか)もあったのかもしれません。しかもいろいろ動いていたので辛かったはず。
Shared Pool Sizeの下限値を大きめにして、

再チャレンジ。。。ん? 

こんどは取れたっぽい。原型とは多少違いますが、かなり近いSQL文が見つかりました! そいつに違いない!!

というところで、今日は時間切れ、To be continued....


CDBとPDBの間で迷子になりそう PART3 - SQL*PlusのAutotrace編
CDBとPDBの間で迷子になりそう PART3 - SQL*PlusのAutotrace編 - その2

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

2017年3月21日 (火)

CDBとPDBの間で迷子になりそう PART3 - SQL*PlusのAutotrace編 - その2

間が空いてしまいましたが、

CDBとPDBの間で迷子になりそう PART3 - SQL*PlusのAutotrace編

のつづきです。


前回は、共通ユーザを作成し、CDB$ROOT、及び残りの2つのPDBでauto traceができるようになって、さりげなく、containers句なんてのを試していたところまででした。

今日はcontainers句で遊びはじめるところからスタート!
まず初めに、containters句でなにができるのかマニュアルで確認しておきましょう。(マニュアル読めよ! お約束w

45.10 CONTAINERS句を使用したコンテナ間の問合せ
http://docs.oracle.com/cd/E82638_01/ADMIN/viewing-information-about-cdbs-and-pdbs-with-sql-plus.htm#GUID-B302A0DA-8A56-4C18-B140-ADD5E682DE60

45.10.1 CONTAINERS句を使用したコンテナ間の問合せの概要
http://docs.oracle.com/cd/E82638_01/ADMIN/viewing-information-about-cdbs-and-pdbs-with-sql-plus.htm#GUID-AD8C9596-67BB-47FA-A728-16F9C9B0AADF

45.10.3 アプリケーションPDB間のアプリケーション共通オブジェクトの問合せ
http://docs.oracle.com/cd/E82638_01/ADMIN/viewing-information-about-cdbs-and-pdbs-with-sql-plus.htm#GUID-7B4E4926-19C6-47A5-A4E3-6BD279F080F0

containers句を利用すると、
CDB$ROOTの共通ユーザから各PDBの同一共通ユーザにある同一表を問い合わせることができるようになる。
また、containers句を利用したクエリーから再帰SQLが生成され、デフォルトではパラレル化される。。と。
なお、パラレル化はされるが、パラレル文のキューイング対象でもない! (え! 対象外なの?)

この時点で、癖者感がw

再帰的SQL実行と、さらり書かれているところ。。気になる気になる、気になりすぎて眠れないw

気になったら確かめないと!!

CDB$ROOTのsysユーザにて全PDBが起動していることを確認!

SYS@orcl12c> show pdbs

CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 PDBORCL12C READ WRITE NO
4 PDBORCL12CLONED READ WRITE NO


CDB$ROOTの共通ユーザ:C##HOGEにEMP表(空)があるこを確認
CDB$ROOTにも同一名のオブジェクトが存在しないとエラーになるのでご注意を。(ここは別エントリで書くかも)

SYS@orcl12c> conn c##hoge/hoge@orcl12c
接続されました。
C##HOGE@orcl12c> select table_name from user_tables where table_name='EMP';

TABLE_NAME
------------------------------
EMP

C##HOGE@orcl12c> select count(*) from emp;

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


以下、残る2つのPDBで、共通ユーザ:C##HOGEユーザにEMP表(データあり)が存在することを確認!

C##HOGE@orcl12c> conn c##hoge/hoge@pdborcl12c
接続されました。
C##HOGE@pdborcl12c> select table_name from user_tables where table_name='EMP';

TABLE_NAME
------------------------------
EMP

C##HOGE@pdborcl12c> select count(*) from emp;

COUNT(*)
----------
14

C##HOGE@pdborcl12c> conn c##hoge/hoge@pdborcl12cloned
接続されました。
C##HOGE@pdborcl12cloned> select table_name from user_tables where table_name='EMP';

TABLE_NAME
------------------------------
EMP

C##HOGE@pdborcl12cloned> select count(*) from emp;

COUNT(*)
----------
14


containers句を含む以下のクエリーをCDB$ROOTの共通ユーザ:C##HOGEユーザから実行!

SYS@orcl12c> conn c##hoge/hoge
接続されました。
C##HOGE@orcl12c> select * from containers(emp) where empno=7369;

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO CON_ID
---------- ---------- --------- ---------- -------- ---------- ---------- ---------- ----------
7369 SMITH CLERK 7902 80-12-17 800 20 4
7369 SMITH CLERK 7902 80-12-17 800 20 3

auto traceでどんな実行計画なのか見てみます(CDB$ROOTでauto traceをやりたかったのはこういうことだったんでっす!w)

マニュアルに記載されている通り、パラレルクエリーになってます!
しかし、実行計画には、emp表という名前は見当たらず!! しかも、EMPNOには主キー制約があるのに、Predicate Information にはfilter("EMPNO"=7369)とある。

....."生成される再帰的SQL文ということばが浮かんで消える":) 不思議な実行計画が!!!!!!

でも、この実行計画、なんとなく見覚え.....ないですか????

C##HOGE@orcl12c> set autot trace exp stat
C##HOGE@orcl12c> select * from containers(emp) where empno=7369;

実行計画
----------------------------------------------------------
Plan hash value: 1439328272

----------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Pstart| Pstop | TQ |IN-OUT| PQ Distrib |
----------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 100 | 0 (0)| | | | | |
| 1 | PX COORDINATOR | | | | | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10000 | 1 | 100 | | | | Q1,00 | P->S | QC (RAND) |
| 3 | PX PARTITION LIST ALL| | 1 | 100 | | 1 | 254 | Q1,00 | PCWC | |
|* 4 | FIXED TABLE FULL | X$CDBVW$ | 1 | 100 | | | | Q1,00 | PCWP | |
----------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

4 - filter("EMPNO"=7369)


統計
----------------------------------------------------------
303 recursive calls
0 db block gets
249 consistent gets
9 physical reads
0 redo size
1220 bytes sent via SQL*Net to client
552 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
18 sorts (memory)
0 sorts (disk)
2 rows processed


見覚えがあると思ったら、まさにこれですよね。
12.1.0.2で突然登場した機能のようにも見えるが、実は、12.1.0.1のころからあった機能らしい。CDB$VIEW clauseとして。
実行計画もそっくり

12.1.0.2 CDB views are now using CONTAINERS() / dbi services BLOG
https://blog.dbi-services.com/12102-cdb-views-are-now-using-containers/

SQL> select * from v$version;

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

SQL> show con_name

CON_NAME
------------------------------
CDB$ROOT
SQL>
SQL> select * from cdb$view(dual);


実行計画
----------------------------------------------------------
Plan hash value: 4256768476

-----------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | TQ |IN-OUT| PQ Distrib |
-----------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 | 0 (0)| 00:00:01 | | | | | |
| 1 | PX COORDINATOR | | | | | | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10000 | 1 | 2 | 0 (0)| 00:00:01 | | | Q1,00 | P->S | QC (RAND) |
| 3 | PX PARTITION LIST ALL| | 1 | 2 | 0 (0)| 00:00:01 | 1 | 254 | Q1,00 | PCWC | |
| 4 | FIXED TABLE FULL | X$CDBVW$42ae64ee | 1 | 2 | 0 (0)| 00:00:01 | | | Q1,00 | PCWP | |
-----------------------------------------------------------------------------------------------------------------------------------------


統計
----------------------------------------------------------
12 recursive calls
0 db block gets
6 consistent gets
0 physical reads
0 redo size
688 bytes sent via SQL*Net to client
544 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
2 rows processed

45.10.3 アプリケーションPDB間のアプリケーション共通オブジェクトの問合せ
これ、アプリケーションからお気軽に使っちゃってよい機能なんだろうか。。。どのようなユースケースを想定した機能なんだろう?。。。

to be continued...

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

2017年1月 9日 (月)

CDBとPDBの間で迷子になりそう PART3 - SQL*PlusのAutotrace編

今回迷子になったのは、昔からあるSQL*PlusのAutotraceで.

Autotraceの使い方は、$ORACLE_HOME/sqlplus/admin/plustrce.sqlをSYSユーザーで実行し、PLUSTRACEロール作成されたら必要なユーザーへ該当ロールを付与。
あとは、SQL*Plusでautotraceを有効にする。

これだけです。

が、

マルチテナント(シングルテナント含む)化した途端に、迷子になりそうな場面に出会います!
(これにハマったことのあるかたは、#ローカルロール! ってハッシュタグでtw...しなくてもいいですw)

マルチテナントでは、共通ユーザー、共通ロール、ローカルユーザー、ローカルロールという2つのタイプのユーザーとロールが登場しました。
CDB$ROOT/各PDBのディクショナリービュー同様、頭では理解したつもりでも指が勝手タイプして迷子になっちゃいうこともあるw (実はOracleさんも?。。。だったりしてね。

余談はこれぐらいにして、とにかく試して見ましょう。

バージョンは以下のとおり

SYS@orcl12c> select * from v$version;

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

マルチテナントにしてあります。(シングルテナントでも同じですが)

SYS@orcl12c> show pdbs

CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 PDBORCL12C READ WRITE NO
4 PDBORCL12CLONED READ WRITE NO


今日の主役、共通ユーザを作成します。
共通ユーザーとするためには、c##(デフォルト)という接頭子をユーザ名に付加する必要があります。(なれるまで辛いw)

SYS@orcl12c> create user c##hoge identified by hoge
2 default tablespace users
3 temporary tablespace temp
4 quota unlimited on users
5 container=all;

ユーザーが作成されました。


CDB$ROOT含む全PDBにC##HOGEユーザが作成されました。
(実はシステム定義の管理ユーザーは共通ユーザー扱になっていることも忘れちゃいけないんですよね。おそらく同じというか特徴はあるはず)

SYS@orcl12c> select con_id,username,common from containers(dba_users) where username in ('SYS','C##HOGE')

CON_ID USERNAME COM
---------- ------------------------------ ---
1 SYS YES
1 C##HOGE YES
4 SYS YES
4 C##HOGE YES
3 SYS YES
3 C##HOGE YES

※さりげなく、PDB CONTAINER句(赤字部分)を使ってますが、もともとそれで遊びたかっただけなんです。


今後のお遊び向けにいくつかのシステム権限の付与...

SYS@orcl12c> grant create session ,resource to c##hoge container=all;

権限付与が成功しました。

SYS@orcl12c> grant create table, create view to c##hoge container=all;

権限付与が成功しました。

SYS@orcl12c> grant create synonym to c##hoge container=all;

権限付与が成功しました。


共通ユーザーでもSQL*Plusのautotrace使いたいな〜と。
(最近はアダプティブな実行計画の影響で影が薄いAutotraceやExplain planですが、とりあえず見たい時や、実行統計を軽く見たいときには便利なんで)

と、思ったとことから、迷子になりまして、、はいw

CDB$ROOTの共通ユーザー接続して、autotraceを有効にしようとしました。
みなれたエラーがでるわけですよ。ロール作ってないので:)

”SP2-0618: セッション識別子が見つかりません。PLUSTRACEロールが有効かを確認してください。”

SYS@orcl12c> conn c##hoge/hoge
接続されました。
C##HOGE@orcl12c> show con_name

CON_NAME
------------------------------
CDB$ROOT

C##HOGE@orcl12c>
C##HOGE@orcl12c> set autot on
SP2-0618: セッション識別子が見つかりません。PLUSTRACEロールが有効かを確認してください。
SP2-0611: STATISTICSレポートを使用可能にするときにエラーが発生しました。


いつものように、$ORACLE_HOME/sqlplus/admin/plustrce.sqlを実行してPLUSTRACEロールを作成しようとすると。。。。。
なんと、ロールが作成できません!!!

そりゃ、そうですよね。CDB$ROOTには共通なものが載るわけですから、。。。
マルチテナント化してあるので、ロールも共通ロールを作成する必要があります。。。オラクルさん。。。。痛恨のミス?!w

PLUSTRACEというロールをCDB$ROOTに作成しようとするとローカルロールを作成している扱いになるので、共通ロールにしてねというエラーが返されます。

どうすんだよwこれw
と、初っ端から迷子ですw (MOSは未確認。なにか記載されてそうな気はしますがw)

C##HOGE@orcl12c> conn / as sysdba
接続されました。
SYS@orcl12c> @?/sqlplus/admin/plustrce
SYS@orcl12c>

...中略...

1SYS@orcl12c> create role plustrace;
create role plustrace
*
行1でエラーが発生しました。:
ORA-65096: 共通ユーザーまたはロール名が無効です

共通ロールにしろというんだから、素直に共通ロールを作ってみます。
$ORACLE_HOME/sqlplus/admin/plustrce.sqlを元に、ロール名をPLUSTRACEからC##PLUSTRACEに変更したスクリプトを作成しました。

共通ロールについては、以下も参照のこと。
Oracle® Databaseセキュリティ・ガイド 12cリリース1 (12.1) 共通ロールの作成

以下のように、C##(共通ユーザやロールのデフォルト接頭子)を付加し共通ユーザ向けロールを作成すればできるようになりますよね!。使う機会があるかどうかは別ですがw

C##HOGE@orcl12c> !cat $ORACLE_HOME/sqlplus/admin/plustrce_common.sql 

drop role c##plustrace;
create role c##plustrace;

grant select on v_$sesstat to c##plustrace;
grant select on v_$statname to c##plustrace;
grant select on v_$mystat to c##plustrace;
grant c##plustrace to dba with admin option;

C##PLUSTRACEの作成ログ
うまくいきました!!!

SYS@orcl12c> drop role c##plustrace;
drop role c##plustrace
*
行1でエラーが発生しました。:
ORA-01919: ロール'C##PLUSTRACE'は存在しません

SYS@orcl12c> create role c##plustrace;

ロールが作成されました。

SYS@orcl12c> grant select on v_$sesstat to c##plustrace;

権限付与が成功しました。

SYS@orcl12c> grant select on v_$statname to c##plustrace;

権限付与が成功しました。

SYS@orcl12c> grant select on v_$mystat to c##plustrace;

権限付与が成功しました。

SYS@orcl12c> grant c##plustrace to dba with admin option;

権限付与が成功しました。

作成したautotrace用共通ロールをcontainter=allで共通ユーザに付与したのですが。。。。
実は、container=allとしても。PDB側では今まで通り、$ORACLE_HOME/sqlplus/admin/plustrce.sqlを各PDBのSYSユーザー実行し、PLUSTRACEロール(ローカルロール)をPDBに存在する共通ユーザ個別に付与する必要があるようです。(面倒くさい><)

SYS@orcl12c> grant c##plustrace to c##hoge container=all;

C##HOGE@orcl12c> conn / as sysdba
接続されました。
SYS@orcl12c>
SYS@orcl12c> conn c##hoge/hoge
接続されました。
C##HOGE@orcl12c> show con_name

CON_NAME
------------------------------
CDB$ROOT
C##HOGE@orcl12c> set autot trace exp stat
C##HOGE@orcl12c> select * from dual;

実行計画
----------------------------------------------------------
Plan hash value: 272002086

--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| DUAL | 1 | 2 | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------

統計
----------------------------------------------------------
0 recursive calls
0 db block gets
3 consistent gets
0 physical reads
0 redo size
561 bytes sent via SQL*Net to client
552 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed


PDB側のC##HOGEユーザーには繼承されない。。。。。かるく迷子になってる状況。

C##HOGE@orcl12c> conn c##hoge/hoge@pdborcl12c
接続されました。
C##HOGE@pdborcl12c>
C##HOGE@pdborcl12c> show con_name

CON_NAME
------------------------------
PDBORCL12C
C##HOGE@pdborcl12c> set autot trace exp stat
SP2-0618: セッション識別子が見つかりません。PLUSTRACEロールが有効かを確認してください。
SP2-0611: STATISTICSレポートを使用可能にするときにエラーが発生しました。

各PDBのローカルユーザーは、以前からあるplustrce.sqlを各PDBごとに個別に作成、付与する必要があるみたい...もう完全に迷子w。
(本当はこれをネタしたかったわけじゃなかったんですけどね、トホホ)

C##HOGE@pdborcl12c> conn sys@pdborcl12c as sysdba
パスワードを入力してください:
接続されました。
SYS@pdborcl12c>
SYS@pdborcl12c>
SYS@pdborcl12c> show con_name

CON_NAME
------------------------------
PDBORCL12C
SYS@pdborcl12c>
SYS@pdborcl12c> @?/sqlplus/admin/plustrce

...中略...

SYS@pdborcl12c> conn c##hoge/hoge@pdborcl12c
接続されました。
C##HOGE@pdborcl12c> set autot trace exp stat
C##HOGE@pdborcl12c> select * from dual;


実行計画
----------------------------------------------------------
Plan hash value: 272002086

--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| DUAL | 1 | 2 | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------

統計
----------------------------------------------------------
1 recursive calls
0 db block gets
3 consistent gets
2 physical reads
0 redo size
561 bytes sent via SQL*Net to client
552 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed


次回、本当に試したかったことへ、つづく....(予定)
久々にその機能本気で使うのかって、ネタになりそうで。。。いいかも(こんな展開は予想してなかっただけに;)


以上、はじめての、 Yahoo! Japan Coworking Space LODGE より


関連エントリー FAQ になりそうな、12c MTA環境での統計履歴管理 ー CDBとPDBの間で迷子になりそう PART2

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

2016年7月19日 (火)

DB Tech Showcase 2016 Tokyo - E35 - SQLチューニング総合診療所的予防医学のセッション資料

DB Tech Showcase 2016 Tokyo - E35 - SQLチューニング総合診療所的予防医学のセッション資料を公開しました。

ぼくとつと、性能試験データの質などのことを言い続ける感じになっていたでしょうか?w

ところで、次回のJPOUG主催のイベントの開催が決まりました。セッション内容は現在準備中ですが、確定次第随時更新します。
お申し込みは以下のイベントベージよりお願いします。

JPOUG in 15 minutes #1

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

2016年3月13日 (日)

FAQ になりそうな、12c MTA環境での統計履歴管理 ー CDBとPDBの間で迷子になりそう PART2

PART1ってあったっけ? というのは置いといて、
PART III以降もなにかありそうなアトモスフィアなのですが、ここで書いておかないとハマりそうなので備忘録代わりに。


みなさん、統計履歴って知ってます?
dbms_stats.gather_*_stats を実行するとオプティマイザ統計情報が取得された表、索引、列統計が自動的にバックアップされることを。
そのバックアップは統計履歴と呼ばれています。(履歴統計と呼んでる人のほうが多いと思うのですが。。。マニュアルだと統計履歴って書いてますね。。。。誰も履歴統計を統計履歴だろ、それ! と突っ込んでくれなてなかった気がw)

Oracle® Database SQLチューニング・ガイド 12cリリース1(12.1) オプティマイザ統計の保存の管理
Oracle® Database PL/SQLパッケージおよびタイプ・リファレンス 12c リリース1(12.1) DBMS_STATS.GET_STATS_HISTORY_RETENTIONファンクション
Oracle® Database PL/SQLパッケージおよびタイプ・リファレンス 12c リリース1(12.1) DBMS_STATS.ALTER_STATS_HISTORY_RETENTIONプロシージャ
Oracle® Database PL/SQLパッケージおよびタイプ・リファレンス 12c リリース1(12.1) PURGE_STATSプロシージャ
Oracle® Database SQL言語リファレンス 12cリリース1 (12.1) SYS_CONTEXT


で、オプティマイザ統計収集が原因と思われる事象があった場合、統計履歴をリストアしてトラブルを華麗に回避なんて手法もあるんです。
古くは小田さんの記事でも取り上げられています。
門外不出のOracle現場ワザ 第4章 Oracleデータベースの頭脳 「オプティマイザ」徹底研究


と、ここまでは、11gとか12cでも非MTA環境のお話です。

先日、12cのMTA環境で統計履歴をリストアしようとしたら。。。統計履歴。。。なんとなく言いづらい。。。履歴統計が無いw
履歴統計の保存期間はデフォルトで31日なのでパージされる前に保存期間を無期限に変更しました。。。(その時はMTA環境の罠にハマったとは気付かず、無期限にしたからもう気にしなくていいや! と思ったんです)

ところが、いざ履歴統計をみると。。。。パージされてる。。。。。焦りましたw 

どういうことだったのか、最初に書いてしまうと、

履歴統計は、CDB/PDB、それぞれ独立して管理されてまっす!。

(え〜〜〜〜〜〜〜〜っ。知らんかったというか、マニュアルのどこかに記載されているのなら、どなたかそのページへのリンクをおしえてくだしぁ。。。)


久々に長〜い前置きはこれぐらいにして確認してみましょう。(--;

PDBが1つあるシングルテナント構成(1 PDB/CDB)で確認してみました。

CDB及び、PDBの履歴統計保存期間を確認します。(デフォルト設定のままです)
なにもしてないデフォルト状態では、CDBもPDBも履歴統計保存期間は31日となっています。


CDB側の履歴統計保存期間

SYSTEM@orcl12c> @show_stats_hist_retention

cdb name container name
-------------------- --------------------
orcl12c CDB$ROOT

stats history retention
-----------------------
31

PDB側の履歴統計保存期間

SYSTEM@pdborcl12c> @show_stats_hist_retention

cdb name container name
-------------------- --------------------
orcl12c PDBORCL12C

stats history retention
-----------------------
31


では最初にどちらも履歴統計を保存しない状態にしてみます。

CDB
履歴統計を保存なしに設定して既存履歴統計をパージ。
事前作成しておいた stats_hist_retention.sqlを実行。(スクリプトはエントリの最後に記載しておきました。)

DBMS_STATS.GATHER_DATABASE_STATSを実行しても履歴統計数の増加なし。想定通り。

SYSTEM@orcl12c> exec dbms_stats.alter_stats_history_retention(0);

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

SYSTEM@orcl12c> exec dbms_stats.purge_stats(null);

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

SYSTEM@orcl12c> @stats_hist_retention

cdb name container name
-------------------- --------------------
orcl12c CDB$ROOT


stats history retention
-----------------------
0

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


number of tab stats histories
-----------------------------
0


PDB

SYSTEM@pdborcl12c> exec dbms_stats.alter_stats_history_retention(0);

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

SYSTEM@pdborcl12c> exec dbms_stats.purge_stats(null);

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

SYSTEM@pdborcl12c> @stats_hist_retention

cdb name container name
-------------------- --------------------
orcl12c PDBORCL12C

stats history retention
-----------------------
0

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

number of tab stats histories
-----------------------------
0

さて、次にCDBの履歴統計保存期間を無期限に変更し、PDBは履歴統計保存なしにしてみます。

CDBの履歴統計数は増加し、PDB側は変化なしということになるはず。。。


CDB

SYSTEM@orcl12c> exec dbms_stats.alter_stats_history_retention(-1);

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

SYSTEM@orcl12c> @stats_hist_retention

cdb name container name
-------------------- --------------------
orcl12c CDB$ROOT

stats history retention
-----------------------
-1

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

number of tab stats histories
-----------------------------
2499

CDB側の履歴統計数が増加した。まあ、そうだよね〜。

PDB
PDB側は履歴統計無しのままなので変化はないです。個別に設定できてるからそうなんでしょうね。多分。

SYSTEM@pdborcl12c> @stats_hist_retention

cdb name container name
-------------------- --------------------
orcl12c PDBORCL12C


stats history retention
-----------------------
0

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

number of tab stats histories
-----------------------------
0


逆にしてみます。CDBは履歴統計無し、PDBの履歴統計保存期間を無期限にしてみます。
履歴統計はCDB/PDB個別管理ならCDBの履歴統計なし、PDB側には履歴統計ありという構成もできるはず!!

なお、確認しやすくするために、CDB側は履歴統計無しに変更後、履歴統計を手動パージしておきます。

CDB

SYSTEM@orcl12c> exec dbms_stats.alter_stats_history_retention(0);

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

SYSTEM@orcl12c> exec dbms_stats.purge_stats(null);

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

SYSTEM@orcl12c> @stats_hist_retention

cdb name container name
-------------------- --------------------
orcl12c CDB$ROOT

stats history retention
-----------------------
0

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

number of tab stats histories
-----------------------------
0




PDB
これが確認できれば問題なさそうですね。CDB/PDBの履歴統計保存期間の管理及びパージは個別管理できるってことで。。。。
Workload RepositoryはCDBでのみ管理できるようになっているので間違いやすいぞ、と
この辺りをまとめたマニュアルがあれば解りやすいのになぁ(ボソっ

SYSTEM@pdborcl12c> exec dbms_stats.alter_stats_history_retention(-1);

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

SYSTEM@pdborcl12c> @stats_hist_retention

cdb name container name
-------------------- --------------------
orcl12c PDBORCL12C

stats history retention
-----------------------
-1

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

number of tab stats histories
-----------------------------
2659


履歴統計は、CDB/PDB個別管理なので、履歴統計保存期間、履歴統計のパージはCDB/PDBそれぞれで行えるようですが、
Workload Repository:AWRのスナップショットの保存期間やパージなどは、CDBのみでしか行えない。(AWRのスナップショットはCDB/PDBどこで実行しても全体が取得されます。)


それに、PDBで変更できる初期化パラメータと変更できないパラメータのまとめがあればもっと便利かも。
以前調べたPDB側で変更できる初期化パラメータの保存場所とかも合わせてまとめとくか。。。

PDB毎に初期化パラメータを変更できるんですよ!(制限はあるけど) #1
PDB毎に初期化パラメータを変更できるんですよ!(制限はあるけど) #2 - PDBの初期化パラメータは何処!?
PDB毎に初期化パラメータを変更できるんですよ!(制限はあるけど) #3 - 消えたPDBの初期化パラメータの謎... Truth is out there.

いろいろ整理できてないので只今混乱中w


今回試した環境
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
PL/SQL Release 12.1.0.2.0 - Production
CORE 12.1.0.2.0 Production
TNS for Linux: Version 12.1.0.2.0 - Production
NLSRTL Version 12.1.0.2.0 - Production


使ったクエリーなど
stats_hist_retention.sql

SELECT 
SYS_CONTEXT('USERENV', 'CDB_NAME') AS "cdb name"
, SYS_CONTEXT('USERENV', 'CON_NAME') AS "container name"
FROM
dual;

SELECT
DBMS_STATS.GET_STATS_HISTORY_RETENTION AS "stats history retention"
FROM
dual;

EXEC DBMS_STATS.GATHER_DATABASE_STATS;

SELECT
COUNT(1) AS "number of tab stats histories"
FROM
dba_tab_stats_history;


show_stats_hist_retention.sql

SELECT 
SYS_CONTEXT('USERENV', 'CDB_NAME') AS "cdb name"
, SYS_CONTEXT('USERENV', 'CON_NAME') AS "container name"
FROM
dual;

SELECT
DBMS_STATS.GET_STATS_HISTORY_RETENTION AS "stats history retention"
FROM
dual;

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

2015年12月26日 (土)

クリスマスのお遊び - SQL de Fractals :)

Twitterを見ていたら以下のtweetが目に入った! お! 面白そう。

元のサイトを覗いてみたら :) w
EXPLAIN EXTENDED -
http://explainextended.com/2013/12/31/happy-new-year-5/

元ネタはPostgreSQLだったので、Oracle Database 12c R1で書き換えて遊んでみた。 :)
遊びながら覚えるSQLってのも面白いよね。久々にLISTAGGなんて使ったよw
20151226_23132


元々あるOracleの方言、階層問合せと、11gR2から実装された階層再帰問合せを組み合わせてます。
PostgreSQLでは、generate_series()関数が利用されていますが、Oracleでは階層問合せかCUBEとrownumを組み合わせて生成するしかないのでちょいとカッコ悪いかもw
ただ、ARRAY_TO_STRING(ARRAY_AGG(s ORDER BY r), '') の箇所は、Oracleなら LISTAGG WITHIN...と1つの関数で代替できたので判りやすいかも。

WITH
q (r, i, rx, ix, g) AS
(
SELECT
CAST(r.r AS DOUBLE PRECISION) * 0.02 AS r
, CAST(i.i AS DOUBLE PRECISION) * 0.02 AS i
, CAST(.0 AS DOUBLE PRECISION) AS rx
, CAST(.0 AS DOUBLE PRECISION) AS ix
, 0 AS g
FROM
(
SELECT
LEVEL - 61 AS r
FROM
DUAL
CONNECT BY
LEVEL <= 80
) r,
(
SELECT
LEVEL - 51 AS i
FROM
DUAL
CONNECT BY
LEVEL <= 100
) i
UNION ALL
SELECT
r
, i
, CASE
WHEN ABS(rx * rx + ix * ix) <= 2
THEN
rx * rx - ix * ix
END + r AS rx
, CASE
WHEN ABS(rx * rx + ix * ix) <= 2
THEN
2 * rx * ix
END + i AS ix
, g + 1 AS g
FROM
q
WHERE
rx IS NOT NULL
AND g < 99
)
SELECT
LISTAGG(s,'') WITHIN GROUP ( ORDER BY r ) AS Mandelbrot
FROM
(
SELECT
i
, r
, SUBSTR(' .:-=+*#%@', MAX(g) / 10 + 1, 1) s
FROM
q
GROUP BY
i
, r
) q
GROUP BY
i
ORDER BY
i
;


実行計画も載せておきますね
こんな実行計画になるのか〜〜〜面白〜い :) :) :)

Global Stats
=================================================
| Elapsed | Cpu | Other | Fetch | Buffer |
| Time(s) | Time(s) | Waits(s) | Calls | Gets |
=================================================
| 35 | 35 | 0.05 | 8 | 22M |
=================================================

SQL Plan Monitoring Details (Plan Hash Value=1659179395)
============================================================================================================================================================
| Id | Operation | Name | Rows | Cost | Time | Start | Execs | Rows | Mem | Activity | Activity Detail |
| | | | (Estim) | | Active(s) | Active | | (Actual) | (Max) | (%) | (# samples) |
============================================================================================================================================================
| 0 | SELECT STATEMENT | | | | 1 | +35 | 1 | 100 | | | |
| 1 | SORT GROUP BY | | 2 | 8 | 1 | +35 | 1 | 100 | 499K | | |
| 2 | VIEW | | 2 | 8 | 1 | +35 | 1 | 8000 | | | |
| 3 | HASH GROUP BY | | 2 | 8 | 34 | +2 | 1 | 8000 | 1M | | |
| 4 | VIEW | | 2 | 8 | 34 | +2 | 1 | 424K | | | |
| 5 | UNION ALL (RECURSIVE WITH) BREADTH FIRST | | | | 35 | +1 | 1 | 424K | 16M | 100.00 | Cpu (35) |
| 6 | MERGE JOIN CARTESIAN | | 1 | 4 | 1 | +2 | 1 | 8000 | | | |
| 7 | VIEW | | 1 | 2 | 1 | +2 | 1 | 80 | | | |
| 8 | CONNECT BY WITHOUT FILTERING | | | | 1 | +2 | 1 | 80 | 2048 | | |
| 9 | FAST DUAL | | 1 | 2 | 1 | +2 | 1 | 1 | | | |
| 10 | BUFFER SORT | | 1 | 4 | 1 | +2 | 80 | 8000 | 4096 | | |
| 11 | VIEW | | 1 | 2 | 1 | +2 | 1 | 100 | | | |
| 12 | CONNECT BY WITHOUT FILTERING | | | | 1 | +2 | 1 | 100 | 2048 | | |
| 13 | FAST DUAL | | 1 | 2 | 1 | +2 | 1 | 1 | | | |
| 14 | RECURSIVE WITH PUMP | | | | 34 | +2 | 100 | 416K | | | |
============================================================================================================================================================


追記!
Sql_de_fractals_frost_pattern


WITH
q (r, i, rx, ix, g) AS
(
SELECT
CAST(r.r AS DOUBLE PRECISION) * 0.0002 AS r
, CAST(i.i AS DOUBLE PRECISION) * 0.0002 AS i
, CAST(r.r AS DOUBLE PRECISION) * 0.0002 AS rx
, CAST(i.i AS DOUBLE PRECISION) * 0.0002 AS ix
, 0 AS g
FROM
(
SELECT
LEVEL - 201 AS r
FROM
DUAL
CONNECT BY
LEVEL <= 120
) r,
(
SELECT
LEVEL - 1 AS i
FROM
DUAL
CONNECT BY
LEVEL <= 100
) i
UNION ALL
SELECT
r
, i
, CASE
WHEN ABS(rx * rx + ix * ix) < 1E+8
THEN
rx * rx - ix * ix
END - 0.70176 AS rx
, CASE
WHEN ABS(rx * rx + ix * ix) < 1E+8
THEN
2 * rx * ix
END + 0.3842 AS ix
, g + 1 AS g
FROM
q
WHERE
rx IS NOT NULL
AND g < 99
)
SELECT
LISTAGG(s,'') WITHIN GROUP ( ORDER BY r ) AS frost_patterns
FROM
(
SELECT
i
, r
, SUBSTR(' .:-=+*#%@', MAX(g) / 10 + 1, 1) s
FROM
q
GROUP BY
i
, r
) q
GROUP BY
i
ORDER BY
i
;


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

2015年11月21日 (土)

WITH clause in-line PL/SQL functionって....

12cの新機能でオイタをしてみたw

with句に関数仕込んで内部でSQL文を実行してオイタしてみました。

実際にこのような使い方するんでしょうか?
これをやるなら素直にスカラー副問合せの方がいいと思うんですね.....
(スカラー副問合せのように使われたら、同じく12cの新機能、Scalar subquery unnestingもできなし。)

なんでこんな機能必要なんだろう?
どのような場面で、有効なんだろう?

今の所、使いどころが思い浮かばないので、誰か教えて〜〜〜〜〜! 
とモヤモヤしてたんですが、今日はお留守番で時間だけはあったので、ごにょごにょとw


SCOTT> set serveroutput on
SCOTT> set feed off
SCOTT> r
1 with
2 function hoge return varchar2
3 deterministic
4 as
5 begin
6 for rec in (select empno,ename from emp order by empno) loop
7 dbms_output.put_line('**** '||rec.empno||':'||rec.ename||' ****');
8 end loop;
9 return null;
10 end;
11 select
12 hoge
13 from
14 dual
15 where
16* hoge is not null

**** 7369:SMITH ****
**** 7499:ALLEN ****
**** 7521:WARD ****
**** 7566:JONES ****
**** 7654:MARTIN ****
**** 7698:BLAKE ****
**** 7782:CLARK ****
**** 7839:KING ****
**** 7844:TURNER ****
**** 7900:JAMES ****
**** 7902:FORD ****
**** 7934:MILLER ****

経過: 00:00:00.01

こんなことをやられると....
実行計画には現れないしw (ちなみにスカラー副問合せは実行計画を見ただけでわかりますです。はい)

ただのチューナーいじめじゃ >< w
SQLトレースなら補足できるけど、なんぎじゃのう。げほげほ

(WITH句のインラインPL/SQLファンクション(名称あってるのかな?)内部でSQL文は実行しない方がいいと思うけど。。。。???)


SCOTT> 
SCOTT> set autot trace exp stat
SCOTT> r
1 with
2 function hoge return varchar2
3 deterministic
4 as
5 begin
6 for rec in (select empno,ename from emp order by empno) loop
7 dbms_output.put_line('**** '||rec.empno||':'||rec.ename||' ****');
8 end loop;
9 return null;
10 end;
11 select
12 hoge
13 from
14 dual
15 where
16* hoge is not null

**** 7369:SMITH ****
**** 7499:ALLEN ****
**** 7521:WARD ****
**** 7566:JONES ****
**** 7654:MARTIN ****
**** 7698:BLAKE ****
**** 7782:CLARK ****
**** 7839:KING ****
**** 7844:TURNER ****
**** 7900:JAMES ****
**** 7902:FORD ****
**** 7934:MILLER ****

経過: 00:00:00.03

実行計画
----------------------------------------------------------
Plan hash value: 4034615273

-----------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 |
|* 1 | FILTER | | | | |
| 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 |
-----------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - filter("HOGE"() IS NOT NULL)


統計
----------------------------------------------------------
1 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
363 bytes sent via SQL*Net to client
541 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed




WITH句のインラインPL/SQLファンクション内でのSQL文の実行はダークサイドな香りしかしないので、使うならデータの加工等、計算中心目的かねぇ〜。とマニュアル読んでたら見つけたw
 
(マニュアルのサンプルも加工のみ! )

SCOTT> r
1 with
2 function hoge(eno number) return varchar2
3 deterministic
4 as
5 begin
6 dbms_output.put_line('Called');
7 return '**** '||eno||' ****';
8 end;
9 select
10 hoge(empno)
11 from
12* emp

HOGE(EMPNO)
---------------------------------------------------------------------
**** 7369 ****
**** 7499 ****
**** 7521 ****
**** 7566 ****
**** 7654 ****
**** 7698 ****
**** 7782 ****
**** 7839 ****
**** 7844 ****
**** 7900 ****
**** 7902 ****
**** 7934 ****
Called
Called
Called
Called
Called
Called
Called
Called
Called
Called
Called
Called
経過: 00:00:00.02

Database SQL Language Reference (12.1)
Database SQL Language Reference (12.1) - SELECT


みなさん、ダークサイドに落ちないように注意しましょうね! :)

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

2015年1月 2日 (金)

机上SQLチューニング、クイズ! 駆動表(外部表)はどれだ!!!! (実解答編)

JPOUG Advent Calendar 2014 17日目のエントリーで公開したクイズを実解答編です。
実際にOracle Database 12c 12.1.0.2.0を使ってどの表を駆動表(外部表)にするか確認してみます。


予想はあたるか、外れるか...どのような結果が待っているのか..ワクワクします。 :-)
Oracle® Database SQLチューニング・ガイド 12cリリース1(12.1) B71277-02 - 7 結合


前回の予想も参考に....机上SQLチューニング、クイズ! 駆動表(外部表)はどれだ!!!! (予想解答編)

問題1
次に示すSQL文の駆動表(外部表)はどれでしょうか? 

表と索引
create table a1 (
id number primary key
, data varchar2(1000)
) nologging
/
create table a2 (
id number primary key
, data varchar2(1000)
) nologging
/

統計情報
TABLE_NAME INDEX_NAME NUM_ROWS DISTINCT_KEYS CLUSTERING_FACTOR
-------------- -------------- ---------- ------------- -----------------
A1 SYS_C0010377 10000 10000 295
A2 SYS_C0010378 2000 2000 59

SELECT
/* SQL01 */
/*+
MONITOR
USE_NL(a1 a2)
*/
*
FROM
a1
INNER JOIN a2
ON
a1.id = a2.id
WHERE
a1.id BETWEEN 1 AND 100
/


私の答え(予想)
Nested Loop結合かつ、INNER JOINですから駆動表(外部表)はデータセットの小さい方。
(Nested Loop結合でOUTER JOINだと結合順は固定されるので駆動表は見つけやすいですが...INNER JOINの場合はそうはいかないですよね。ちなみに、最近のOracleだと、OUTER JOINでHash結合だと外部表を入れれかえて最適化するケースもあります。いずれどこかでそのネタをやると思います。)

ただ、結合条件キーはどちらも主キーですし、WHERE a1.id BETWEEN 1 AND 100は、a2表にも適用されることになるでしょうから、a1、a2どちらも最大で100行ヒットする可能性はあります。
どちらでも正解になる可能性はありますが...w (最初から引っ掛けかよw

細かい条件は提示していないので、提示した情報だけで机上で駆動表(外部表)を決めるとすれば、全体のサイズが小さい、a2でいいんじゃないでしょうか?(私ならそうします。机上ですから)
(当初、もう少し詳細な情報を提示しようとしていたのですが忘れてました...なのでa1だと思った方も可能性は五分五分ですね。前提条件不足でした。...ごめんなさい。ごめんなさい。)

Oracle Database 12c 12.1.0.2.0の動き
以下、SQLモニタリングレポートをみると、駆動表は、 a2表でした。 :)
ちなみに、a1を駆動表にした場合は、若干Buffer Getsが増加していました。誤差の範囲ですが...

SQL Monitoring Report

Global Stats
=======================================
| Elapsed | Other | Fetch | Buffer |
| Time(s) | Waits(s) | Calls | Gets |
=======================================
| 0.00 | 0.00 | 3 | 37 |
=======================================

SQL Plan Monitoring Details (Plan Hash Value=3695212685)
=====================================================================================================================================================
| Id | Operation | Name | Rows | Cost | Time | Start | Execs | Rows | Activity | Activity Detail |
| | | | (Estim) | | Active(s) | Active | | (Actual) | (%) | (# samples) |
=====================================================================================================================================================
| 0 | SELECT STATEMENT | | | | 1 | +0 | 1 | 20 | | |
| 1 | NESTED LOOPS | | 20 | 23 | 1 | +0 | 1 | 20 | | |
| 2 | NESTED LOOPS | | 20 | 23 | 1 | +0 | 1 | 20 | | |
| 3 | TABLE ACCESS BY INDEX ROWID BATCHED | A2 | 20 | 3 | 1 | +0 | 1 | 20 | | |
| 4 | INDEX RANGE SCAN | SYS_C0010378 | 20 | 2 | 1 | +0 | 1 | 20 | | |
| 5 | INDEX UNIQUE SCAN | SYS_C0010377 | 1 | | 1 | +0 | 20 | 20 | | |
| 6 | TABLE ACCESS BY INDEX ROWID | A1 | 1 | 1 | 1 | +0 | 20 | 20 | | |
=====================================================================================================================================================

問題2
次に示すSQL文の駆動表(外部表)はどれでしょうか? 
(表と索引、および、統計情報は問題1と同じです。)

SELECT
/* SQL02 */
/*+
MONITOR
USE_HASH(a1 a2)
*/
*
FROM
a1
INNER JOIN a2
ON
a1.id = a2.id
/

私の答え(予想)
Hash結合でINNER JOINかつ、WHERE句はないのでこの問題は簡単ですよね! (これは迷わないはず!!!)

Hash結合も外部表はデータセットの小さい方ですから...この場合だと、a2が外部表になるはず。

Oracle Database 12c 12.1.0.2.0の動き
以下、SQLモニタリングレポートから....外部表は、予想通りのa2

SQL Monitoring Report

Global Stats
=================================================
| Elapsed | Cpu | Other | Fetch | Buffer |
| Time(s) | Time(s) | Waits(s) | Calls | Gets |
=================================================
| 0.01 | 0.01 | 0.00 | 135 | 497 |
=================================================

SQL Plan Monitoring Details (Plan Hash Value=1713954154)
==================================================================================================================================
| Id | Operation | Name | Rows | Cost | Time | Start | Execs | Rows | Mem | Activity | Activity Detail |
| | | | (Estim) | | Active(s) | Active | | (Actual) | (Max) | (%) | (# samples) |
==================================================================================================================================
| 0 | SELECT STATEMENT | | | | 1 | +0 | 1 | 2000 | | | |
| 1 | HASH JOIN | | 2000 | 121 | 1 | +0 | 1 | 2000 | 1M | | |
| 2 | TABLE ACCESS FULL | A2 | 2000 | 19 | 1 | +0 | 1 | 2000 | | | |
| 3 | TABLE ACCESS FULL | A1 | 10000 | 102 | 1 | +0 | 1 | 10000 | | | |
==================================================================================================================================


問題3
次に示すSQL文の駆動表(外部表)はどれでしょうか? 
なお、D1とD2の多重度は、D1:D2 = 1:100
(個人的にUMLの多重度表記のほうが好きなので、UML表記の多重度で記述します。

表と索引
create table d1 (
id number
, data varchar2(1000)
) nologging
/
alter table d1 add constraint pk_d1 primary key (id) using index nologging
/
create table d2 (
id number not null
, seq# number not null
, data varchar2(1000)
) nologging
/
alter table d2 add constraint pk_d2 primary key (id, seq#) using index nologging
/

統計情報
TABLE_NAME INDEX_NAME NUM_ROWS DISTINCT_KEYS CLUSTERING_FACTOR
-------------- -------------- ---------- ------------- -----------------
D1 PK_D1 200 200 9
D2 PK_D2 20000 20000 870

SELECT
/* SQL03 */
/*+
MONITOR
*/
*
FROM
d2
WHERE
EXISTS (
SELECT
1
FROM
d1
WHERE
d1.id = d2.id
AND d1.id IN (1,5)
)
/


私の答え(予想)
これはちょっと意地悪な問題ですが、わかる人ならわかるはず。だと思って(信じて)作った問題です。 :)

最近のオプティマイザは、相関副問合せを可能であれば結合に書き換える(unnest)傾向が強いのをご存知でしょうか? 
となれば、方向はだいだい見えてきます。

d1.id IN (1,5)から最大で2件ヒットすると予想できますよね。
さらに、Nested Loop結合に書き換え、d2を内部表として結合できれば無駄がない。
つまり、駆動表は d1が理想的なはず。

d2を外部表にしてしまうと、WHERE条件がないので結合に置き換えてしまうとHash結合または、d2を全表走査して相関副問合せを都度実行のいづれかになってしまうでしょうね。(unnestの傾向が強いのでHash結合になる可能性が高そう)
ヒットするデータ件数から考えると、どちらも無駄なデータアクセスが多くなる可能性は高いのではないでしょうか。


Oracle Database 12c 12.1.0.2.0の動き
おおお〜。予想通り、相関副問合せは、unnestされて結合に書き換えられています。 さらに 12cの新機能であるAdaptive Joinになっています。興味深い。

で本題である、外部表はどうなっているかというと....pk_d1をindex only scanしてNested Loop結合になっています。つまり、駆動表は、予想通り、d1になっています。Yahoo!
id=1でHash結合がありますが、試行はしたようですが、実際にはNested Loop結合だったようです。

SQL Monitoring Report

Global Stats
=======================================
| Elapsed | Other | Fetch | Buffer |
| Time(s) | Waits(s) | Calls | Gets |
=======================================
| 0.01 | 0.01 | 15 | 44 |
=======================================

SQL Plan Monitoring Details (Plan Hash Value=804853015)
==============================================================================================================================================
| Id | Operation | Name | Rows | Cost | Time | Start | Execs | Rows | Activity | Activity Detail |
| | | | (Estim) | | Active(s) | Active | | (Actual) | (%) | (# samples) |
==============================================================================================================================================
| 0 | SELECT STATEMENT | | | | 1 | +0 | 1 | 0 | | |
| 1 | HASH JOIN | | 200 | 5 | 1 | +0 | 1 | 0 | | |
| 2 | NESTED LOOPS | | 200 | 5 | 1 | +0 | 1 | 200 | | |
| 3 | NESTED LOOPS | | 200 | 5 | 1 | +0 | 1 | 200 | | |
| 4 | STATISTICS COLLECTOR | | | | 1 | +0 | 1 | 1 | | |
| 5 | INLIST ITERATOR | | | | 1 | +0 | 1 | 2 | | |
| 6 | INDEX UNIQUE SCAN | PK_D1 | 2 | 1 | 1 | +0 | 2 | 2 | | |
| 7 | INDEX RANGE SCAN | PK_D2 | 1 | 1 | 1 | +0 | 2 | 200 | | |
| 8 | TABLE ACCESS BY INDEX ROWID | D2 | 100 | 2 | 1 | +0 | 200 | 200 | | |
| 9 | INLIST ITERATOR | | | | | | | | | |
| 10 | TABLE ACCESS BY INDEX ROWID BATCHED | D2 | 100 | 2 | | | | | | |
| 11 | INDEX RANGE SCAN | PK_D2 | 1 | 1 | | | | | | |
==============================================================================================================================================


問題4
次に示すSQL文の駆動表(外部表)はどれでしょうか? 
(表と索引、および、統計情報は問題3と同じです。)

SELECT
/* SQL04 */
/*+
MONITOR
*/
*
FROM
d1
INNER JOIN d2
ON
d1.id > d2.id
AND d2.id BETWEEN 1 AND 5
AND d2.seq# BETWEEN 2 AND 4
/

私の答え(予想)
結合条件が ">" であることに気付きましたか? ;)


これは、Nested Loop結合にも、Hash結合にもなりません。 Merge(sort/merge)結合が選択されます。

内部表は索引が利用できないのでソートが発生します。(ソートは避けられない)
外部表では索引を利用してソート処理が回避可能であれば、回避する。

つまりソート処理の影響を最小にしようとするはず、なので...

d1:d2=1:100という比率からd2のソート処理を重いと判断し回避するために外部表にするだろうなぁ〜〜。
私は、d2が外部表になるだろうと予想しています。
(直積じゃないMerge結合なんて最近お目にかかったことないのですが...)

余談)
Hash結合のない時代のOracleで、Merge結合の実行計画を見せられて、なんでソートしてるんですかね〜と、某ベンダーの方に質問されて一瞬固まったことを思い出したw


Oracle Database 12c 12.1.0.2.0の動き
良かったw。 予想どおりソートを回避したようで、 外部表は、 d2ですね。

SQL Monitoring Report

Global Stats
=================================================
| Elapsed | Cpu | Other | Fetch | Buffer |
| Time(s) | Time(s) | Waits(s) | Calls | Gets |
=================================================
| 0.02 | 0.01 | 0.01 | 198 | 48 |
=================================================

SQL Plan Monitoring Details (Plan Hash Value=705618498)
=============================================================================================================================================
| Id | Operation | Name | Rows | Cost | Time | Start | Execs | Rows | Mem | Activity | Activity Detail |
| | | | (Estim) | | Active(s) | Active | | (Actual) | (Max) | (%) | (# samples) |
=============================================================================================================================================
| 0 | SELECT STATEMENT | | | | 1 | +0 | 1 | 2955 | | | |
| 1 | MERGE JOIN | | 3966 | 10 | 1 | +0 | 1 | 2955 | | | |
| 2 | TABLE ACCESS BY INDEX ROWID | D2 | 20 | 4 | 1 | +0 | 1 | 15 | | | |
| 3 | INDEX RANGE SCAN | PK_D2 | 20 | 3 | 1 | +0 | 1 | 15 | | | |
| 4 | SORT JOIN | | 199 | 6 | 1 | +0 | 15 | 2955 | 145K | | |
| 5 | TABLE ACCESS FULL | D1 | 199 | 5 | 1 | +0 | 1 | 199 | | | |
=============================================================================================================================================


問題5
次に示すSQL文の駆動表(外部表)はどれでしょうか? 

表と索引定義
create table b1 (
id number
, data varchar2(1000)
) nologging
/
alter table b1 add constraint pk_b1 primary key(id) using index nologging
/
create table b3 (
id number
, seq# number
, data varchar2(1000)
) nologging
/
alter table b3 add constraint pk_b3 primary key (id, seq#) using index nologging
/
create table b2 (
id number
, seq# number
, subseq# number
, data varchar2(1000)
) nologging
/
alter table b2 add constraint pk_b2 primary key (id ,seq#, subseq#) using index nologging
/

統計情報
TABLE_NAME INDEX_NAME NUM_ROWS DISTINCT_KEYS CLUSTERING_FACTOR
-------------- -------------- ---------- ------------- -----------------
B1 PK_B1 20000 20000 870
B2 PK_B2 5000 5000 228
B3 PK_B3 500 500 23

ERDと多重度
b1 : b3 = 1 : 0..2
b3 : b2 = 1 : 0..10
(UML表記の多重度で記述しています。
20141221_120733

SELECT
/* SQL05 */
/*+
MONITOR
USE_HASH(b1 b3 b2)
*/
*
FROM
b1
INNER JOIN b3
ON
b1.id = b3.id
INNER JOIN b2
ON
b3.id = b2.id
AND b3.seq# = b2.seq#
/

私の答え(予想)
INNER JOINでHash結合かつ、WHERE句もないので簡単な問題ですよね。

外部表は、b3

ついでに、続けると、 b3とb2を結合すると最大で5000件、b3とb1を結合した場合、最大で500件なので、 結合順として理想的なのは、 b3, b1, b2 ですよね。


Oracle Database 12c 12.1.0.2.0の動き
結果は、予想通りでした〜。これは簡単だから!。

SQL Monitoring Report

Global Stats
=================================================
| Elapsed | Cpu | Other | Fetch | Buffer |
| Time(s) | Time(s) | Waits(s) | Calls | Gets |
=================================================
| 0.06 | 0.04 | 0.02 | 335 | 1476 |
=================================================

SQL Plan Monitoring Details (Plan Hash Value=3711653655)
===================================================================================================================================
| Id | Operation | Name | Rows | Cost | Time | Start | Execs | Rows | Mem | Activity | Activity Detail |
| | | | (Estim) | | Active(s) | Active | | (Actual) | (Max) | (%) | (# samples) |
===================================================================================================================================
| 0 | SELECT STATEMENT | | | | 1 | +0 | 1 | 5000 | | | |
| 1 | HASH JOIN | | 5000 | 315 | 1 | +0 | 1 | 5000 | 1M | | |
| 2 | HASH JOIN | | 500 | 247 | 1 | +0 | 1 | 500 | 1M | | |
| 3 | TABLE ACCESS FULL | B3 | 500 | 9 | 1 | +0 | 1 | 500 | | | |
| 4 | TABLE ACCESS FULL | B1 | 20000 | 238 | 1 | +0 | 1 | 20000 | | | |
| 5 | TABLE ACCESS FULL | B2 | 5000 | 68 | 1 | +0 | 1 | 5000 | | | |
===================================================================================================================================


問題6
次に示すSQL文の駆動表(外部表)はどれでしょうか? 
(表と索引、および、統計情報は問題5と同じです。)

SELECT
/* SQL06 */
/*+
MONITOR
USE_HASH(b1 b3 b2)
*/
*
FROM
b1
LEFT OUTER JOIN b3
ON
b1.id = b3.id
LEFT OUTER JOIN b2
ON
b3.id = b2.id
AND b3.seq# = b2.seq#
/

私の答え(予想)
OUTER JOINなのですが、Hash結合なので、多分、予想通りにはならないだろうな〜〜と。

最近のオプティマイザは外部結合かつHash結合の場合、外部表と内部表をデータセットサイズに応じて入れ替える傾向が強いんですよね。PGAの使用サイズが小さくなるように....

とは言っても、机上の話なので、入れ替えないとしたらどうなるだろう..と、外部結合なので、内部表は、そのまま内部表として結合したほうがわかりやすいといえばわかりやすい。
(統計情報に乖離がある場合には入れ替えないほうが良い結果だったりすることもあります。)

注)()内を先に結合するものとします。
入れ替えなかった場合は、記述したままなので、(外部表、内部表)=外部表、内部表ということで、 (b1, b3), b2
データセットの小さい順に従えば、外部表と、内部表をいれかえて、b3, b1この結果セットの最大件数は元の外部表がb1ですから20,250件、b2が5,000件なので、また外部表と内部表を入れ替えて、結果として、b2, (b3, b1)ってことに...
(内部的に結合順が入れ替えられ、Right Joinに置き換えられることが多いんですよね〜いつ頃からだろう...10gあたりか。)

で、机上ならどちらを取るかということですが、机上では、ひとまず、SQL文の通りとしておくケースが多いです。あくまで私の場合ですよ。(難しいんですよ、これ。外れる可能性大w)
オプティマイザが内部的に外部表と内部表を入れ替えて問題がなければよし、問題があれば、内部的な入れ替えをヒントで止めるというのが私の基本方針なので、この辺りは、チューナーさんのさじ加減次第じゃないかなぁ、と思っています。

あはは、むずかし過ぎたか... 机上だと orz.

Oracle Database 12c 12.1.0.2.0の動き
結果を見てみると〜〜〜〜〜っ。恐れていたw 外部表と内部表の置き換え操作(LEFT OUTERがRIGHT OUTER)になってますね〜っ。あはは、見事に、外れました....orz.

SQL Monitoring Report

Global Stats
=================================================
| Elapsed | Cpu | Other | Fetch | Buffer |
| Time(s) | Time(s) | Waits(s) | Calls | Gets |
=================================================
| 0.34 | 0.21 | 0.13 | 1651 | 2648 |
=================================================

SQL Plan Monitoring Details (Plan Hash Value=1453650298)
======================================================================================================================================
| Id | Operation | Name | Rows | Cost | Time | Start | Execs | Rows | Mem | Activity | Activity Detail |
| | | | (Estim) | | Active(s) | Active | | (Actual) | (Max) | (%) | (# samples) |
======================================================================================================================================
| 0 | SELECT STATEMENT | | | | 4 | +0 | 1 | 24750 | | | |
| 1 | HASH JOIN RIGHT OUTER | | 203K | 316 | 4 | +0 | 1 | 24750 | 3M | | |
| 2 | TABLE ACCESS FULL | B2 | 5000 | 68 | 1 | +0 | 1 | 5000 | | | |
| 3 | HASH JOIN RIGHT OUTER | | 20250 | 247 | 4 | +0 | 1 | 20250 | 1M | | |
| 4 | TABLE ACCESS FULL | B3 | 500 | 9 | 1 | +0 | 1 | 500 | | | |
| 5 | TABLE ACCESS FULL | B1 | 20000 | 238 | 4 | +0 | 1 | 20000 | | | |
======================================================================================================================================

問題ごとの解説をおまけで何回かに分けて、書いた方が良さそうだなw

ということで、おまけエントリーを書くかも...し、れ、な、い。


机上SQLチューニング、クイズ! 駆動表(外部表)はどれだ!!!!
机上SQLチューニング、クイズ! 駆動表(外部表)はどれだ!!!! (予想解答編)

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

2015年1月 1日 (木)

机上SQLチューニング、クイズ! 駆動表(外部表)はどれだ!!!! (予想解答編)

JPOUG Advent Calendar 2014 17日目のエントリーで公開したクイズの予想解答編です。
机上ですし、限られた情報しか提示していないので、実際にやってみたら違う...ということも十分ありえます。 (^^;;;;


外部表はどれがいいか予想できると、いろいろな制限のあるチューニング現場では役立つこともあるんです。LEADINGヒント等で結合順を考える場合にも役立ちますyo!
机上の予想なので間違うこともあります。オプティマイザも統計情報から予想しているわけで(Adaptiveな機能を除く)ハズすことも多いですから... (^^

Oracle® Database SQLチューニング・ガイド 12cリリース1(12.1) B71277-02 - 7 結合


問題1
次に示すSQL文の駆動表(外部表)はどれでしょうか? 

表と索引
create table a1 (
id number primary key
, data varchar2(1000)
) nologging
/
create table a2 (
id number primary key
, data varchar2(1000)
) nologging
/

統計情報
TABLE_NAME INDEX_NAME NUM_ROWS DISTINCT_KEYS CLUSTERING_FACTOR
-------------- -------------- ---------- ------------- -----------------
A1 SYS_C0010377 10000 10000 295
A2 SYS_C0010378 2000 2000 59

SELECT
/* SQL01 */
/*+
MONITOR
USE_NL(a1 a2)
*/
*
FROM
a1
INNER JOIN a2
ON
a1.id = a2.id
WHERE
a1.id BETWEEN 1 AND 100
/

私の答え(予想)
Nested Loop結合かつ、INNER JOINですから駆動表(外部表)はデータセットの小さい方。
(Nested Loop結合でOUTER JOINだと結合順は固定されるので駆動表は見つけやすいですが...INNER JOINの場合はそうはいかないですよね)

ただ、結合条件キーはどちらも主キーですし、WHERE a1.id BETWEEN 1 AND 100は、a2表にも適用されることになるでしょうから、a1、a2どちらも最大で100行ヒットする可能性はあります。
どちらでも正解になる可能性はありますが...w (最初から引っ掛けかよw

細かい条件は提示していないので、提示した情報だけで机上で駆動表(外部表)を決めるとすれば、全体のサイズが小さい、a2でいいんじゃないでしょうか?(私ならそうします。机上ですから)
(当初、もう少し詳細な情報を提示しようとしていたのですが忘れてました...なのでa1だと思った方も可能性は五分五分ですね。前提条件不足でした。...ごめんなさい。ごめんなさい。)


問題2
次に示すSQL文の駆動表(外部表)はどれでしょうか? 
(表と索引、および、統計情報は問題1と同じです。)

SELECT
/* SQL02 */
/*+
MONITOR
USE_HASH(a1 a2)
*/
*
FROM
a1
INNER JOIN a2
ON
a1.id = a2.id
/

私の答え(予想)
Hash結合でINNER JOINかつ、WHERE句はないのでこの問題は簡単ですよね! (これは迷わないはず!!!)

Hash結合も外部表はデータセットの小さい方ですから...この場合だと、a2が外部表になるはず。

問題3
次に示すSQL文の駆動表(外部表)はどれでしょうか? 
なお、D1とD2の多重度は、D1:D2 = 1:100
(個人的にUMLの多重度表記のほうが好きなので、UML表記の多重度で記述します。

表と索引
create table d1 (
id number
, data varchar2(1000)
) nologging
/
alter table d1 add constraint pk_d1 primary key (id) using index nologging
/
create table d2 (
id number not null
, seq# number not null
, data varchar2(1000)
) nologging
/
alter table d2 add constraint pk_d2 primary key (id, seq#) using index nologging
/

統計情報
TABLE_NAME INDEX_NAME NUM_ROWS DISTINCT_KEYS CLUSTERING_FACTOR
-------------- -------------- ---------- ------------- -----------------
D1 PK_D1 200 200 9
D2 PK_D2 20000 20000 870

SELECT
/* SQL03 */
/*+
MONITOR
*/
*
FROM
d2
WHERE
EXISTS (
SELECT
1
FROM
d1
WHERE
d1.id = d2.id
AND d1.id IN (1,5)
)
/


私の答え(予想)
これはちょっと意地悪な問題ですが、わかる人ならわかるはず。だと思って(信じて)作った問題です。 :)

最近のオプティマイザは、相関副問合せを可能であれば結合に書き換える(unnest)傾向が強いのをご存知でしょうか? 
となれば、方向はだいだい見えてきます。

d1.id IN (1,5)から最大で2件ヒットすると予想できますよね。
さらに、Nested Loop結合に書き換え、d2を内部表として結合できれば無駄がない。
つまり、駆動表は d1が理想的なはず。

d2を外部表にしてしまうと、WHERE条件がないので結合に置き換えてしまうとHash結合または、d2を全表走査して相関副問合せを都度実行のいづれかになってしまうでしょうね。(unnestの傾向が強いのでHash結合になる可能性が高そう)
ヒットするデータ件数から考えると、どちらも無駄なデータアクセスが多くなる可能性は高いのではないでしょうか。

問題4
次に示すSQL文の駆動表(外部表)はどれでしょうか? 
(表と索引、および、統計情報は問題3と同じです。)

SELECT
/* SQL04 */
/*+
MONITOR
*/
*
FROM
d1
INNER JOIN d2
ON
d1.id > d2.id
AND d2.id BETWEEN 1 AND 5
AND d2.seq# BETWEEN 2 AND 4
/

私の答え(予想)
結合条件が ">" であることに気付きましたか? ;)


これは、Nested Loop結合にも、Hash結合にもなりません。 Merge(sort/merge)結合が選択されます。

内部表は索引が利用できないのでソートが発生します。(ソートは避けられない)
外部表では索引を利用してソート処理が回避可能であれば、回避する。

つまりソート処理の影響を最小にしようとするはず、なので...

d1:d2=1:100という比率からd2のソート処理を重いと判断し回避するために外部表にするだろうなぁ〜〜。
私は、d2が外部表になるだろうと予想しています。
(直積じゃないMerge結合なんて最近お目にかかったことないのですが...)

余談)
Hash結合のない時代のOracleで、Merge結合の実行計画を見せられて、なんでソートしてるんですかね〜と、某ベンダーの方に質問されて一瞬固まったことを思い出したw


問題5
次に示すSQL文の駆動表(外部表)はどれでしょうか? 

表と索引定義
create table b1 (
id number
, data varchar2(1000)
) nologging
/
alter table b1 add constraint pk_b1 primary key(id) using index nologging
/
create table b3 (
id number
, seq# number
, data varchar2(1000)
) nologging
/
alter table b3 add constraint pk_b3 primary key (id, seq#) using index nologging
/
create table b2 (
id number
, seq# number
, subseq# number
, data varchar2(1000)
) nologging
/
alter table b2 add constraint pk_b2 primary key (id ,seq#, subseq#) using index nologging
/

統計情報
TABLE_NAME INDEX_NAME NUM_ROWS DISTINCT_KEYS CLUSTERING_FACTOR
-------------- -------------- ---------- ------------- -----------------
B1 PK_B1 20000 20000 870
B2 PK_B2 5000 5000 228
B3 PK_B3 500 500 23

ERDと多重度
b1 : b3 = 1 : 0..2
b3 : b2 = 1 : 0..10
(UML表記の多重度で記述しています。
20141221_120733

SELECT
/* SQL05 */
/*+
MONITOR
USE_HASH(b1 b3 b2)
*/
*
FROM
b1
INNER JOIN b3
ON
b1.id = b3.id
INNER JOIN b2
ON
b3.id = b2.id
AND b3.seq# = b2.seq#
/

私の答え(予想)
INNER JOINでHash結合かつ、WHERE句もないので簡単な問題ですよね。

外部表は、b3

ついでに、続けると、 b3とb2を結合すると最大で5000件、b3とb1を結合した場合、最大で500件なので、 結合順として理想的なのは、 b3, b1, b2 ですよね。


問題6
次に示すSQL文の駆動表(外部表)はどれでしょうか? 
(表と索引、および、統計情報は問題5と同じです。)

SELECT
/* SQL06 */
/*+
MONITOR
USE_HASH(b1 b3 b2)
*/
*
FROM
b1
LEFT OUTER JOIN b3
ON
b1.id = b3.id
LEFT OUTER JOIN b2
ON
b3.id = b2.id
AND b3.seq# = b2.seq#
/

私の答え(予想)
OUTER JOINなのですが、Hash結合なので、多分、予想通りにはならないだろうな〜〜と。

最近のオプティマイザは外部結合かつHash結合の場合、外部表と内部表をデータセットサイズに応じて入れ替える傾向が強いんですよね。PGAの使用サイズが小さくなるように....

とは言っても、机上の話なので、入れ替えないとしたらどうなるだろう..と、外部結合なので、内部表は、そのまま内部表として結合したほうがわかりやすいといえばわかりやすい。
(統計情報に乖離がある場合には入れ替えないほうが良い結果だったりすることもあります。)


注)()内を先に結合するものとします。
入れ替えなかった場合は、記述したままなので、(外部表、内部表)=外部表、内部表ということで、 (b1, b3), b2
データセットの小さい順に従えば、外部表と、内部表をいれかえて、b3, b1。
この結果セットの最大件数は元の外部表がb1ですから20,250件、b2が5,000件なので、また外部表と内部表を入れ替えて、結果として、b2, (b3, b1)ってことに...
(内部的に結合順が入れ替えられ、Right Joinに置き換えられることが多いんですよね〜いつ頃からだろう...10gあたりか。)

で、机上ならどちらを取るかということですが、机上では、ひとまず、SQL文の通りとしておくケースが多いです。あくまで私の場合ですよ。(難しいんですよ、これ。外れる可能性大w)
オプティマイザが内部的に外部表と内部表を入れ替えて問題がなければよし、問題があれば、内部的な入れ替えをヒントで止めるというのが私の基本方針なので、この辺りは、チューナーさんのさじ加減次第じゃないかなぁ、と思っています。

あはは、むずかし過ぎたか... 机上だと orz.

結合順がほぼ想定できる場合、状況次第で変わりそうな結合順、いろいろありますよね。
オプティマイザの気持ちになって考えてみると、いろいろ気づくことも多いんじゃないかなぁ。と思います。

オプティマイザってソートが嫌いなんだ〜、とか、PGA少ない方が好きなんだ〜とか....


役に立ったか、どうなのか不明なオチになりましたが.....

本年もよろしくお願いいたします。 m(_ _)m


あ、そうそう、一つ忘れてました。

次回は、Oracle Database 12c 12.1.0.2.0を使って試したオプティマイザが選択した駆動表(外部表)がどれだったかのか公開する予定です。


机上SQLチューニング、クイズ! 駆動表(外部表)はどれだ!!!!

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

2014年12月17日 (水)

机上SQLチューニング、クイズ! 駆動表(外部表)はどれだ!!!!

予備プラン発動中 :)

ということで、諸事情により開け忘れた窓を開けるためJPOUG Advent Calendar 2014 2回目の登場となりました。

JPOUG Advent Calendar 2014 17日目のエントリーです。


突然ですが、

「机上SQLチューーーーーニング、クイズ〜〜〜っ!!!!!!
 駆動表(外部表)はどれだ!!!!」


なお、このクイズには次の制限があります。

別途、本ブログで解答エントリーが公開(年明けを予定)されるまで、Oracle Databaseを利用して答え求めるのは禁止。 :-)
Oracle Databaseを利用せず、机上で、どの表を駆動表(外部表)にすれば理想的な実行計画になりそうか考えてみてね。

また、解答はOracle Database 12c Release 1 12.1.0.2.0 のオプティマイザをインストールしたまま(初期化パラメータはデフォルトのまま)の環境を使って行います。
(11gでも違わないと思いますが)

というクリスマスプレゼント :)

次に示されるSQL文の駆動表(外部表)はどれでしょうか? 

前提

統計情報と実データとの間に乖離はありません。
リテラル値で指定した検索条件に該当するデータは必ず存在します。


※引っ掛け問題もあるよ! :)


問題1
次に示すSQL文の駆動表(外部表)はどれでしょうか? 

表と索引
create table a1 (
id number primary key
, data varchar2(1000)
) nologging
/
create table a2 (
id number primary key
, data varchar2(1000)
) nologging
/

統計情報
TABLE_NAME INDEX_NAME NUM_ROWS DISTINCT_KEYS CLUSTERING_FACTOR
-------------- -------------- ---------- ------------- -----------------
A1 SYS_C0010377 10000 10000 295
A2 SYS_C0010378 2000 2000 59

SELECT
/* SQL01 */
/*+
MONITOR
USE_NL(a1 a2)
*/
*
FROM
a1
INNER JOIN a2
ON
a1.id = a2.id
WHERE
a1.id BETWEEN 1 AND 100
/

問題2
次に示すSQL文の駆動表(外部表)はどれでしょうか? 
(表と索引、および、統計情報は問題1と同じです。)

SELECT
/* SQL02 */
/*+
MONITOR
USE_HASH(a1 a2)
*/
*
FROM
a1
INNER JOIN a2
ON
a1.id = a2.id
/

問題3
次に示すSQL文の駆動表(外部表)はどれでしょうか? 
なお、D1とD2の多重度は、D1:D2 = 1:100
(個人的にUMLの多重度表記のほうが好きなので、UML表記の多重度で記述します。

表と索引
create table d1 (
id number
, data varchar2(1000)
) nologging
/
alter table d1 add constraint pk_d1 primary key (id) using index nologging
/
create table d2 (
id number not null
, seq# number not null
, data varchar2(1000)
) nologging
/
alter table d2 add constraint pk_d2 primary key (id, seq#) using index nologging
/

統計情報
TABLE_NAME INDEX_NAME NUM_ROWS DISTINCT_KEYS CLUSTERING_FACTOR
-------------- -------------- ---------- ------------- -----------------
D1 PK_D1 200 200 9
D2 PK_D2 20000 20000 870

SELECT
/* SQL03 */
/*+
MONITOR
*/
*
FROM
d2
WHERE
EXISTS (
SELECT
1
FROM
d1
WHERE
d1.id = d2.id
AND d1.id IN (1,5)
)
/


問題4
次に示すSQL文の駆動表(外部表)はどれでしょうか? 
(表と索引、および、統計情報は問題3と同じです。)

SELECT
/* SQL04 */
/*+
MONITOR
*/
*
FROM
d1
INNER JOIN d2
ON
d1.id > d2.id
AND d2.id BETWEEN 1 AND 5
AND d2.seq# BETWEEN 2 AND 4
/


問題5
次に示すSQL文の駆動表(外部表)はどれでしょうか? 

表と索引定義
create table b1 (
id number
, data varchar2(1000)
) nologging
/
alter table b1 add constraint pk_b1 primary key(id) using index nologging
/
create table b3 (
id number
, seq# number
, data varchar2(1000)
) nologging
/
alter table b3 add constraint pk_b3 primary key (id, seq#) using index nologging
/
create table b2 (
id number
, seq# number
, subseq# number
, data varchar2(1000)
) nologging
/
alter table b2 add constraint pk_b2 primary key (id ,seq#, subseq#) using index nologging
/

統計情報
TABLE_NAME INDEX_NAME NUM_ROWS DISTINCT_KEYS CLUSTERING_FACTOR
-------------- -------------- ---------- ------------- -----------------
B1 PK_B1 20000 20000 870
B2 PK_B2 5000 5000 228
B3 PK_B3 500 500 23

ERDと多重度
b1 : b3 = 1 : 0..2
b3 : b2 = 1 : 0..10
(UML表記の多重度で記述しています。
20141221_120733

SELECT
/* SQL05 */
/*+
MONITOR
USE_HASH(b1 b3 b2)
*/
*
FROM
b1
INNER JOIN b3
ON
b1.id = b3.id
INNER JOIN b2
ON
b3.id = b2.id
AND b3.seq# = b2.seq#
/


問題6
次に示すSQL文の駆動表(外部表)はどれでしょうか? 
(表と索引、および、統計情報は問題5と同じです。)

SELECT
/* SQL06 */
/*+
MONITOR
USE_HASH(b1 b3 b2)
*/
*
FROM
b1
LEFT OUTER JOIN b3
ON
b1.id = b3.id
LEFT OUTER JOIN b2
ON
b3.id = b2.id
AND b3.seq# = b2.seq#
/


冬休みの宿題〜〜〜〜っ。暇つぶしにトライしてみてくださいね。(ニヤニヤ 

解答エントリーの公開は年明けを予定していま〜す。

We wish your merry christmas and a happy new year!

次の扉は、Tamie Yamamotoさんです。

| | コメント (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年7月30日 (水)

Oracle Database 12c R1 12.1.0.2.0 In-memory option はじめの一歩。

こまけーことは置いといて、
Oracle Database 12c R1 12.1.0.2.0 In-memory optionが利用できるようになったので簡単に試してみた。


環境は以下の通り

Oracle VM VirtualBox 4.3.12 for OS X
Oracle Linux 6.4
Oracle Database 12c EE 12.1.0.2.0 for Linux x86-64


時間が無かったので、マニュアルを斜め読みしつつ、とにかくインストール....
inmemory系初期化パラメータの確認。 (12.1.0.1と12.1.0.2の初期化パラメータの差分確認はあとで:TODO)

inmemory_sizeパラメータが0なのでin-memory column storeは機能しない状態がデフォルトなのか..

Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
に接続されました。
SYS>
SYS> show parameter inmemory

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
inmemory_clause_default string
inmemory_force string DEFAULT
inmemory_max_populate_servers integer 0
inmemory_query string ENABLE
inmemory_size big integer 0
inmemory_trickle_repopulate_servers_ integer 1
percent
optimizer_inmemory_aware boolean TRUE
SYS>

以下の表を作成してあります。 10万行のうちb='1'である行は10行だけにしてあります。

SCOTT> desc foobar
名前 NULL? 型
----------------------------------------- -------- ----------------------------
A NUMBER
B CHAR(1)


SCOTT> select count(1) from foobar;

COUNT(1)
----------
100000


今まで通りに表を作成すると、in-memory column storeはdisabledで作成されるのか! ふむふむ。

SCOTT> select table_name,inmemory from user_tables where table_name='FOOBAR';

TABLE_NAME INMEMORY
------------------------------ --------
FOOBAR DISABLED

索引は作成していないので以下のようなクエリを実行すれば、TABLE ACCESS FULLですよね。

SCOTT> select /*+ gather_plan_statistics */ count(1) from foobar where b = '1';

COUNT(1)
----------
10

SCOTT> @show_actual_plan

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------
SQL_ID 4zurd70pg2qna, child number 0
-------------------------------------
select /*+ gather_plan_statistics */ count(1) from foobar where b = '1'

Plan hash value: 2479556450

---------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
---------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 191 |
| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 191 |
|* 2 | TABLE ACCESS FULL| FOOBAR | 1 | 15 | 10 |00:00:00.01 | 191 |
---------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - filter("B"='1')

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


23行が選択されました。


in-memory column storeを利用するための準備〜〜〜。
alter table文でin-memory column storeを有効化。(簡単だな!)

SCOTT> alter table foobar inmemory;

表が変更されました。


おっと、忘れてました、 inmemory_sizeパラメータを設定しないといけないんだった...

ちなみに、inmemory_sizeパラメータは静的パラメータなので、scope=spfileを付けることをお忘れなく...

SYS> alter system set inmemory_size = 10m;
alter system set inmemory_size = 10m
*
行1でエラーが発生しました。:
ORA-02097: 指定した値が無効なので、パラメータを変更できません。 ORA-02095:
指定した初期化パラメータを変更できません。


メモリ関係のパラメータ変えて起動しなくなるって過去やらかしたことがあるので、手が勝ってに動くw

SYS> create pfile from spfile;

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

変更できたました。
SYS> alter system set inmemory_size = 10m scope=spfile;

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

SYS>

....中略....

起動してみましょう! あらららら。

SYS> startup
ORA-64353: in-memory area size cannot be less than 100MB

ううううう、なんということでしょう! w このパラメータ間違うと起動しないのな!!!!! 注意しないと。 > 俺


in-memory初期化パラメータは 100MB以上に設定しましょうね。マニュアルにも書いてますから。(読みましょうね。 (^^;;;;

気を取り直して、再チャレンジ :)

[oracle@emperor ˜]$ sqlplus / as sysdba

SQL*Plus: Release 12.1.0.2.0 Production on 火 7月 29 06:34:46 2014

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

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

SYS> create spfile from pfile;

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

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

Total System Global Area 3875536896 bytes
Fixed Size 3717856 bytes
Variable Size 2248148256 bytes
Database Buffers 1610612736 bytes
Redo Buffers 13058048 bytes
データベースがマウントされました。
データベースがオープンされました。

SYS> alter system set inmemory_size = 100m scope=spfile;

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

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


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

Total System Global Area 3875536896 bytes
Fixed Size 3717856 bytes
Variable Size 2231371040 bytes
Database Buffers 1509949440 bytes
Redo Buffers 13058048 bytes
In-Memory Area 117440512 bytes
データベースがマウントされました。
データベースがオープンされました。
SYS>
SYS>


In-Memory Areaとリストされています。
うまくいったようなので in-memory column storeを試してみます!!!!

SCOTT> select /*+ gather_plan_statistics */ count(1) from foobar where b = '1';

COUNT(1)
----------
10

SCOTT>
SCOTT>
SCOTT> @show_actual_plan

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------
SQL_ID 4zurd70pg2qna, child number 0
-------------------------------------
select /*+ gather_plan_statistics */ count(1) from foobar where b = '1'

Plan hash value: 2479556450

------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 8 |
| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 8 |
|* 2 | TABLE ACCESS INMEMORY FULL| FOOBAR | 1 | 15 | 10 |00:00:00.01 | 8 |
------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - inmemory("B"='1')
filter("B"='1')

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


24行が選択されました。


in-memory column storeを利用しない場合、Buffer Getsが191ありましたが、in-memory column storeを利用した場合、Buffer Getsが8と大幅に減少しています!!!。データにもよるだろうけど、このケースだと、4%程度になってますね。

KEEP乗せとか手動でやらなくて済むケースあるんだろうな〜と、遠くを眺めながら.......in-memory column store初めの一歩はここまで。


つづく。

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

2014年7月26日 (土)

TABLE ACCESS BY INDEX ROWID BATCHED (Oracle Database 12c R1) ってなに! #3

つづきです。
バッファキャッシュにヒットした場合はどうかというと、物理I/Oは発生しないので、そのまんまの結果ですよね。(^^;;;

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 195 0.11 0.18 0 6287 0 2907
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 197 0.11 0.18 0 6287 0 2907

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 110 (SCOTT)
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ---------------------------------------------------
2907 2907 2907 NESTED LOOPS (cr=6287 pr=0 pw=0 time=206651 us)
2907 2907 2907 NESTED LOOPS (cr=3380 pr=0 pw=0 time=116870 us cost=5362 size=1744812 card=2851)
2907 2907 2907 TABLE ACCESS BY INDEX ROWID BATCHED HIGH_CLUSTERING_FACTOR (cr=3108 pr=0 pw=0 time=42395 us cost=2861 size=872406 card=2851)
2907 2907 2907 INDEX RANGE SCAN PK_HIGH_CLUSTERING_FACTOR (cr=201 pr=0 pw=0 time=12292 us cost=8 size=0 card=2851)(object id 93727)
2907 2907 2907 INDEX UNIQUE SCAN PK_LOW_CLUSTERING_FACTOR (cr=272 pr=0 pw=0 time=36902 us cost=0 size=0 card=1)(object id 93725)
2907 2907 2907 TABLE ACCESS BY INDEX ROWID LOW_CLUSTERING_FACTOR (cr=2907 pr=0 pw=0 time=37280 us cost=1 size=306 card=1)


Rows Execution Plan
------- ---------------------------------------------------
0 SELECT STATEMENT MODE: ALL_ROWS
2907 NESTED LOOPS
2907 NESTED LOOPS
2907 TABLE ACCESS MODE: ANALYZED (BY INDEX ROWID BATCHED) OF 'HIGH_CLUSTERING_FACTOR' (TABLE)
2907 INDEX MODE: ANALYZED (RANGE SCAN) OF 'PK_HIGH_CLUSTERING_FACTOR' (INDEX (UNIQUE))
2907 INDEX MODE: ANALYZED (UNIQUE SCAN) OF 'PK_LOW_CLUSTERING_FACTOR' (INDEX (UNIQUE))
2907 TABLE ACCESS MODE: ANALYZED (BY INDEX ROWID) OF 'LOW_CLUSTERING_FACTOR' (TABLE)


Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 195 0.00 0.00
SQL*Net message from client 195 0.00 0.15
SQL*Net more data to client 193 0.00 0.01
********************************************************************************

12cで、optimizer_features_enable='11.2.0.1'にしてバッファキャッシュをクリアすれば、11gと同じ実行計画(TABLE ACCESS BY INDEX ROWID)になって、db file parallel readになるよね!

という確認もしておいた!

call     count       cpu    elapsed       disk      query    current        rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.42 1.59 0 0 0 0
Execute 1 0.00 0.01 0 0 0 0
Fetch 195 18.34 61.02 2450 6287 0 2907
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 197 18.77 62.63 2450 6287 0 2907

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 110 (SCOTT)
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ---------------------------------------------------
2907 2907 2907 NESTED LOOPS (cr=6287 pr=2450 pw=0 time=92881090 us)
2907 2907 2907 NESTED LOOPS (cr=3380 pr=2232 pw=0 time=59488238 us cost=5362 size=1744812 card=2851)
2907 2907 2907 TABLE ACCESS BY INDEX ROWID HIGH_CLUSTERING_FACTOR (cr=3108 pr=2221 pw=0 time=31142410 us cost=2861 size=872406 card=2851)
2907 2907 2907 INDEX RANGE SCAN PK_HIGH_CLUSTERING_FACTOR (cr=201 pr=7 pw=0 time=3493710 us cost=8 size=0 card=2851)(object id 93727)
2907 2907 2907 INDEX UNIQUE SCAN PK_LOW_CLUSTERING_FACTOR (cr=272 pr=11 pw=0 time=10377721 us cost=0 size=0 card=1)(object id 93725)
2907 2907 2907 TABLE ACCESS BY INDEX ROWID LOW_CLUSTERING_FACTOR (cr=2907 pr=218 pw=0 time=13380036 us cost=1 size=306 card=1)


Rows Execution Plan
------- ---------------------------------------------------
0 SELECT STATEMENT MODE: ALL_ROWS
2907 NESTED LOOPS
2907 NESTED LOOPS
2907 TABLE ACCESS MODE: ANALYZED (BY INDEX ROWID BATCHED) OF 'HIGH_CLUSTERING_FACTOR' (TABLE)
2907 INDEX MODE: ANALYZED (RANGE SCAN) OF 'PK_HIGH_CLUSTERING_FACTOR' (INDEX (UNIQUE))
2907 INDEX MODE: ANALYZED (UNIQUE SCAN) OF 'PK_LOW_CLUSTERING_FACTOR' (INDEX (UNIQUE))
2907 TABLE ACCESS MODE: ANALYZED (BY INDEX ROWID) OF 'LOW_CLUSTERING_FACTOR' (TABLE)


Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 195 0.00 0.21
Disk file operations I/O 1 0.00 0.00
db file sequential read 452 0.21 1.54
SQL*Net message from client 195 15.35 16.71
SQL*Net more data to client 193 0.00 0.47
db file parallel read 190 0.05 5.91
********************************************************************************


整形前SQLトレースより抜粋 (db file parallel readが索引で現れている

WAIT #140513423347200: nam='db file parallel read' ela= 16615 files=1 blocks=13 requests=13 obj#=93726 tim=6258017207

straceより抜粋...io_submit()、だよね〜。:)

io_submit(140513465466880, 13, ...中略... ) = 13


最後に、11g R2 11.2.0.1で同じことを確認(確認するまでもないんだけどね)

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 169 0.58 6.88 2148 5439 0 2509
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 171 0.58 6.88 2148 5439 0 2509

Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 84 (SCOTT)

Rows Row Source Operation
------- ---------------------------------------------------
2509 NESTED LOOPS (cr=5439 pr=2148 pw=0 time=19292592 us)
2509 NESTED LOOPS (cr=2930 pr=1931 pw=0 time=24524478 us cost=5012 size=1530612 card=2501)
2509 TABLE ACCESS BY INDEX ROWID HIGH_CLUSTERING_FACTOR (cr=2683 pr=1922 pw=0 time=24392808 us cost=2510 size=765612 card=2502)
2509 INDEX RANGE SCAN PK_HIGH_CLUSTERING_FACTOR (cr=174 pr=5 pw=0 time=11616 us cost=8 size=0 card=2502)(object id 113222)
2509 INDEX UNIQUE SCAN PK_LOW_CLUSTERING_FACTOR (cr=247 pr=9 pw=0 time=0 us cost=0 size=0 card=1)(object id 113220)
2509 TABLE ACCESS BY INDEX ROWID LOW_CLUSTERING_FACTOR (cr=2509 pr=217 pw=0 time=0 us cost=1 size=306 card=1)


Rows Execution Plan
------- ---------------------------------------------------
0 SELECT STATEMENT MODE: ALL_ROWS
2509 NESTED LOOPS
2509 NESTED LOOPS
2509 TABLE ACCESS MODE: ANALYZED (BY INDEX ROWID) OF 'HIGH_CLUSTERING_FACTOR' (TABLE)
2509 INDEX MODE: ANALYZED (RANGE SCAN) OF 'PK_HIGH_CLUSTERING_FACTOR' (INDEX (UNIQUE))
2509 INDEX MODE: ANALYZED (UNIQUE SCAN) OF 'PK_LOW_CLUSTERING_FACTOR' (INDEX (UNIQUE))
2509 TABLE ACCESS MODE: ANALYZED (BY INDEX ROWID) OF 'LOW_CLUSTERING_FACTOR' (TABLE)


Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 169 0.00 0.00
SQL*Net message from client 169 24.57 25.54
Disk file operations I/O 1 0.00 0.00
db file parallel read 167 0.09 5.66
db file sequential read 357 0.01 0.92
SQL*Net more data to client 167 0.00 0.01
********************************************************************************

11gまでは、実行計画上には現れず実行時に内部的に行っていたI/O最適化の動きが、12cからは実行計画上でも確認できるようになったというのは分かり易くていい。
時間あったら、v$sesstatも載せるかも。 :)

さて、12c 12.1.0.2.0のダウンロードも終わったので、別の楽しみが増えましたよね、みなさん!

ダウンロード! しましたか〜〜〜〜〜っ! :)

みなさんの、12c ネタ祭りを楽しみにしております。 (^^


TABLE ACCESS BY INDEX ROWID BATCHED (Oracle Database 12c R1) ってなに! #1
TABLE ACCESS BY INDEX ROWID BATCHED (Oracle Database 12c R1) ってなに! #2

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

2014年7月25日 (金)

TABLE ACCESS BY INDEX ROWID BATCHED (Oracle Database 12c R1) ってなに! #2

Oracle Database 12c R1 12.1.0.2.0 EEが公開されましたが、12.1.0.1.0で試してあります。

注)バッファキャッシュをクリア後にSQL文を実行してあります。

SELECT
/*+
leading(t2 t1)
use_nl(t2 t1)
index(t2 pk_high_clustering_factor)
*/
t2.id
,t2.name
,t1.name
FROM
low_clustering_factor t1
INNER JOIN high_clustering_factor t2
ON
t1.id = t2.id
WHERE
t2.id BETWEEN 30001 AND 35000

上記のSQL文でTABLE ACCESS BY INDEX ROWID BATCHED操作を行わせてみた。

以下、SQLトレースの結果です。予想通り db file parallel readが発生しています。
高いクラスタリングファクタを持つ索引をアクセス、不連続なROWDをかき集めかき集めたROWIDをある程度まとめて1度のI/Oリクエストでバッファキャッシュへ読み込む動作ですよね!

call     count       cpu    elapsed       disk      query    current        rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.01 0.07 6 6 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 195 0.48 4.92 2288 6338 0 2907
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 197 0.50 4.99 2294 6344 0 2907

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 110 (SCOTT)
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ---------------------------------------------------
2907 2907 2907 NESTED LOOPS (cr=6338 pr=2288 pw=0 time=2150320 us)
2907 2907 2907 NESTED LOOPS (cr=3431 pr=2087 pw=0 time=6036546 us cost=3368 size=1159620 card=3514)
2907 2907 2907 TABLE ACCESS BY INDEX ROWID BATCHED HIGH_CLUSTERING_FACTOR (cr=3107 pr=2082 pw=0 time=5948676 us cost=1012 size=579810 card=3514)
2907 2907 2907 INDEX RANGE SCAN PK_HIGH_CLUSTERING_FACTOR (cr=201 pr=0 pw=0 time=15435 us cost=11 size=0 card=3514)(object id 93727)
2907 2907 2907 INDEX UNIQUE SCAN PK_LOW_CLUSTERING_FACTOR (cr=324 pr=5 pw=0 time=56981 us cost=0 size=0 card=1)(object id 93725)
2907 2907 2907 TABLE ACCESS BY INDEX ROWID LOW_CLUSTERING_FACTOR (cr=2907 pr=201 pw=0 time=312848 us cost=1 size=165 card=1)


Rows Execution Plan
------- ---------------------------------------------------
0 SELECT STATEMENT MODE: ALL_ROWS
2907 NESTED LOOPS
2907 NESTED LOOPS
2907 TABLE ACCESS (BY INDEX ROWID BATCHED) OF 'HIGH_CLUSTERING_FACTOR' (TABLE)
2907 INDEX (RANGE SCAN) OF 'PK_HIGH_CLUSTERING_FACTOR' (INDEX (UNIQUE))
2907 INDEX (UNIQUE SCAN) OF 'PK_LOW_CLUSTERING_FACTOR' (INDEX (UNIQUE))
2907 TABLE ACCESS (BY INDEX ROWID) OF 'LOW_CLUSTERING_FACTOR' (TABLE)


Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 195 0.00 0.00
db file sequential read 209 0.03 0.32
SQL*Net message from client 195 19.95 21.21
db file parallel read 194 0.09 4.33
SQL*Net more data to client 193 0.00 0.01
********************************************************************************

SQLトレース(整形前)のトレースログより : db file parallel read (この時は、最小 3blocks〜15blocksの範囲で行われていた。

WAIT #139657829206792: nam='db file parallel read' ela= 64710 files=1 blocks=12 requests=12 obj#=93726 tim=4037078687

ちなみにstraceでみるとio_submitが呼び出されていて11gの頃と変わりはなかった :)

つまり、実行計画上、db file parallel readやるからね!! 物理I/Oを行うときは! という意思が明確に表示されるようになった。 
分かり易くなっていい!!!!
これだと物理I/Oがあれば、db file parallel readやってるな〜と実行計画を見ただけで想像できますな:)




TABLE ACCESS BY INDEX ROWID BATCHED (Oracle Database 12c R1) ってなに! #1

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

2014年7月23日 (水)

TABLE ACCESS BY INDEX ROWID BATCHED (Oracle Database 12c R1) ってなに! #1

Oracle® Database SQLチューニング・ガイド 12cリリース1(12.1) - ROWIDによる表アクセス: 例にも記載され、昨年試していたときにも現れていた、table access by index rowid batched という操作って、実際のところdb file parallel readをやるよ! と実行計画に表すようになったということだよね! それだけだよね。

ということを確認してみた。(TODOと書いてから1年経過してしまった orz )

詳細はあした以降に書きまする。 :)

20140723_220538

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

2014年5月24日 (土)

シーケンスでパーティションだと〜っ! (Oracle Database 12c R1ではドキュメントに記載なし...だが...) - おまけ

シーケンスでパーティションだと〜っ! (Oracle Database 12c R1ではドキュメントに記載なし...だが...) を書いた後に、もしかして、パーティション表でIdentity columnを使うと勝ってにパーティショニングされたシーケンスが自動生成されたりしないのかな〜っ。

と思って念のために試してみた。


結果は見ての通り....

次のリリースではなにかあるのかもね....。

SCOTT@nonpdb12c> select * from v$version;

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


以下のように、id列をIdentity columnにし、そのid列をパーティショニングキーにしたハッシュパーティション表を作成してみた。

SCOTT@nonpdb12c> r
1 select
2 identity_column
3 ,column_name
4 ,data_type
5 ,data_default
6 from
7 user_tab_columns
8 where
9 table_name = 'HASH_PART_TABLE_USING_ID_COL'
10* order by column_id

IDE COLUMN_NAME DATA_TYPE DATA_DEFAULT
--- ------------------------------ -------------------- ------------------------------
YES ID NUMBER "SCOTT"."ISEQ$$_93596".nextval
NO DATA VARCHAR2

SCOTT@nonpdb12c> r
1 select
2 table_name
3 ,partitioning_type
4 ,partition_count
5 ,partitioning_key_count
6 from
7 user_part_tables
8 where
9* table_name = 'HASH_PART_TABLE_USING_ID_COL'

TABLE_NAME PARTITION PARTITION_COUNT PARTITIONING_KEY_COUNT
------------------------------ --------- --------------- ----------------------
HASH_PART_TABLE_USING_ID_COL HASH 4 1

SCOTT@nonpdb12c> r
1 select
2 name
3 ,object_type
4 ,column_name
5 from
6 user_part_key_columns
7 where
8* name = 'HASH_PART_TABLE_USING_ID_COL'

NAME OBJEC COLUMN_NAME
------------------------------ ----- ------------------------------
HASH_PART_TABLE_USING_ID_COL TABLE ID

対応するシーケンスはどうかというと、PARTITION_COUNTはNULLのまま....ですね。あははは。

SCOTT@nonpdb12c> select * from user_sequences where sequence_name = 'ISEQ$$_93596';

SEQUENCE_NAME MIN_VALUE MAX_VALUE INCREMENT_BY C O CACHE_SIZE LAST_NUMBER PARTITION_COUNT S K
------------------------------ ---------- --------------------------------- ------------ - - ---------- ----------- --------------- - -
ISEQ$$_93596 1 9999999999999999999999999999 1 N N 20 1 N N

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

2014年4月30日 (水)

シーケンスでパーティションだと〜っ! (Oracle Database 12c R1ではドキュメントに記載なし...だが...)

Identity Columnがどのシーケンスを利用しているかを確認するディクショナリビューを調べていて見つけた、シーケンスのパーティション化!
とはいっても現時点ではマニュアルには解説はないので使い方は不明なままですが、RACとかで便利な感じとか、単にパラレル処理でいい感じになるのかとか、いろいろ想像を巡らしております。はい。

SCOTT@nonpdb12c> break on table_name skip 1
SCOTT@nonpdb12c> select table_name,has_identity from user_tables where has_identity='YES';

TABLE_NAME HAS_IDENTITY
------------------------------ ------------
TABLE_FOOBAR_IDENTITY2 YES

TABLE_FOOBAR_IDENTITY YES


SCOTT@nonpdb12c> select * from user_tab_identity_cols;

TABLE_NAME COLUMN_NAM GENERATION IDENTITY_OPTIONS
------------------------------ ---------- ---------- --------------------------------------------------------------------------------------------------------------------------------------------
TABLE_FOOBAR_IDENTITY ID BY DEFAULT START WITH: 1, INCREMENT BY: 1, MAX_VALUE: 9999999999999999999999999999, MIN_VALUE: 1, CYCLE_FLAG: N, CACHE_SIZE: 20, ORDER_FLAG: N

TABLE_FOOBAR_IDENTITY2 ID ALWAYS START WITH: 1, INCREMENT BY: 1, MAX_VALUE: 9999999999999999999999999999, MIN_VALUE: 1, CYCLE_FLAG: N, CACHE_SIZE: 20, ORDER_FLAG: N


SCOTT@nonpdb12c> select table_name,column_name,data_default,identity_column from user_tab_columns where identity_column='YES';

TABLE_NAME COLUMN_NAM DATA_DEFAULT IDENTITY_COLUMN
------------------------------ ---------- -------------------------------------------------------------------------------- ---------------
TABLE_FOOBAR_IDENTITY ID "SCOTT"."ISEQ$$_93570".nextval YES

TABLE_FOOBAR_IDENTITY2 ID "SCOTT"."ISEQ$$_93589".nextval YES


SCOTT@nonpdb12c> select * from user_sequences;

SEQUENCE_NAME MIN_VALUE MAX_VALUE INCREMENT_BY C O CACHE_SIZE LAST_NUMBER PARTITION_COUNT S K
------------------------------ ---------- ---------- ------------ - - ---------- ----------- --------------- - -
ISEQ$$_93570 1 1.0000E+28 1 N N 20 101 N N
ISEQ$$_93589 1 1.0000E+28 1 N N 20 101 N N


ん? PARTITION_COUNTだと? シーケンスでパーティションだと〜〜〜〜〜っ!


Oracle Database 12c R1のマニュアルの構文解説にもまったく記載されていないが..........
Oracle® Database SQL言語リファレンス 12cリリース1 (12.1) CREATE SEQUENCE

SCOTT@nonpdb12c> create sequence p_seq start with 1 maxvalue 9999999 partition 4;

順序が作成されました。

おおおおおおおおおおおおおお〜〜〜できたw Partitioned Sequence!!!!!!

SCOTT@nonpdb12c> select * from user_sequences;

SEQUENCE_NAME MIN_VALUE MAX_VALUE INCREMENT_BY C O CACHE_SIZE LAST_NUMBER PARTITION_COUNT S K
------------------------------ ---------- ---------- ------------ - - ---------- ----------- --------------- - -
ISEQ$$_93570 1 1.0000E+28 1 N N 20 101 N N
ISEQ$$_93589 1 1.0000E+28 1 N N 20 101 N N
P_SEQ 1 9999999 1 N N 20 1 4 N N


RACで効果がありそうな機能だが....、そもそも、どう使うんだ、謎。

次のリリースではなにか使えるのか...現リリースでも裏で使われているのか......

参考
dbi services Blog:Oracle Partitioned Sequences - a future new feature in 12c?

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

2014年4月29日 (火)

Oracle Database 12cで実装されたidentity columnのメモ

Oracle® Database SQL言語リファレンス 12cリリース1 (12.1) CREATE TABLE identity_clause


制限事項に、「CREATE TABLE AS SELECTを使用すると、列に対するIDのプロパティが継承されなくなります。」と記載されているのでかるく確認 :)

SCOTT@nonpdb12c> CREATE TABLE table_foobar_identity2
2 (
3 id NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY
4 ,data VARCHAR2(10)
5 );

表が作成されました。

SCOTT@nonpdb12c> create table table_foobar_identity2_tmp as select * from table_foobar_identity2;

表が作成されました。

SCOTT@nonpdb12c> break on table_name skip 1
SCOTT@nonpdb12c> select table_name,column_name,identity_column from user_tab_columns where table_name like 'TABLE_FOOBAR%' order by table_name,column_id;

TABLE_NAME COLUMN_NAME IDE
------------------------------ ------------------------------ ---
TABLE_FOOBAR_IDENTITY2 ID YES
DATA NO

TABLE_FOOBAR_IDENTITY2_TMP ID NO
DATA NO

CREATE TABLE AS SELECTで復籍してもidentity columnは継承されてない。ふむふむ。


同マニュアルの注意には、「ID列を作成するときには、パフォーマンスを向上するために、デフォルトの20よりも大きな値を使用してCACHE句を指定してください。」
とある.
シーケンスを利用しているので注意するところは一緒ということね。

SCOTT@nonpdb12c> select * from user_sequences;

SEQUENCE_NAME MIN_VALUE MAX_VALUE INCREMENT_BY C O CACHE_SIZE LAST_NUMBER PARTITION_COUNT S K
------------------------------ ---------- ---------- ------------ - - ---------- ----------- --------------- - -
ISEQ$$_93570 1 1.0000E+28 1 N N 20 1 N N

参考
ORACLE-BASE:Identity Columns in Oracle Database 12c Release 1 (12.1)
Inside Oracle – Julian Dyke:Oracle 12c New Feature – Identity Columns

| | コメント (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年12月 9日 (月)

no ocijdbc11 in java.library.path on OS X Mavericks

JPOUG Advent Calendar 2013、9日目のエントリー、かつ、チューニングネタではなく Java on OS X の話という変化球 :) です。

OS X版Oracle SQL DeveloperやOracle JDeveloperで、OCI/Thick JDBCを利用しようとして以下のようなメッセージに遭遇したら...みなさんどうしてるのだろう? 

no ocijdbc11 in java.library.path

と考えだしたら眠れなくなったので、役に立つのか、たたないのかわからないけど書いておきます

私は、Oracle SQL DeveloperやOracle JDeveloperの起動シェルでDYLD_LIBRARY_PATHなどの環境変数をセットすることで対処しています。
(今となってはこれが楽だと思います。 environment.plistでなんとかできた時代もありましたけど...いまは使えないしね)

no ocijdbc11 in java.library.pathとなっている状態から解決するまでの操作をYouTubeで....


映像では、ユーザーのホームディレクトリーにOracle向け環境変数設定ファイル (この例では、oracleenvというファイルを作成してあります) を作成しておき、その設定ファイルをOracle SQL Developer等の起動シェルで読み込ませて問題を解決するまでの操作を行っています。

主演
MacBook Air (mid2013)

ホストOS、その他

  • OS X 10.9 Maveriks
  • Oracle Instant Client 11g 11.2.0.3.0 for OS X (64bit)
  • Terminal 2.4
  • VirtualBox 4.3.4 for OS X
  • Oracle SQL Developer 4.0.0 for OS X
  • Oracle JDeveloper12c 12.1.2.0.0 Studio Edition Generic

ゲストOS、その他

  • Oracle Linux Server 6.4 x86_64
  • Oracle Database 12c EE R1 for Linux x86_64

映像では見づらい方向けの解説。

事前にOracle向け設定ファイルを該当ユーザーのホームディレクトリーに作成しておきます。
この例では、oracleenvとして作成しました。(不過視ファイルとしてもよいかもしれません。)
Oracle_environment_variables


Oracle SQL Developer 4.0 for OS X

「Oracle SQL Developerメニュー」→「Preference...」を選択
002_sdev_004

「データベース」→「拡張」→「OCI/Thickドライバの使用」チェックボックス」をチェック→「テスト」ボタンをクリック
002_sdev_005

no ocijdbc11 in java.library.pathエラーとなる(ライブラリーへのパスが通ってないので当然ですよね)
002_sdev_006

「Finder」→「アプリケーション」→「SQL Developer」→「右クリック」→ポップアップメニューの「パッケージの内容表示」
002_sdev_009

「Contents」→「MacOS」→「sqldeveloper.sh」を選択
002_sdev_010

ポップアップメニュー「このアプリケーションで開く」でお好きなテキストエティタを選択
002_sdev_012

oracle向け環境設定ファイルを読み込ませるように編集。この例ではユーザーホームディレクトリにある oracleenvというファイルを読み込むように変更。
002_sdev_013

Oracle SQL Developer 4.0を再起動しOCI/Thick JDBCドライバーで接続可能か再確認
002_sdev_014

002_sdev_015


Oracle JDeveloper12c 12.1.2.0.0 Studio Edition Generic

「データベース接続編集」ダイアログの「接続のテスト」ボタンをクリックするとno ocijdbc11 in java.library.pathエラー(これもパスが通ってないのが原因なので...)
003_jdev_002

003_jdev_003

「Finder」でOracle JDeveloper12cのインストールディレクトリーからアプリケーション「JDeveloper」を右クリック
→ポップアップメニューの「パッケージの内容を表示」を選択

003_jdev_004

「Contents」→「MacOS」→「JDeveloper」を選択して右クリック→「このアプリケーションを開く」でお好きなテキストエディタを選択
003_jdev_005

oracle向け環境設定ファイルを読み込ませるように編集。この例ではユーザーホームディレクトリにある oracleenvというファイルを読み込むように変更。
003_jdev_006

Oracle JDeveloper12cを再起動し、OCI/Thick JDBCドライバーで接続可能か再確認
003_jdev_007

003_jdev_008


明日は、@dekasasaki さんの担当です。引き続き、JPOUG Advent Calendar 2013をお楽しみください。:)


| | コメント (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)

2013年10月13日 (日)

AWRレポートはOracle Database 12c R1ではFlat Designに変更されたのか? ;p

AWRレポートもフラットデザイン採用? w

以下、Oracle Database 11g R2までのAWRレポート

20131013_70906




Oracle Database 12C R1では、フラットデザイン。 
意図してやっているのだろうか? 
border="1"がborder="0"になってる。CSSは以前のままだが。

20131013_70856

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

2013年9月 6日 (金)

shutdown immeidateしない、ほかの理由に遭遇! は修正されていた! (12c)

数年前に、shutdown immeidateしない、ほかの理由に遭遇!
というエントリを書いていたことをご存知の方も多いと思います。

リリースされたばかりのOracle Database 12c R1 12.1.0.1.0ではどうなったか知りたくないですか? (俺だけかw)

Oracle Database 12c R1 12.1.0.1.0をリスナーも含め起動します。

※ /optの下がu01なのはこちらの事情なので突っ込みなしでお願いします m(_ _)m

[oracle@emperortetra ˜]$ lsnrctl start

LSNRCTL for Linux: Version 12.1.0.1.0 - Production on 06-9月 -2013 13:27:09

Copyright (c) 1991, 2013, Oracle. All rights reserved.

/opt/u01/product/12.1.0/dbhome_1/bin/tnslsnrを起動しています。お待ちください...

TNSLSNR for Linux: Version 12.1.0.1.0 - Production
システム・パラメータ・ファイルは/opt/u01/product/12.1.0/dbhome_1/network/admin/listener.oraです。
ログ・メッセージを/opt/u01/diag/tnslsnr/emperortetra/listener/alert/log.xmlに書き込みました。
リスニングしています: (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1521)))
リスニングしています: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=emperortetra)(PORT=1521)))

(DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1521)))に接続中
リスナーのステータス
------------------------
別名 LISTENER
バージョン TNSLSNR for Linux: Version 12.1.0.1.0 - Production
開始日 06-9月 -2013 13:27:10
稼働時間 0 日 0 時間 0 分 0 秒
トレース・レベル off
セキュリティ ON: Local OS Authentication
SNMP OFF
パラメータ・ファイル /opt/u01/product/12.1.0/dbhome_1/network/admin/listener.ora
ログ・ファイル /opt/u01/diag/tnslsnr/emperortetra/listener/alert/log.xml
リスニング・エンドポイントのサマリー...
(DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1521)))
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=emperortetra)(PORT=1521)))
リスナーはサービスをサポートしていません。
コマンドは正常に終了しました。
[oracle@emperortetra ˜]$ sqlplus / as sysdba

SQL*Plus: Release 12.1.0.1.0 Production on 金 9月 6 13:27:15 2013

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

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

SYS@orcl12c> startup
ORACLEインスタンスが起動しました。

Total System Global Area 534462464 bytes
Fixed Size 2290416 bytes
Variable Size 473959696 bytes
Database Buffers 50331648 bytes
Redo Buffers 7880704 bytes
データベースがマウントされました。
データベースがオープンされました。
SYS@orcl12c> alter pluggable database all open;

プラガブル・データベースが変更されました。

SYS@orcl12c>


別terminalでSQL*Plusを起動しshellに入っておきます。

そして、

今回は特別に!

なんと、もう一度、SQL*Plus経由で、shellに入っておきます。:)

[oracle@emperortetra ˜]$ 
[oracle@emperortetra ˜]$ sqlplus system

SQL*Plus: Release 12.1.0.1.0 Production on 金 9月 6 13:31:13 2013

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

パスワードを入力してください:
最終正常ログイン時間: 金 9月 06 2013 13:30:24 +09:00

Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
に接続されました。
SYSTEM@orcl12c> !
[oracle@emperortetra ˜]$ sqlplus system

SQL*Plus: Release 12.1.0.1.0 Production on 金 9月 6 13:31:22 2013

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

パスワードを入力してください:
最終正常ログイン時間: 金 9月 06 2013 13:31:14 +09:00

Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
に接続されました。
SYSTEM@orcl12c>


前述の状態でpstreeでプロセスツリーを見ると以下のようになっています。

[oracle@emperortetra ˜]$ pstree -ualp oracle
VBoxClient,2099 --draganddrop
├─{VBoxClient},2104
└─{VBoxClient},2105

...中略...

sshd,3854
└─bash,3855
└─sqlplus,3876 \040\040\040\040\040\040
├─bash,3878
│ └─sqlplus,3891 \040\040\040\040\040\040
│ ├─bash,4019
│ └─oracle_3894_orc,3894 (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))
└─oracle_3877_orc,3877 (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))

tnslsnr,3304 LISTENER -inherit
└─{tnslsnr},3305
[oracle@emperortetra ˜]$

確認してみましょう!。11gではshutdown timeoutすら効かず停止できない状態になっていたのですが.....

SYS@orcl12c> shutdown immediate
データベースがクローズされました。
データベースがディスマウントされました。
ORACLEインスタンスがシャットダウンされました。
SYS@orcl12c>

おおおおおおおお〜〜〜、shutdown immediateできた〜〜〜〜! 12cでは修正されたようですね。:)




shutdown immeidateしない、ほかの理由に遭遇!
shutdown immeidateしない、ほかの理由に遭遇! #2
shutdown immeidateしない、ほかの理由に遭遇! #3
shutdown immeidateしない、ほかの理由に遭遇! おまけ
shutdown immeidateしない、ほかの理由に遭遇! おまけのおまけ(でた〜最近、よくあるパターンw)

ablog - shutdown immeidate ...

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

2013年8月21日 (水)

PDB毎に初期化パラメータを変更できるんですよ!(制限はあるけど) #3 - 消えたPDBの初期化パラメータの謎... Truth is out there.

CDB、PDBの各データベースで変更可能な初期化パラメータを変更してもspfileに書き出しているのはCDBのパラメータだけなのです。

spfileのタイムスタンプを確認してもCDBの時だけしかタイムスタンプは更新されません。もちろん心の目で見てもw

同じことで不思議に感じている方々も多いようです
Living with Oracle / oracle 12c database - pluggable database and spfile/parameter - how does that work?

いったい、どこに書き込んでるんでしょう....

PDB個別に設定した初期化パラメータは、spfileに書き込まれていないのは確かです。

どこかしらない、Cloud上に書いてくれちゃってるのでしょうかw 12c だけに... (ありえんw たぶん...

ということは、DBに書くしかないじゃないですか! 


どうやって調べるか....

あ、そうだ、 alter database set system hogehoge = xxxx scope=spfile をPDBでタイプしてるところを、心の目で見ればいいんだ :)

dbms_monitor.session_trace_enable.............awrレポートでも見えるわな、これw なんで気づかんのだ、俺 ><

....


見つけた

SYS@orcl12c> show con_name

CON_NAME
------------------------------
CDB$ROOT
SYS@orcl12c> select table_name from dba_tables where table_name like '%SPFILE%';

TABLE_NAME
------------------------------
PDB_SPFILE$


SYS@orcl12c> conn sys@pdborcl as sysdba
パスワードを入力してください:
接続されました。
SYS@pdborcl> show con_name

CON_NAME
------------------------------
PDBORCL
SYS@pdborcl> select table_name from dba_tables where table_name like '%SPFILE%';

TABLE_NAME
------------------------------
PDB_SPFILE$


SYS@pdborcl> conn sys@pdbdiscus as sysdba
パスワードを入力してください:
接続されました。
SYS@pdbdiscus> show con_name

CON_NAME
------------------------------
PDBDISCUS
SYS@pdbdiscus> select table_name from dba_tables where table_name like '%SPFILE%';

TABLE_NAME
------------------------------
PDB_SPFILE$


PDB_SPFILE$というSYSユーザの表の書き込んでいました!

CDBのPDB_SPFILE$を覗いてみます。

SYS@orcl12c> show con_name

CON_NAME
------------------------------
CDB$ROOT
SYS@orcl12c> l
1 select
2 db_uniq_name
3 ,sid
4 ,pdbs.name as "PDB NAME"
5 ,psf.name as "PARAMETER NAME"
6 ,value$
7 from
8 pdb_spfile$ psf
9 join v$pdbs pdbs
10 on
11 psf.pdb_uid = pdbs.con_uid
12 order by
13 db_uniq_name
14 ,sid
15 ,pdbs.name
16 ,psf.name
17*
SYS@orcl12c> /

DB_UNIQ_NAME SID PDB NAME PARAMETER NAME VALUE$
-------------- -------------- -------------- ------------------------------ --------------------------------------------------
orcl12c * PDBDISCUS open_cursors 500

DB_UNIQ_NAME SID PDB NAME PARAMETER NAME VALUE$
-------------- -------------- -------------- ------------------------------ --------------------------------------------------
orcl12c * PDBORCL open_cursors 200

いました! いましたよ〜〜〜〜。 PDBで設定した初期化パラメータが! (ちなみに、alter system resetコマンドで上記表から削除されます!)


実は、謎は、まだまだ、続くんです。

上記クエリはCDB上で実行しました。 PDB上で設定した初期化パラメータなのだから、PDB側のpdb_spfile$には対象PDBの初期化パラメータが見えるはず...

PDB上のpdb_spfile$を問い合わせてみると.....

SYS@pdborcl> show con_name

CON_NAME
------------------------------
PDBORCL

SYS@pdborcl> select name,value$ from pdb_spfile$;

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


SYS@pdbdiscus> show con_name

CON_NAME
------------------------------
PDBDISCUS

SYS@pdbdiscus> select name,value$ from pdb_spfile$;

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

むむ! むむむむむむ!!!!! 私個人は実に普通というか常識的な想像を働かせてPDB上のpdb_spfile$表を覗いたのに、裏切られた!!!

PDB側で設定した初期化パラメータなのにPDB側のpdb_spfile$表には格納されていなんです。 CDB側のpdb_spfile$しか格納されていません。(実はBugなんてことはないですよね)

俺の初期化パラメータなのに!


部下の手柄は上司の手柄....的なw いや〜〜〜な感じですね。


PDB側のpdb_spfile$表には、いつ初期化パラメータが入るのでしょうか?

それとも、いまの仕様では入ることはない....まだ見ぬ先のリリースでは利用されるのでしょうか....謎は深まる。というか気になって寝れないw 

何か気づいたら。続きはあるかもしれません. 一旦シリーズ終了 :)




PDB毎に初期化パラメータを変更できるんですよ!(制限はあるけど) #1
PDB毎に初期化パラメータを変更できるんですよ!(制限はあるけど) #2 - PDBの初期化パラメータは何処!?

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

2013年8月20日 (火)

PDB毎に初期化パラメータを変更できるんですよ!(制限はあるけど) #2 - PDBの初期化パラメータは何処!?

制限はあるものの、PDBごとに変更可能な初期化パラメータの存在は確認できました。 :)

試してみます!

CDBのOPEN_CURSORSを変更してみます。
他のPDBで変更していないのでCDBの値が継承されるはずです。

$ sqlplus / as sysdba

SQL*Plus: Release 12.1.0.1.0 Production on 月 8月 19 23:12:19 2013

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

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

SYS@orcl12c> startup
ORACLEインスタンスが起動しました。

Total System Global Area 534462464 bytes
Fixed Size 2290416 bytes
Variable Size 473959696 bytes
Database Buffers 50331648 bytes
Redo Buffers 7880704 bytes
データベースがマウントされました。
データベースがオープンされました。
SYS@orcl12c> alter pluggable database all open;

プラガブル・データベースが変更されました。

SYS@orcl12c>
SYS@orcl12c> show parameter open_cursors

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
open_cursors integer 300
SYS@orcl12c>
SYS@orcl12c> alter system set open_cursors=400 scope=both;

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

SYS@orcl12c> show parameter open_cursors

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
open_cursors integer 400
SYS@orcl12c>


PDBの初期化パラメータ値はCDBの初期化パラメータ値を継承しています!

SYS@orcl12c> conn sys@pdborcl as sysdba
パスワードを入力してください:
接続されました。
SYS@pdborcl>
SYS@pdborcl> show parameter open_cursors

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
open_cursors integer 400


PDBの初期化パラメータを変更してみます。(MEMORYとSPFILEを変更)

SYS@pdborcl> alter system set open_cursors=200 scope=both;

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

SYS@pdborcl> show parameter open_cursors

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
open_cursors integer 200

変更できますね :)


ついでなので、もひとつのPDBの初期化パラメータも他の値に変更してみます。(同じくscope=bothで)

変更前なのでOPEN_CURSORSパラメータはCDBの同パラメータを継承しています!

SYS@pdborcl> conn sys@pdbdiscus as sysdba
パスワードを入力してください:
接続されました。
SYS@pdbdiscus>
SYS@pdbdiscus> show parameter open_cursors

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
open_cursors integer 400

400から500に増やてみます。

SYS@pdbdiscus> alter system set open_cursors=500 scope=both;

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

SYS@pdbdiscus> show parameter open_cursors

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
open_cursors integer 500

問題なく変更できました。:)  順調、順調


SQL*Plusのshow parameter同様に、v$parameterではCDB,PDB毎のパラメータのみ参照できるようですね。ふむふむ。

SYS@orcl12c> select name,value from v$parameter where name='open_cursors';

NAME VALUE
------------------------------ ------------------------------
open_cursors 400

SYS@orcl12c> conn sys@pdborcl as sysdba
パスワードを入力してください:
接続されました。
SYS@pdborcl> /

NAME VALUE
------------------------------ ------------------------------
open_cursors 200

SYS@pdborcl> conn sys@pdbdiscus as sysdba
パスワードを入力してください:
接続されました。
SYS@pdbdiscus> /

NAME VALUE
------------------------------ ------------------------------
open_cursors 500

ついでなので、もう少し検証してみましょう。

初期化パラメータを変更する際、scope=bothとしたのでSPFILEにも格納されているはずですよね。

マルチテナント化されてもSPFILEは一つ!  確認しておきましょう。

SYS@orcl12c> !find $ORACLE_BASE -name spfile*.ora
/opt/u01/product/12.1.0/dbhome_1/dbs/spfileorcl12c.ora

一つだけです!


中身がどうなっているか確認しておきましょう。

SYS@orcl12c> !strings $ORACLE_HOME/dbs/spfileorcl12c.ora
orcl12c.__data_transfer_cache_size=0
orcl12c.__db_cache_size=33554432
orcl12c.__java_pool_size=16777216
orcl12c.__large_pool_size=50331648
orcl12c.__oracle_base='/opt/u01'#ORACLE_BASE set from environment
orcl12c.__pga_aggregate_target=570425344
orcl12c.__sga_target=1090519040
orcl12c.__shared_io_pool_size=0
orcl12c.__shared_pool_size=213909504
orcl12c.__streams_pool_size=0
*.audit_file_dest='/opt/u01/admin/orcl12c/adump'
*.audit_trail='db'
*.compatible='12.1.0.0.0'
*.control_files='
/opt/u01/oradata/orcl12c/control01.ctl','/opt/u01/fast_recovery_area/orcl12c/control02.ctl'
*.db_block_size=8192
*.db_domain=''
*.db_name='orcl12c'
*.db_recovery_file_dest='/opt/u01/fast_recovery_area'
*.db_recovery_file_dest_size=4800m
*.diagnostic_dest='/opt/u01'
*.dispatchers='(PROTOCOL=TCP) (SERVICE=orcl12cXDB)'
*.enable_pluggable_database=true
*.memory_max_target=0
*.memory_target=0
*.open_cursors=400
*.pga_aggregate_target=536870912
*.processes=300
*.remote_login_passwordfile='
EXCLUSIVE'
*.sga_max_size=536870912
*.undo_tablespace='UNDOTBS1'

あれれれれれれ〜〜、 なんで CDBのパラメータしかないんでしょう!!!!!!! 

scope=bothと指定してもエラーのでずに設定されてる。 

SPFILEのバイナリ部分だけに記録さされているのか?。イヤそんなことはないだろ!

scope=memoryと同じではないことを確認するために一旦、再起動!! 

SYS@orcl12c> alter pluggable database all close;

プラガブル・データベースが変更されました。

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

Total System Global Area 534462464 bytes
Fixed Size 2290416 bytes
Variable Size 473959696 bytes
Database Buffers 50331648 bytes
Redo Buffers 7880704 bytes
データベースがマウントされました。
データベースがオープンされました。
SYS@orcl12c>
SYS@orcl12c> alter pluggable database all open;

プラガブル・データベースが変更されました。

SYS@orcl12c>
SYS@orcl12c> show parameter open_cursors

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
open_cursors integer 400
SYS@orcl12c>
SYS@orcl12c> conn sys@pdborcl as sysdba
パスワードを入力してください:
接続されました。
SYS@pdborcl> show parameter open_cursors

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
open_cursors integer 200
SYS@pdborcl>
SYS@pdborcl> conn sys@pdbdiscus as sysdba
パスワードを入力してください:
接続されました。
SYS@pdbdiscus> show parameter open_cursors

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
open_cursors integer 500


むむ!  むむむ!!!!!  SPFILEには格納されていない..ようなのに......

PDBの初期化パラメータは、何処にあるんだ〜〜〜〜!。 

次回へつづく!

次回、心の目を研ぎすませば、見えてくるものがある....みえないものもある...かもしれない

...乞うご期待w




PDB毎に初期化パラメータを変更できるんですよ!(制限はあるけど) #1

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

2013年8月18日 (日)

PDB毎に初期化パラメータを変更できるんですよ!(制限はあるけど) #1

11g R2と12c R1の初期化パラメータ(隠しパラメータを含む)の差分をチェックしようとして気づいたのですが....

いままでとちがうんですよ。 シングルインスタンスなのに、なぜ、同じパラメータが4つあるんだ?

SYS@orcl12c> l
1 select
2 count(ksppinm)
3 from
4 x$ksppi
5 where
6* ksppinm='open_cursors'
SYS@orcl12c> /

COUNT(KSPPINM)
--------------
4
SYS@orcl12c> l
1 select
2 count(distinct ksppinm)
3 from
4 x$ksppi
5 where
6* ksppinm='open_cursors'
SYS@orcl12c> /

COUNT(DISTINCTKSPPINM)
----------------------
1

実は、CDB (Container Database)が1つ、PDB SEED (Pluggable Database Seed)が1つ、PDB (Pluggable Database)が2つあるんです.....1インスタンスに

SYS@orcl12c> l
1 select
2 inst_id
3 ,cons.name
4 ,ksppinm
5 from
6 x$ksppi params
7 join v$containers cons
8 on
9 params.con_id = cons.con_id
10 where
11* ksppinm='open_cursors'
SYS@orcl12c> /

INST_ID NAME KSPPINM
---------- ------------------------------ ----------------------------------------
1 CDB$ROOT open_cursors
1 PDB$SEED open_cursors
1 PDBORCL open_cursors
1 PDBDISCUS open_cursors

初期化パラメータはCDBだけでなく、PDB毎に設定できるようになっているようです!


ただし、よくよく調べてみると、PDBで変更可能な初期化パラメータは制限されているんです。

今後のためにPDBで変更可能な初期化パラメータ一覧(隠しパラメータ含む)をHTML形式でスプールしておきました。
Oracle Database 12c r1 12.1.0.1.0 - Pluggable Database Modifiable Parameters (including hidden parameters)

何かのときに役にたつかも... :)

...え、どうやって隠しパラメータの分もリストしたのかって?、 PDBで変更できる初期化パラメータはv$parameterのISPDB_MODIFIABLE列を見ればわかるのですが、隠しパラメータの分まではでてないですものね〜、

v$parameterを心の目で見ればいいんですよ。(謎


次回は、PDBで設定できる初期化パラメータを変更していて気づいたことを書く予定 :)

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

2013年8月14日 (水)

DBCAでPluggable Databaseを追加作成してみた


Pluggable Database毎に、システム、AUX、一時、ユーザの表領域を持ち、制御ファイル、REDOログ、UNDOはContainer Database配下で共有管理されています。

/opt/u01 なのはこちらの都合なので気にしないようにw

$ ls -lR $ORACLE_BASE/oradata
/opt/u01/oradata:
合計 4
drwxr-x---. 5 oracle oinstall 4096 8月 9 00:22 2013 orcl12c

/opt/u01/oradata/orcl12c:
合計 2185944
-rw-r-----. 1 oracle oinstall 17973248 8月 9 00:46 2013 control01.ctl
drwxr-x---. 2 oracle oinstall 4096 8月 9 00:22 2013 pdbdiscus
drwxr-x---. 2 oracle oinstall 4096 6月 29 10:56 2013 pdborcl
drwxr-x---. 2 oracle oinstall 4096 6月 29 10:48 2013 pdbseed
-rw-r-----. 1 oracle oinstall 52429312 8月 9 00:46 2013 redo01.log
-rw-r-----. 1 oracle oinstall 52429312 8月 9 00:16 2013 redo02.log
-rw-r-----. 1 oracle oinstall 52429312 8月 9 00:16 2013 redo03.log
-rw-r-----. 1 oracle oinstall 859840512 8月 9 00:46 2013 sysaux01.dbf
-rw-r-----. 1 oracle oinstall 828383232 8月 9 00:46 2013 system01.dbf
-rw-r-----. 1 oracle oinstall 92282880 8月 9 00:45 2013 temp01.dbf
-rw-r-----. 1 oracle oinstall 367009792 8月 9 00:46 2013 undotbs01.dbf
-rw-r-----. 1 oracle oinstall 5251072 8月 9 00:46 2013 users01.dbf

/opt/u01/oradata/orcl12c/pdbdiscus:
合計 957528
-rw-r-----. 1 oracle oinstall 5251072 8月 9 00:45 2013 pdbdiscus_users01.dbf
-rw-r-----. 1 oracle oinstall 702554112 8月 9 00:45 2013 sysaux01.dbf
-rw-r-----. 1 oracle oinstall 272637952 8月 9 00:45 2013 system01.dbf
-rw-r-----. 1 oracle oinstall 20979712 8月 9 00:22 2013 temp01.dbf

/opt/u01/oradata/orcl12c/pdborcl:
合計 7135544
-rw-r-----. 1 oracle oinstall 4618985472 8月 9 00:45 2013 SAMPLE_SCHEMA_users01.dbf
-rw-r-----. 1 oracle oinstall 375529472 8月 9 00:45 2013 example01.dbf
-rw-r-----. 1 oracle oinstall 1323311104 8月 3 14:48 2013 pdborcl_temp01.dbf
-rw-r-----. 1 oracle oinstall 734011392 8月 9 00:45 2013 sysaux01.dbf
-rw-r-----. 1 oracle oinstall 293609472 8月 9 00:45 2013 system01.dbf

/opt/u01/oradata/orcl12c/pdbseed:
合計 948084
-rw-r-----. 1 oracle oinstall 91234304 6月 29 10:52 2013 pdbseed_temp01.dbf
-rw-r-----. 1 oracle oinstall 671096832 6月 29 10:55 2013 sysaux01.dbf
-rw-r-----. 1 oracle oinstall 272637952 6月 29 10:55 2013 system01.dbf

参考:
orcl12c : CDB
pdbdiscus : PDB (DBCAで追加作成したPDB)
pdborcl : PDB
pdbseed : PDB Seed

次はなにを調べましょうか ...そうだあれにしよう...

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

2013年8月13日 (火)

Cross Platform Transportable Tablespace #12

ネタとしては地味ですがOracle Database 12cのTransportalbe tablespaceも軽めにチェック

以前のエントリ..2009年か〜〜遠い目
Cross Platform Transportable Tablespace #11


あれ、ちょいとズレてるけどご愛嬌:)

06:59:36 SYS@orcl12c> select * from v$version;

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

プラットフォームの情報も変化はない。Mac OSの文字もそのまま..

06:52:31 SYS@pdborcl> select * from v$transportable_platform;

PLATFORM_ID PLATFORM_NAME ENDIAN_FORMAT CON_ID
----------- ----------------------------------------------------------------------------------------------------- -------------- ----------
1 Solaris[tm] OE (32-bit) Big 0
2 Solaris[tm] OE (64-bit) Big 0
7 Microsoft Windows IA (32-bit) Little 0
10 Linux IA (32-bit) Little 0
6 AIX-Based Systems (64-bit) Big 0
3 HP-UX (64-bit) Big 0
5 HP Tru64 UNIX Little 0
4 HP-UX IA (64-bit) Big 0
11 Linux IA (64-bit) Little 0
15 HP Open VMS Little 0
8 Microsoft Windows IA (64-bit) Little 0
9 IBM zSeries Based Linux Big 0
13 Linux x86 64-bit Little 0
16 Apple Mac OS Big 0
12 Microsoft Windows x86 64-bit Little 0
17 Solaris Operating System (x86) Little 0
18 IBM Power Based Linux Big 0
19 HP IA Open VMS Little 0
20 Solaris Operating System (x86-64) Little 0
21 Apple Mac OS (x86-64) Little 0

20行が選択されました。


con_idはお約束で追加されていますが、ビューは大きく変わってないようですね。

12cで試している方のエントリを見つけたのでメモ:
Oracle 12c: Transport tablespaces across platforms




Cross Platform Transportable Tablespace #11

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

2013年8月 8日 (木)

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

※2014/8/4 修正、追記
比較したバージョンが誤っていたため訂正しました。正しくは、11g R1 11.1.0.6.0でした。


型の差分までは取得しませんでしが、Oracle11g R2 (11.2.0.1.0)とOracle12c R1 (12.1.0.1.0)の初期化パラメータ(隠しパラメータ含む)の差分をHTML化しました。(クエリ結果をHTML形式でspoolしただけですが)

まだどのような差分があるのか見切れていませんが、じ〜〜〜っくりと見ようと思っています :)

参考 (パラメータ数)
11g R2 11.2.0.1.0
11g R1 11.1.0.6.0
パラメータ総数 : 2049
隠しパラメータ数 : 1755 (うち ダブルアンダースコア隠しパラメータ数 : 10 )

11g R1 11.2.0.1.0
パラメータ総数 : 2399
隠しパラメータ数 : 2057 (うち ダブルアンダースコア隠しパラメータ数 : 10 )

12c R1 12.1.0.1.0
パラメータ総数 : 3351
隠しパラメータ数 : 2984 (うち ダブルアンダースコア隠しパラメータ数 : 11 )

隠しパラメータの増加が目立ちます.... (@@)

Difference of Initialization Parameters between 11g r1 (11.1.0.6.0) and 12c r1 (12.1.0.1.0)

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

2013年7月25日 (木)

Oracle Database 12c New Feature : Invisible Columnsの怪w s/怪w/謎/

Oracle® Database New Features Guide 12c Release 1 (12.1) - 1.5.5.3 Invisible Columns
Oracle® Database Administrator's Guide 12c Release 1 (12.1) - Understand Invisible Columns


予告通り Invisible Columnの小ネタを。
(祭りに呼び出されて書けないかかもしれない、という状況にはならずw この時間に自宅にいるのはラッキーw)

本題とは関係ないですが、改行されないのはご愛嬌:)

SYS@orcl12c> startup pluggable database pdborcl;
ラガブル・データベースがオープンされました。SYS@orcl12c>
SYS@orcl12c>
SYS@orcl12c> conn scott@pdborcl
パスワードを入力してください:
接続されました。
SCOTT@pdborcl>

Invisible columnを含む表を作成します。(問題なく作成されました。当たり前か..)

SCOTT@pdborcl> create table hoge (a number, b number, c number invisible);

表が作成されました。


SQL*Plusのdescコマンドで見てみます。マニュアルの通り、Invisible columnはリストされません。

SCOTT@pdborcl> desc hoge
名前 NULL? 型
----------------------------------------- -------- ----------------------------
A NUMBER
B NUMBER


さあ、ここから、気持ち悪い事が起きますよ〜〜。よ〜〜〜く見ててくださいね〜〜。

列は隠れていますが、存在を知って、Invisible Columnでもカラムを指定すればデータを登録できるんです。見えてないだけなんです!

SCOTT@pdborcl> insert into hoge(a,b,c) values(1,2,4);

1行が作成されました。


カラム指定しないとa列と、b列しかないものとして扱われ、見慣れたエラー、「ORA-00913: 値の個数が多すぎます。」となります。

いい感じの気持ち悪さでしょ :)

SCOTT@pdborcl> insert into hoge values(11,12,14);
insert into hoge values(11,12,14)
*
行1でエラーが発生しました。:
ORA-00913: 値の個数が多すぎます。

2列分なら正常に登録できます。見えるのはa列とb列の2列なので当然と言えば当然。

SCOTT@pdborcl> insert into hoge values(11,12);

1行が作成されました。

SELECTリストに * を指定すれば、ほらほら、自然です。 a列とb列だけがリストされています。

SCOTT@pdborcl> select * from hoge;

A B
---------- ----------
1 2
11 12


でも...c列の存在を知っている人には....見えちゃうんです。

SCOTT@pdborcl> select a, b, c from hoge;

A B C
---------- ---------- ----------
1 2 4
11 12 [null]

同様に削除や更新もできちゃいます。見えないものが見えてる人にはw。
(その存在を知らない人には見えないわですが...)

SCOTT@pdborcl> update hoge set c = 14 where c is null;

1行が更新されました。

SCOTT@pdborcl> select a, b, c from hoge where c = 14;

A B C
---------- ---------- ----------
11 12 14

SCOTT@pdborcl> delete from hoge where c = 14;

1行が削除されました。

SCOTT@pdborcl> select a, b, c from hoge;

A B C
---------- ---------- ----------
1 2 4


ORDER BY句でも、その存在さえ知っていればいろいろイタズラできますね。

SCOTT@pdborcl> select a,b,c from hoge order by c desc;

A B C
---------- ---------- ----------
11 12 14
1 2 4


おもしろいですね。

SCOTT@pdborcl> select * from hoge order by c desc;

A B
---------- ----------
11 12
1 2

Invisible columnには索引も作れます!

SCOTT@pdborcl> create index hoge_ix on hoge(c);

索引が作成されました。

SCOTT@pdborcl> set autot trace exp
SCOTT@pdborcl> select * from hoge where c = 14;

実行計画
----------------------------------------------------------
Plan hash value: 3349209795

-----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 39 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID BATCHED| HOGE | 1 | 39 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | HOGE_IX | 1 | | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - access("C"=14)

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

SCOTT@pdborcl>

次のようなイタズラもできます! うひゃw うひゃw 

相手の腕試をしするにはぴったりなイタズラです(嘘

SCOTT@pdborcl> alter table hoge modify (c number not null);

表が変更されました。

SCOTT@pdborcl>
SCOTT@pdborcl> insert into hoge(a, b) values(100,111);
insert into hoge(a, b) values(100,111)
*
行1でエラーが発生しました。:
ORA-01400: ("SCOTT"."HOGE"."C")にはNULLは挿入できません。


イタズラはこれくらいにして、Invisible Columnをディクショナリビューから覗いてみましょう。
Invisible Indexもディクショナリビューからいろいろと情報を得ることができましたよね! 
(多分、同じように見れるのでは...と思っていたが...

desc[ribe]コマンドではInvisible Columnは見えませんが、 ALL/DBA/USER_TAB_COLUMNSからは見る事ができます。

racle® Database Reference 12c Release 1 (12.1) - ALL_TAB_COLUMNS


ただし、見る事はできるのですが、その列がInvisible Columnかどうかを確認する列がないんですよ。(ぱっと見)

例えば、Invisible IndexだとALL/DBA/USER_INDEXES確認できます

SCOTT@pdborcl> select index_name,visibility from user_indexes where table_name='HOGE';

INDEX_NAME VISIBILIT
------------------------------ ---------
HOGE_IX INVISIBLE
HOGE_PK VISIBLE


そこで疑問!
SQL*PLusのdesc[ribe]コマンドはどのような情報を基にVisible Columeだけを表示してるんでしょうねぇ〜。

これ、探すのにてこずりましたよ!

以下のマニュアルにも記載されていますが、Visible/InvisibleにするとColumn Orderが変化することにも関連しているようです。
Oracle® Database Administrator's Guide 12c Release 1 (12.1) - Understand Invisible Columns

desc[ribe]ではInvisible Columnは見えません

SCOTT@pdborcl> desc hoge
名前 NULL? 型
----------------------------------------- -------- ----------------------------
A NUMBER
B NUMBER


どのような情報を見てInvisibleであると判断しているのか....

SCOTT@pdborcl> select column_name,data_type,nullable,column_id from user_tab_columns where table_name='HOGE' order by column_id;

COLUMN_NAME DATA_TYPE N COLUMN_ID
------------------------------ ---------- - ----------
A NUMBER Y 1
B NUMBER Y 2
C NUMBER N [null]


COLUMN_IDがNULLである列がInvisible Columns !!!!

SCOTT@pdborcl> l
1 select
2 column_name
3 ,data_type
4 ,nullable
5 ,column_id
6 from
7 user_tab_columns
8 where
9 table_name='HOGE'
10 and column_id is not null
11 order by
12* column_id
SCOTT@pdborcl> /

COLUMN_NAME DATA_TYPE N COLUMN_ID
------------------------------ ---------- - ----------
A NUMBER Y 1
B NUMBER Y 2

いずれ、ALL/DBA/USER_TAB_COLUMNSに、VISIBILITYという列が追加されるんじゃないかと想像してます :)

それまでは俺俺 USER_TAB_COLUMNSビューでも作っておくと便利かも...しれない。

SCOTT@pdborcl> create view my_tab_columns as
2 select
3 user_tab_columns.*
4 ,case when user_tab_columns.column_id is null
5 then 'INVISIBLE' else 'VISIBLE' end as VISIBILITY
6 from
7 user_tab_columns
8 ;

ビューが作成されました。
SCOTT@pdborcl> select column_name,data_type,nullable,visibility from my_tab_columns where table_name='HOGE' order by column_id;

COLUMN_NAME DATA_TYPE N VISIBILIT
------------------------------ ---------- - ---------
A NUMBER Y VISIBLE
B NUMBER Y VISIBLE
C NUMBER N INVISIBLE


このような特性を理解した上で、どのような場面で使うと便利なのか、じ〜〜〜〜っくり考えてみたいと...と思いつつ...寝ます。パタリ。 1:48am


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

2013年7月13日 (土)

Oracle Database 12c R1 : コンテナデータベースとプラガブルデータベースを歩きやすくしてみる

世界を見渡せば、かなりの方がOracle Database 12cのインストール手順を公開し始めているのでインストール後の話を書いておきますね。

インストール時にPluggable Databaseも同時に作成してもtnsnames.oraにはContainer Databaseへの接続定義しか無かったんです。(私のインストール手順に問題がなければ..なんですが)
無くてもEasy connectを使えば接続できるので問題はないんですが...

ただ、Easy connectで毎回タイプするのも面倒(少々長いし)なので、tnsnames.oraにPluggable Database接続用定義を作成しておきましょう。

定義内容はいままでと変わらず。 SERVICE_NAMEの箇所を接続先のPluggable Database名にするだけ。
(Pluggable Database名と書いたが、マニュアル読みきれてないので表現は間違っているかもしれません。間違っていたら後で修正します)

[oracle@emperortetra]$ cat $ORACLE_HOME/network/admin/tnsnames.ora
# tnsnames.ora Network Configuration File: /opt/u01/product/12.1.0/dbhome_1/network/admin/tnsnames.ora
# Generated by Oracle configuration tools.

# for Container Database : orcl12c
ORCL12C =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = emperortetra)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = orcl12c)
)
)

# for Pluggable Database : pdborcl
PDBORCL =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = emperortetra)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = pdborcl)
)
)

本題である、歩きやすくするための設定がこれ。

複数のPluggable DatabaseとContainer Database間を旅することも多くなりそうですから、今、自分はどこにいるのか把握しやすくしておいたほうが吉かと。

12c以前から定番で設定している内容ではあるのですが。赤字部分がポイント

目立たないけど、地味に大切なのが、 set tab off だと思っているのは私だけだろうか!w 
(ここのところ、set tab offじゃない人のコピペしてきた、位置ズレまくりの実行計画見せられててイライラしている影響もある :)


それ以外の設定も、設定してるだけで、「むむむ、この方できるかも!」 と、
思わせる(思わせるだけですからね!w つかみはOK的な感じなので、あとはあなた次第)設定内容なので大切と言えば大切。
(login.sqlでもOK)

[oracle@emperortetra]$ cat $ORACLE_HOME/sqlplus/admin/glogin.sql
--
-- Copyright (c) 1988, 2005, Oracle. All Rights Reserved.
--
-- NAME
-- glogin.sql
--
-- DESCRIPTION
-- SQL*Plus global login "site profile" file
--
-- Add any SQL*Plus commands here that are to be executed when a
-- user starts SQL*Plus, or uses the SQL*Plus CONNECT command.
--
-- USAGE
-- This script is automatically run
--
set linesize 180
set pagesize 10000
set timi on
set time on
define _EDITOR=vi
col table_name for a30
col column_name for a30
col segment_name for a30
col tablespace_name for a30
col index_name for a30
col partition_name for a30
col sub_partition_name for a30
set sqlp "_USER'@'_CONNECT_IDENTIFIER> "
set tab off
[oracle@emperortetra]$


リスナーを起動してステータスを見てみましょう (u01が/optの下にあるのは内緒w じゃないw
まだ、データベースを起動していないのでこんな感じです。

[oracle@emperortetra]$ lsnrctl status

LSNRCTL for Linux: Version 12.1.0.1.0 - Production on 06-7月 -2013 09:10:04

Copyright (c) 1991, 2013, Oracle. All rights reserved.

(DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1521)))に接続中
リスナーのステータス
------------------------
別名 LISTENER
バージョン TNSLSNR for Linux: Version 12.1.0.1.0 - Production
開始日 06-7月 -2013 09:06:38
稼働時間 0 日 0 時間 3 分 26 秒
トレース・レベル off
セキュリティ ON: Local OS Authentication
SNMP OFF
パラメータ・ファイル /opt/u01/product/12.1.0/dbhome_1/network/admin/listener.ora
ログ・ファイル /opt/u01/diag/tnslsnr/emperortetra/listener/alert/log.xml
リスニング・エンドポイントのサマリー...
(DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1521)))
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=emperortetra)(PORT=1521)))
リスナーはサービスをサポートしていません。
コマンドは正常に終了しました。
[oracle@emperortetra]$


Container Databaseの起動(12cより前のOracle Databaseと同じですね)

Container Databaseである orcl12c がSQL*Plusのプロンプトに表示されていますよね!! :)

[oracle@emperortetra]$ sqlplus / as sysdba

SQL*Plus: Release 12.1.0.1.0 Production on 土 7月 6 09:25:22 2013

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

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

09:25:22 SYS@orcl12c> startup
ORACLEインスタンスが起動しました。

Total System Global Area 1653518336 bytes
Fixed Size 2289016 bytes
Variable Size 1040188040 bytes
Database Buffers 603979776 bytes
Redo Buffers 7061504 bytes
データベースがマウントされました。
データベースがオープンされました。
09:25:32 SYS@orcl12c>



Pluggable Databaseを起動します!

09:25:34 SYS@orcl12c> alter pluggable database pdborcl open;

プラガブル・データベースが変更されました。

経過: 00:00:00.86


Pluggable DatabaseのSYS、SYSTEMおよび、SCOTTユーザに接続してみます!
09:25:53 SYSTEM@orcl12c> conn sys@pdborcl as sysdba
パスワードを入力してください:
接続されました。
09:26:06 SYS@pdborcl>
09:26:07 SYS@pdborcl>
09:26:07 SYS@pdborcl> conn system@pdborcl
パスワードを入力してください:
接続されました。
09:26:34 SYSTEM@pdborcl>
09:26:34 SYSTEM@pdborcl>
09:26:35 SYSTEM@pdborcl> conn scott@pdborcl
パスワードを入力してください:
接続されました。
09:26:50 SCOTT@pdborcl>
09:26:51 SCOTT@pdborcl>
09:26:51 SCOTT@pdborcl>


SQL*Plusのプロンプトに接続先の情報を表示しておくと便利ですよね。Database間を歩きやすく、迷子になりにくくなりますよ! :)

おまけ
Container Databaseおよび、Pluggable Database起動後のlistenerのステータスは以下の通り。

[oracle@emperortetra]$ lsnrctl status

LSNRCTL for Linux: Version 12.1.0.1.0 - Production on 06-7月 -2013 09:28:09

Copyright (c) 1991, 2013, Oracle. All rights reserved.

(DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1521)))に接続中
リスナーのステータス
------------------------
別名 LISTENER
バージョン TNSLSNR for Linux: Version 12.1.0.1.0 - Production
開始日 06-7月 -2013 09:06:38
稼働時間 0 日 0 時間 21 分 31 秒
トレース・レベル off
セキュリティ ON: Local OS Authentication
SNMP OFF
パラメータ・ファイル /opt/u01/product/12.1.0/dbhome_1/network/admin/listener.ora
ログ・ファイル /opt/u01/diag/tnslsnr/emperortetra/listener/alert/log.xml
リスニング・エンドポイントのサマリー...
(DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1521)))
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=emperortetra)(PORT=1521)))
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=emperortetra)(PORT=5500))(Security=(my_wallet_directory=/opt/u01/admin/orcl12c/xdb_wallet))(Presentation=HTTP)(Session=RAW))
サービスのサマリー...
サービス"orcl12c"には、1件のインスタンスがあります。
インスタンス"orcl12c"、状態READYには、このサービスに対する1件のハンドラがあります...
サービス"orcl12cXDB"には、1件のインスタンスがあります。
インスタンス"orcl12c"、状態READYには、このサービスに対する1件のハンドラがあります...
サービス"pdborcl"には、1件のインスタンスがあります。
インスタンス"orcl12c"、状態READYには、このサービスに対する1件のハンドラがあります...
コマンドは正常に終了しました。
[oracle@emperortetra]$

Enjoy Oracle Database 12c R1 :)


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

2013年7月 8日 (月)

rownum使って満足しちゃってると.....おまけのおまけ FETCH FIRST N ROWS ONLY編

20130628_233812


Oracle Database 12c R1 12.1.0.1.0 がリリースされたので、自分用のメモとしても使うネタから :)


実行環境は Oracle Database 12c R1 12.1.0.1.0 EE/Oracle Linux 6.4/VirtualBox for OS X 11g R2と同じデータをインポートし統計情報を再取得しています。


まず、rownum から!

おおおおお〜、 まあ想定通りではあるのですが、11gとは違う点が一つ。

TABLE ACCESS BY INDEX ROWID BATCHEDと見慣れないオペレーションが...興味深いですね。これ :)

別途調べるTODO :)

23:14:41 SCOTT@pdborcl> r
1 select /*+ leading(tc) use_nl(tc tb ta) */ *
2 from
3 tc join tb
4 on
5 tc.version = tb.version
6 and tc.branch# = tb.branch#
7 join ta
8 on
9 tb.version = ta.version
10 where
11 tc.version between 1 and 10
12* and rownum <= 1000

1000行が選択されました。

経過: 00:00:00.13

実行計画
----------------------------------------------------------
Plan hash value: 1463769645

-------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1000 | 2952K| 4813 (1)| 00:00:01 |
|* 1 | COUNT STOPKEY | | | | | |
| 2 | NESTED LOOPS | | | | | |
| 3 | NESTED LOOPS | | 2002 | 5910K| 4813 (1)| 00:00:01 |
| 4 | NESTED LOOPS | | 4004 | 7894K| 2810 (1)| 00:00:01 |
| 5 | TABLE ACCESS BY INDEX ROWID BATCHED| TC | 4004 | 3953K| 585 (0)| 00:00:01 |
|* 6 | INDEX RANGE SCAN | PK_TC | | | 14 (0)| 00:00:01 |
| 7 | TABLE ACCESS BY INDEX ROWID | TB | 1 | 1008 | 1 (0)| 00:00:01 |
|* 8 | INDEX UNIQUE SCAN | PK_TB | 1 | | 0 (0)| 00:00:01 |
|* 9 | INDEX UNIQUE SCAN | PK_TA | 1 | | 0 (0)| 00:00:01 |
| 10 | TABLE ACCESS BY INDEX ROWID | TA | 1 | 1004 | 1 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - filter(ROWNUM<=1000)
6 - access("TC"."VERSION">=1 AND "TC"."VERSION"<=10)
8 - access("TC"."VERSION"="TB"."VERSION" AND "TC"."BRANCH#"="TB"."BRANCH#")
filter("TB"."VERSION"<=10 AND "TB"."VERSION">=1)
9 - access("TB"."VERSION"="TA"."VERSION")
filter("TA"."VERSION">=1 AND "TA"."VERSION"<=10)


統計
----------------------------------------------------------
0 recursive calls
0 db block gets
2418 consistent gets
0 physical reads
0 redo size
1059870 bytes sent via SQL*Net to client
1270 bytes received via SQL*Net from client
68 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1000 rows processed


次に、Oracle Database 12c R1 12.1.0.1.0 から実装された FETCH FIRST N ROWS ONLYとの比較

FETCH FIRST N ROWS ONLYを利用した場合TCを全表走査してしまったので、rownum利用時と同じオブジェクト参照させるためヒントでPK_TC索引を利用するようチューニングしてあります
ただ..なぜか、TABLE ACCESS BY INDEX ROWID BATCHEDではなくTABLE ACCESS BY INDEX ROWIDとなっています。


さらに不思議なことに、COSTが異常に跳ね上がっています。Rowsの見積もり件数で大きな差があることが影響しているように見えるんだが、なんでこんなに違うんだろう!
いろいろ試してみると、不思議なことがおきそうな気配w


Buffer Getsはほぼ同じなので、全表走査になりやすい?場合、索引が利用できそうなら使わせたほうがいいですな。多分。

23:12:22 SCOTT@pdborcl> r
1 select /*+ leading(tc) use_nl(tc tb ta) index(tc pk_tc) */ *
2 from
3 tc join tb
4 on
5 tc.version = tb.version
6 and tc.branch# = tb.branch#
7 join ta
8 on
9 tb.version = ta.version
10 where
11 tc.version between 1 and 10
12* fetch first 1000 rows only

1000行が選択されました。

経過: 00:00:00.13

実行計画
----------------------------------------------------------
Plan hash value: 3242622317

------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 300K| 456M| 1141K (1)| 00:00:45 |
|* 1 | VIEW | | 300K| 456M| 1141K (1)| 00:00:45 |
|* 2 | WINDOW NOSORT STOPKEY | | 300K| 864M| 1141K (1)| 00:00:45 |
| 3 | NESTED LOOPS | | | | | |
| 4 | NESTED LOOPS | | 300K| 864M| 1141K (1)| 00:00:45 |
| 5 | NESTED LOOPS | | 600K| 1155M| 841K (1)| 00:00:33 |
| 6 | TABLE ACCESS BY INDEX ROWID| TC | 1200K| 1156M| 174K (1)| 00:00:07 |
|* 7 | INDEX RANGE SCAN | PK_TC | 1200K| | 3278 (1)| 00:00:01 |
| 8 | TABLE ACCESS BY INDEX ROWID| TB | 1 | 1008 | 1 (0)| 00:00:01 |
|* 9 | INDEX UNIQUE SCAN | PK_TB | 1 | | 0 (0)| 00:00:01 |
|* 10 | INDEX UNIQUE SCAN | PK_TA | 1 | | 0 (0)| 00:00:01 |
| 11 | TABLE ACCESS BY INDEX ROWID | TA | 1 | 1004 | 1 (0)| 00:00:01 |
------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - filter("from$_subquery$_006"."rowlimit_$$_rownumber"<=1000)
2 - filter(ROW_NUMBER() OVER ( ORDER BY NULL )<=1000)
7 - access("TC"."VERSION">=1 AND "TC"."VERSION"<=10)
9 - access("TC"."VERSION"="TB"."VERSION" AND "TC"."BRANCH#"="TB"."BRANCH#")
filter("TB"."VERSION"<=10 AND "TB"."VERSION">=1)
10 - access("TB"."VERSION"="TA"."VERSION")
filter("TA"."VERSION">=1 AND "TA"."VERSION"<=10)


統計
----------------------------------------------------------
0 recursive calls
0 db block gets
2420 consistent gets
0 physical reads
0 redo size
1044954 bytes sent via SQL*Net to client
1270 bytes received via SQL*Net from client
68 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1000 rows processed

FETCH FISRSTを利用すると、rownumとは異なり、内部でROW_NUMBER() OVER( OVER BY NULL) <= N
のような変換が発生するんですね!!!! 


rownumの弱点はどうなったか確認してみます。

12c でも rownum は rownumですね! という確認から。

23:37:32 SCOTT@pdborcl> r
1 select /*+ leading(tc) use_nl(tc tb ta) */ *
2 from
3 tc join tb
4 on
5 tc.version = tb.version
6 and tc.branch# = tb.branch#
7 join ta
8 on
9 tb.version = ta.version
10 where
11 tc.version between 11 and 20
12* and rownum <= 1000

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

経過: 00:00:08.21

実行計画
----------------------------------------------------------
Plan hash value: 1463769645

-------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1000 | 2952K| 37940 (1)| 00:00:02 |
|* 1 | COUNT STOPKEY | | | | | |
| 2 | NESTED LOOPS | | | | | |
| 3 | NESTED LOOPS | | 1101 | 3250K| 37940 (1)| 00:00:02 |
| 4 | NESTED LOOPS | | 22019 | 42M| 26928 (1)| 00:00:02 |
| 5 | TABLE ACCESS BY INDEX ROWID BATCHED| TC | 38230 | 36M| 5683 (1)| 00:00:01 |
|* 6 | INDEX RANGE SCAN | PK_TC | | | 109 (0)| 00:00:01 |
| 7 | TABLE ACCESS BY INDEX ROWID | TB | 1 | 1008 | 1 (0)| 00:00:01 |
|* 8 | INDEX UNIQUE SCAN | PK_TB | 1 | | 0 (0)| 00:00:01 |
|* 9 | INDEX UNIQUE SCAN | PK_TA | 1 | | 0 (0)| 00:00:01 |
| 10 | TABLE ACCESS BY INDEX ROWID | TA | 1 | 1004 | 1 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - filter(ROWNUM<=1000)
6 - access("TC"."VERSION">=11 AND "TC"."VERSION"<=20)
8 - access("TC"."VERSION"="TB"."VERSION" AND "TC"."BRANCH#"="TB"."BRANCH#")
filter("TB"."VERSION">=11 AND "TB"."VERSION"<=20)
9 - access("TB"."VERSION"="TA"."VERSION")
filter("TA"."VERSION">=11 AND "TA"."VERSION"<=20)


統計
----------------------------------------------------------
0 recursive calls
0 db block gets
1174942 consistent gets
176197 physical reads
0 redo size
913 bytes sent via SQL*Net to client
533 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed


FETCH FIRST N ROWS ONLYでも弱点は同じです!

23:36:02 SCOTT@pdborcl> r
1 select /*+ leading(tc) use_nl(tc tb ta) index(tc pk_tc) */ *
2 from
3 tc join tb
4 on
5 tc.version = tb.version
6 and tc.branch# = tb.branch#
7 join ta
8 on
9 tb.version = ta.version
10 where
11 tc.version between 11 and 20
12* fetch first 1000 rows only

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

経過: 00:00:07.36

実行計画
----------------------------------------------------------
Plan hash value: 3242622317

------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 29999 | 45M| 1141K (1)| 00:00:45 |
|* 1 | VIEW | | 29999 | 45M| 1141K (1)| 00:00:45 |
|* 2 | WINDOW NOSORT STOPKEY | | 29999 | 86M| 1141K (1)| 00:00:45 |
| 3 | NESTED LOOPS | | | | | |
| 4 | NESTED LOOPS | | 29999 | 86M| 1141K (1)| 00:00:45 |
| 5 | NESTED LOOPS | | 599K| 1155M| 841K (1)| 00:00:33 |
| 6 | TABLE ACCESS BY INDEX ROWID| TC | 1200K| 1156M| 174K (1)| 00:00:07 |
|* 7 | INDEX RANGE SCAN | PK_TC | 1200K| | 3278 (1)| 00:00:01 |
| 8 | TABLE ACCESS BY INDEX ROWID| TB | 1 | 1008 | 1 (0)| 00:00:01 |
|* 9 | INDEX UNIQUE SCAN | PK_TB | 1 | | 0 (0)| 00:00:01 |
|* 10 | INDEX UNIQUE SCAN | PK_TA | 1 | | 0 (0)| 00:00:01 |
| 11 | TABLE ACCESS BY INDEX ROWID | TA | 1 | 1004 | 1 (0)| 00:00:01 |
------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - filter("from$_subquery$_006"."rowlimit_$$_rownumber"<=1000)
2 - filter(ROW_NUMBER() OVER ( ORDER BY NULL )<=1000)
7 - access("TC"."VERSION">=11 AND "TC"."VERSION"<=20)
9 - access("TC"."VERSION"="TB"."VERSION" AND "TC"."BRANCH#"="TB"."BRANCH#")
filter("TB"."VERSION">=11 AND "TB"."VERSION"<=20)
10 - access("TB"."VERSION"="TA"."VERSION")
filter("TA"."VERSION">=11 AND "TA"."VERSION"<=20)


統計
----------------------------------------------------------
0 recursive calls
0 db block gets
1174942 consistent gets
175116 physical reads
0 redo size
913 bytes sent via SQL*Net to client
533 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed


最後に、ハッシュ結合にした場合のrownum vs fetch first n rows onlyの比較

NL結合にすべきか、ハッシュ結合にすべきかどうかは、悩むんですよ。状況に合わせて使い分ける必要があるのは、11gでも12cでも同じだと思います。理由は前回のエントリを参照のこと。

rownumでハッシュ結合にした場合、11g R2では黙っていても索引を利用していたのですが、12c R1では全表走査になる傾向が見られます。
11gの実行計画と同じオブジェクトを参照するようにヒントでチューニングしてありますが、やはりここでもTABLE ACCESS BY INDEX ROWID BATCHEDが行われていますね。

実に興味深い。

23:46:06 SCOTT@pdborcl> r
1 select /*+ leading(tc) use_hash(tc tb ta) index(ta pk_ta) */ *
2 from
3 tc join tb
4 on
5 tc.version = tb.version
6 and tc.branch# = tb.branch#
7 join ta
8 on
9 tb.version = ta.version
10 where
11 tc.version between 1 and 10
12* and rownum <= 1000

1000行が選択されました。

経過: 00:00:34.63

実行計画
----------------------------------------------------------
Plan hash value: 3316229909

--------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1000 | 4923K| | 199K (1)| 00:00:08 |
|* 1 | COUNT STOPKEY | | | | | | |
|* 2 | HASH JOIN | | 2002 | 9857K| | 199K (1)| 00:00:08 |
| 3 | TABLE ACCESS BY INDEX ROWID BATCHED | TA | 10 | 10040 | | 4 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | PK_TA | 10 | | | 1 (0)| 00:00:01 |
|* 5 | HASH JOIN | | 4004 | 7894K| 1170M| 199K (1)| 00:00:08 |
|* 6 | TABLE ACCESS FULL | TC | 1200K| 1156M| | 139K (1)| 00:00:06 |
| 7 | TABLE ACCESS BY INDEX ROWID BATCHED| TB | 10001 | 9844K| | 1486 (0)| 00:00:01 |
|* 8 | INDEX RANGE SCAN | PK_TB | 10000 | | | 26 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - filter(ROWNUM<=1000)
2 - access("TB"."VERSION"="TA"."VERSION")
4 - access("TA"."VERSION">=1 AND "TA"."VERSION"<=10)
5 - access("TC"."VERSION"="TB"."VERSION" AND "TC"."BRANCH#"="TB"."BRANCH#")
6 - filter("TC"."VERSION"<=10 AND "TC"."VERSION">=1)
8 - access("TB"."VERSION">=1 AND "TB"."VERSION"<=10)


統計
----------------------------------------------------------
1258 recursive calls
0 db block gets
515770 consistent gets
516798 physical reads
0 redo size
1062679 bytes sent via SQL*Net to client
1270 bytes received via SQL*Net from client
68 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1000 rows processed

FETCH FIRST N ROWS ONLYを利用した場合

00:20:36 SCOTT@pdborcl> r
1 select /*+ leading(tc) use_hash(tc tb ta) index(ta pk_ta) index(tb pk_tb) */ *
2 from
3 tc join tb
4 on
5 tc.version = tb.version
6 and tc.branch# = tb.branch#
7 join ta
8 on
9 tb.version = ta.version
10 where
11 tc.version between 1 and 10
12* fetch first 1000 rows only

1000行が選択されました。

経過: 00:00:32.69

実行計画
----------------------------------------------------------
Plan hash value: 3430218324

-------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 300K| 456M| | 199K (1)| 00:00:08 |
|* 1 | VIEW | | 300K| 456M| | 199K (1)| 00:00:08 |
|* 2 | WINDOW NOSORT STOPKEY | | 300K| 864M| | 199K (1)| 00:00:08 |
|* 3 | HASH JOIN | | 300K| 864M| | 199K (1)| 00:00:08 |
| 4 | TABLE ACCESS BY INDEX ROWID | TA | 10 | 10040 | | 4 (0)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | PK_TA | 10 | | | 1 (0)| 00:00:01 |
|* 6 | HASH JOIN | | 600K| 1155M| 1170M| 199K (1)| 00:00:08 |
|* 7 | TABLE ACCESS FULL | TC | 1200K| 1156M| | 139K (1)| 00:00:06 |
| 8 | TABLE ACCESS BY INDEX ROWID| TB | 10001 | 9844K| | 1486 (0)| 00:00:01 |
|* 9 | INDEX RANGE SCAN | PK_TB | 10000 | | | 26 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - filter("from$_subquery$_006"."rowlimit_$$_rownumber"<=1000)
2 - filter(ROW_NUMBER() OVER ( ORDER BY NULL )<=1000)
3 - access("TB"."VERSION"="TA"."VERSION")
5 - access("TA"."VERSION">=1 AND "TA"."VERSION"<=10)
6 - access("TC"."VERSION"="TB"."VERSION" AND "TC"."BRANCH#"="TB"."BRANCH#")
7 - filter("TC"."VERSION"<=10 AND "TC"."VERSION">=1)
9 - access("TB"."VERSION">=1 AND "TB"."VERSION"<=10)


統計
----------------------------------------------------------
1456 recursive calls
0 db block gets
516181 consistent gets
514506 physical reads
0 redo size
1045990 bytes sent via SQL*Net to client
1270 bytes received via SQL*Net from client
68 SQL*Net roundtrips to/from client
75 sorts (memory)
0 sorts (disk)
1000 rows processed


Top N に関してはrownumでも fetch first N rows onlyでも弱点は弱点なのでrownumと同じ考え方でチューニングの方向を決めないと、ね。


rownum使って満足しちゃってると..... #1
rownum使って満足しちゃってると..... #2
rownum使って満足しちゃってると..... #3
rownum使って満足しちゃってると..... #4
rownum使って満足しちゃってると.....おまけ

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

2013年6月27日 (木)

Oracle Database 12c R1 12.1.0.1.0 released!

http://www.oracle.com/technetwork/jp/database/enterprise-edition/downloads/index.html

Oracle Database 12c release 1 12.1.0.1.0 がやっと公開されました :)

ダウンロードは朝一でしたが、帰宅してからインストール、力尽きたので、寝ます。<イマココ

ちなみに、Linuxは、CentOS5.8 x86_64です。Oracle11g R2をインストールしていたのですが、そのまま別ORACLE_HOMEへインストールしてみました。 

問題なく?インストールできたようですが、6系とかSolarisにしたほうが良かったかなぁ...w


20130627_03453


20130627_11605


なんか、沢山のバックグランドプロセスが... まだマニュアルもまともに読んでないので、これからです :)


20130627_12233


そして、噂のpga_aggregate_limit

SQL> show parameter pga

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
pga_aggregate_limit big integer 3596M
pga_aggregate_target big integer 1798M
SQL>

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