このブログを検索

2011年2月25日金曜日

似て非なるSQLを探す

Oracleは意識的にプレースホルダを使わないと、共有プールのSQL領域を食いつぶしてSQLのキャッシュ率が悪くなります。
SGAを増やす手段もありますが、数ギガ規模にまで増やすとキャッシュの吐き出し(エージアウト)をしている間、SQLキャッシュ全体をロック(ラッチ)されて処理を何も受け付けなくなります。
そこで、リテラル値が含まれているSQLを定期的に探すといいでしょう。
この例では、SQL文を前方一致100文字だけで比較していますが、アプリケーションによっては50~150文字など調整するといいかと思います。
CNTが多いものを最優先に対応するといいでしょう。
select "Stmt",cnt,"Mem/count","Exec" from (
  SELECT row_number() over (order by count(*) desc) as rn,
      substr(sql_text,1,100) "Stmt", count(*) cnt,
      sum(sharable_mem)/count(*)    "Mem/count",
      sum(executions)      "Exec"
  FROM v$sqlstats
  GROUP BY substr(sql_text,1,100)
  HAVING count(*) > 10
) where rn<=100;
実行例は次の通り。
Stmt                                                                                    CNT  Mem/count       Exec
-------------------------------------------------------------------------------- ---------- ---------- ----------
    SELECT     msfr.free_rankavg_id,     msfr.free_rankavg_nm,     msfr.event_id       4308 36555.0975       4312
,     msfr.team_flg,

select substrb(dump(val,16,0,32),1,120) ep, cnt from (select /*+ no_parallel(t)         308 12900.4416       3365
no_parallel_index(t)

select TABLE_NAME,TABLESPACE_NAME,CLUSTER_NAME,PCT_FREE,PCT_USED,INI_TRANS,MAX_T        170 44840.8471        380
RANS,INITIAL_EXTENT/

select column_name,data_type,data_length,nullable,data_default,data_precision,da        127 48466.2047        310
ta_scale from user_t

 select /*+ no_parallel(t) no_parallel_index(t) dbms_stats cursor_sharing_exact         104 11319.4615       1182
use_weak_name_resl d

SELECT /*+ cursor_sharing_exact */ count(*) FROM  "SYS"."KUPC$DATAPUMP_QUETAB" T        100      12426          0
AB, SYS.DUAL WHERE t

select /*+ no_parallel(t) no_parallel_index(t) dbms_stats cursor_sharing_exact u         93 51273.5484       1069
se_weak_name_resl dy

SELECT /* OPT_DYN_SAMP */ /*+ ALL_ROWS IGNORE_WHERE_CLAUSE NO_PARALLEL(SAMPLESUB         91 17089.3187       1338
) opt_param('paralle

    SELECT     tau.user_id,     tau.aplus_level_no,     taf.appr_stat_cd    FROM         63 19573.8413        252
     aplus001iuser.t

select * from ( select rank() over ( order by last_access_dt desc , rownum) AS r         49 32231.8367        161
n, user_id,uid_2,car

insert into TBL_ObjectiveEventLog (regist_dt,event_id,objective_id,carrier_id,us         34 10804.2353        397
er_id,event_clear_co

SELECT COUNT(DISTINCT BAG_USER_ID), COUNT(DISTINCT CAP_USER_ID) FROM (SELECT CAS         32    22367.5       4622
E MBAG.BAG_KIND WHEN

SELECT COUNT(DISTINCT APL_USER_ID), COUNT(DISTINCT SMS_USER_ID) FROM (SELECT CAS         32   23160.75       4458
E MAPP.SMST_FLG WHEN

select item_id,category_id,item_nm,carrier_1_publish_flg,carrier_2_publish_flg,c         25   13244.16         88
arrier_3_publish_flg

SELECT * FROM (SELECT DISTINCT user_id, 1 as carrier_id, row_number() over( orde         22 17519.6364         65
r by last_adm_dt  )

SELECT alias000$."STYLESHEET" AS STYLESHEET FROM "SYS"."METASTYLESHEET" alias000         20      14730        992
$ WHERE 1 = 1 AND ((

select user_regist_kind1, TO_CHAR(last_adm_dt_kind1,'YYYY/MM/DD HH24:MI:SS') as          20    24929.2         93
last_adm_dt_kind1 fr

SELECT     user_id,     sum(prev_user_point_amt),      sum(user_point_result_amt         18 15337.3333         19
),     trunc(update_

    SELECT     mfri.free_rankavg_incentive_id,     mfri.free_rankavg_id,     mfr         18      15336         18
i.team_flg,     mfri

     sss01dbiuser.         17 22733.6471        291
tbl_usermyroom1

select * from (       select temp_.*, rownum as rownumber_ from (            SEL         16    35747.5        389
ECT         mwp.aplu

select * from (       select temp_.*, rownum as rownumber_ from (            sel         15    34043.2      13478
ect     user_id,

SELECT count(DISTINCT user_id) as datacount FROM MST_User1 WHERE user_id in (SEL         15    14788.8         42
ECT user_id FROM MST

SELECT AP001_ID,USER_ID,AP001_LEVEL_NO,MISSION_COMPLETE_PCT,TOTAL_GAME_CNT,TOTAL         13 27131.0769         87
_COIN_AMT,TOTAL_DECO

select user_id,nick_name,mail,mail_sec,mail_domain,user_name,user_zip,user_pref,         12 29984.6667       5073
user_address,to_char

SELECT AP001_ITEM_ID,AP001_ID,AP001_ITEM_CATEGORY_CD,CARRIER_1_PUBLISH_FLG,CARRI         12       9270         31
ER_1_PUBLISH_DT,CARR

2011年2月24日木曜日

LOBセグメントからテーブル名を探す

LOBはテーブルセグメントとは別管理なので、セグメントのサイズを確認するとSYS_LOB
から始まるセグメント名で表示されます。
shrinkするのにテーブル名を知りたい場合、dba_lobsで探すことができます。
set time on
set pages 10000
set lines 120
col owner for a20
col tablespace_name for a20
col table_name for a30
col column_name for a20
col segment_name for a30
select owner,segment_name,tablespace_name,table_name,column_name from dba_lobs
where segment_name in ('SYS_LOB0000032214C00005$$','SYS_LOB0000032217C00014$$');
実行例は次の通り。
OWNER           SEGMENT_NAME                   TABLESPACE_NAME TABLE_NAME           COLUMN_NAME
--------------- ------------------------------ --------------- -------------------- --------------------
SSS01DBIUSER    SYS_LOB0000032214C00005$$      SSS01_I_DATA    TBL_AAARESTEXT1      AAA_ANS_TEXT
SSS01DBIUSER    SYS_LOB0000032217C00014$$      SSS01_I_DATA    TBL_GENERALENTRY1    GENERALENTRY_FREE

セグメントのサイズを確認する

テーブルやインデックスなどのセグメントは、使ううちに断片化して肥大化します。
定期的にサイズをチェックし、shrinkなどの対策をするといいでしょう。
set time on
 set pages 10000
 set lines 120
 col segment_name for a30
 col tablespace_name for a20
 col bytes for 9,999,999,999
 select tablespace_name,segment_name,bytes from (
   select rank() over (order by bytes desc) rnk,
     tablespace_name,segment_name,bytes from dba_segments
 ) where rnk<=20;
実行例は次の通り。
TABLESPACE_NAME      SEGMENT_NAME                            BYTES
-------------------- ------------------------------ --------------
SSS01_INDPA1_DATA    TBL_CHARGECONSENTLOG1           1,412,431,872
SSS01_MASTERD_DATA   TBL_OBJECTIVESTREAMING01LOG1    1,046,478,848
SSS01_MASTERD_DATA   IXT2_OBJECTIVESTREAMING01LOG1     745,537,536
SSS01_MASTERD_DATA   TBL_MEDIAAPPITEMLOG1              732,954,624
SSS01_MASTERD_DATA   TBL_OBJECTIVESTREAMING01LOG3      495,976,448
SSS01_MASTERD_DATA   TBL_OBJSTREAMING01LOG1_1201       490,733,568
SSS01_MASTERD_DATA   TBL_OBJSTREAMING01LOG1_0101       475,004,928
SSS01_MASTERD_DATA   TBL_OBJSTREAMING01LOG1_0201       452,984,832
SSS01_MASTERD_DATA   TBL_CCACCESS1                     418,381,824
SSS01_MASTERD_DATA   TBL_OBJSTREAMING01LOG1_1101       387,973,120
SSS01_MASTERD_DATA   IXT2_OBJECTIVESTREAMING01LOG3     353,370,112
FUKA_I_DATA          TBL_OBJECTIVESTREAMING011         344,981,504
SSS01_MASTERD_DATA   TBL_MEDIABAGLOG1                  342,884,352
FUKA_I_DATA          TBL_DAILYTEXTMACHINEUPLOAD1       319,815,680
FUKA_I_DATA          TBL_USERSESSION1                  318,767,104
FUKA_I_DATA          TBL_DAILYTEXTTOTALUPLOAD1         279,969,792
SSS01_I_DATA         TBL_USERSESSION1                  264,241,152
FUKA_I_DATA          TBL_CCQUIZ_USER_RESULT1           244,318,208
FUKA_I_IDX           IXT1_DAILYTEXTTOTALUPLOAD1        236,978,176
SSS01_MASTERD_DATA   TBL_OBJSTREAMING01LOG3_0201       227,540,992

2011年2月20日日曜日

データベースファイルを追加し表領域を拡張する

1.データベースファイル名を確認する
$ sqlplus sys as sysdba
SQL> set pages 10000
set lines 120
col tablespace_name for a20
col file_name for a50
col bytes for 999,999,999,999
select tablespace_name,file_name,bytes,status from DBA_DATA_FILES
where tablespace_name='SSS01_I_DATA'
order by tablespace_name,file_name;

TABLESPACE_NAME  FILE_NAME                            BYTES          STATUS
---------------- ------------------------------------ -------------- ---------
SSS01_I_DATA     /DATA/DATABASE/SSS01_I_DATA_01.DBF    2,147,483,648 AVAILABLE
SSS01_I_DATA     /DATA/DATABASE/SSS01_I_DATA_02.DBF    2,147,483,648 AVAILABLE
SSS01_I_DATA     /DATA/DATABASE/SSS01_I_DATA_03.DBF    2,147,483,648 AVAILABLE
SSS01_I_DATA     /DATA/DATABASE/SSS01_I_DATA_04.DBF    2,147,483,648 AVAILABLE
2.データベースファイルを追加する
A)ASMの場合(SE RACなど)
※ASM(RAW)はパスが1文字違うので注意。
$ sqlplus sys as sysdba
ALTER TABLESPACE SSS01_I_DATA
  ADD DATAFILE '+DATA/DATABASE/SSS01_I_DATA_05.DBF' SIZE 2048M AUTOEXTEND ON;
B)ファイルシステムの場合
$ sqlplus sys as sysdba
ALTER TABLESPACE SSS01_I_DATA
  ADD DATAFILE '/DATA/DATABASE/SSS01_I_DATA_05.DBF' SIZE 2048M AUTOEXTEND ON;

Data Pumpによる過去分データをインポートする

今担当している案件では頻繁に過去データの調査があるため、ときどきバックアップから開発DBにインポートしています。
インポートにはData Pumpを使っています。
Recovery Managerではない理由は次の通り。
・インポート先(開発DB)の容量不足でエクスポートデータを置けない
・サーバ間マテリアライズドビューが多数あるので、テーブルとインデックス以外をリカバリしたくない
・週次でRMANフルバックアップという運用をしているため、リカバリがめんどうw
1.はじめに
Oracleには2種類のエクスポート/インポートコマンドがあります。
Data Pumpを使っている理由は、速度とスキーマ変更機能です。
2.作業の流れ
ここでは、マテビューのマスタ側サーバのエクスポートデータをインポートします。
そのままインポートするとマテビューログや統計情報も含まれるので、次の流れで 行います。
(1)バックアップサーバからエクスポートデータをコピー
(2)DDLの抽出ディレクトリの確認
(3)エクスポートデータからDDLだけをファイル出力
(4)DDLファイルを編集し、テーブルおよびインデックス以外を削除
(5)編集したDDLを実行してcreate table|index
(6)エクスポートデータからレコードデータのみをインポート
(7)analyze
(1)バックアップサーバからエクスポートデータをコピー
エクスポートデータのコピー例
$ ssh sssdev1
$ /backup/databasefile/201008/sssdb3/
$ scp sss01_db_i_dp20100820.dmp.gz  oracle@sssdb11:/usr/local/dbdata/
(2)DDLの抽出ディレクトリの確認
ディレクトリ設定がされているか確認します。
ここではEXPDP_DATAを使います。
select * from dba_directories;
OWNER      DIRECTORY_NAME            DIRECTORY_PATH
---------- ------------------------- ---------------------------------------------
SYS        ORACLE_OCM_CONFIG_DIR     /opt/app/oracle/product/10.2.0/db/ccr/state
SYS        DATA_PUMP_DIR             /opt/app/oracle/product/10.2.0/db/rdbms/log/
SYS        EXPDP_DATA                /usr/local/dbdata
(3)エクスポートデータからDDLだけをファイル出力
本番システムで使っていないスキーマにインポートしたい時はremap_schemaが非常に便利です。
remap_tableの方が便利ですが、たしか11gからだったと思います。
ここではtestdocomoという調査用に作ったスキーマに変換します。
$ vi testdocomo.par1_0820 
directory=expdp_data
dumpfile=sss01_db_i_dp20100820.dmp   ★エクスポートしたデータ
logfile=sss01_db_i_sql20100820.log
job_name=job_impdp
sqlfile=sss01_db_i_20100820.sql   ★DDLのファイル出力
remap_schema=sss01docomo:testdocomo   ★別スキーマにも変換可能
remap_tablespace=sss01_i_data:test_i_data   ★別表領域にも変換可能
remap_tablespace=sss01_i_idx:test_i_idx
remap_tablespace=mvlog_i_data:test_i_data
INCLUDE=TABLE:"IN ('T_ACCESS1','T_USER1')"   ★テーブル指定も可能

$ impdp testdocomo/xxxxxxxxxxxx parfile=testdocomo.par1_0820 
(4)DDLファイルを編集し、テーブルおよびインデックス以外を削除
TABLE, INDEX, CONSTRAINT以外を削除します。
特に、マテビューログのSYS用DDLは、元のスキーマ名で設定するので注意。
また、ビットマップインデックスは、通常のインデックスとは別項目で出力することも注意。
vi等で編集して★だけ残します。
$ grep "^-- new obj" sss01_db_i_20100902.sql 
-- new object type path is: SCHEMA_EXPORT/TABLE/TABLE   ★
-- new object type path is: SCHEMA_EXPORT/TABLE/INDEX/INDEX   ★
-- new object type path is: SCHEMA_EXPORT/TABLE/CONSTRAINT/CONSTRAINT   ★
-- new object type path is: SCHEMA_EXPORT/TABLE/INDEX/STATISTICS/INDEX_STATISTICS
-- new object type path is: SCHEMA_EXPORT/TABLE/COMMENT
-- new object type path is: SCHEMA_EXPORT/TABLE/INDEX/FUNCTIONAL_AND_BITMAP/INDEX   ★
-- new object type path is: SCHEMA_EXPORT/TABLE/INDEX/STATISTICS/FUNCTIONAL_AND_BITMAP/INDEX_STATISTICS
-- new object type path is: SCHEMA_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
-- new object type path is: SCHEMA_EXPORT/TABLE/POST_TABLE_ACTION
-- new object type path is: SCHEMA_EXPORT/TABLE/MATERIALIZED_VIEW_LOG
(5)編集したDDLを実行してcreate table|index
テーブルおよびインデックス作成例
$ sqlplus testdocomo/xxxxxxxxxxxx
SQL> @sss01_db_i_20100820.sql
(6)エクスポートデータからレコードデータのみをインポート
レコードデータのインポート例
$ cat testdocomo.par2_0820 
directory=expdp_data
dumpfile=sss01_db_i_dp20100820.dmp
logfile=sss01_db_i_sql20100820.log
job_name=job_impdp
remap_schema=sss01docomo:testdocomo
remap_tablespace=sss01_i_data:test_i_data
remap_tablespace=sss01_i_idx:test_i_idx
remap_tablespace=mvlog_i_data:test_i_data
CONTENT=DATA_ONLY   ★レコードデータのみを指定
INCLUDE=TABLE:"IN ('T_ACCESS1','T_USER1')"   ★テーブル指定も可能

$ impdp testdocomo/xxxxxxxxxxxx parfile=testdocomo.par2_0820 
(7)analyze
データ量が多いときはやった方が精神衛生上よいです。
analyze table TBL_SG1_0820 compute statistics;   ★インデックスもanalyze

Data Pumpによる過去分データをインポートする

今担当している案件では頻繁に過去データの調査があるため、ときどきバックアップから開発DBにインポートしています。
インポートにはData Pumpを使っています。
Recovery Managerではない理由は次の通り。
・インポート先(開発DB)の容量不足でエクスポートデータを置けない
・サーバ間マテリアライズドビューが多数あるので、テーブルとインデックス以外をリカバリしたくない
・週次でRMANフルバックアップという運用をしているため、リカバリがめんどうw
1.はじめに
Oracleには2種類のエクスポート/インポートコマンドがあります。
Data Pumpを使っている理由は、速度とスキーマ変更機能です。
2.作業の流れ
ここでは、マテビューのマスタ側サーバのエクスポートデータをインポートします。
そのままインポートするとマテビューログや統計情報も含まれるので、次の流れで 行います。
(1)バックアップサーバからエクスポートデータをコピー
(2)DDLの抽出ディレクトリの確認
(3)エクスポートデータからDDLだけをファイル出力
(4)DDLファイルを編集し、テーブルおよびインデックス以外を削除
(5)編集したDDLを実行してcreate table|index
(6)エクスポートデータからレコードデータのみをインポート
(7)analyze
(1)バックアップサーバからエクスポートデータをコピー
エクスポートデータのコピー例
$ ssh sssdev1
$ /backup/databasefile/201008/sssdb3/
$ scp sss01_db_i_dp20100820.dmp.gz  oracle@sssdb11:/usr/local/dbdata/
(2)DDLの抽出ディレクトリの確認
ディレクトリ設定がされているか確認します。
ここではEXPDP_DATAを使います。
select * from dba_directories;
OWNER      DIRECTORY_NAME            DIRECTORY_PATH
---------- ------------------------- ---------------------------------------------
SYS        ORACLE_OCM_CONFIG_DIR     /opt/app/oracle/product/10.2.0/db/ccr/state
SYS        DATA_PUMP_DIR             /opt/app/oracle/product/10.2.0/db/rdbms/log/
SYS        EXPDP_DATA                /usr/local/dbdata
(3)エクスポートデータからDDLだけをファイル出力
本番システムで使っていないスキーマにインポートしたい時はremap_schemaが非常に便利です。
remap_tableの方が便利ですが、たしか11gからだったと思います。
ここではtestdocomoという調査用に作ったスキーマに変換します。
$ vi testdocomo.par1_0820 
directory=expdp_data
dumpfile=sss01_db_i_dp20100820.dmp   ★エクスポートしたデータ
logfile=sss01_db_i_sql20100820.log
job_name=job_impdp
sqlfile=sss01_db_i_20100820.sql   ★DDLのファイル出力
remap_schema=sss01docomo:testdocomo   ★別スキーマにも変換可能
remap_tablespace=sss01_i_data:test_i_data   ★別表領域にも変換可能
remap_tablespace=sss01_i_idx:test_i_idx
remap_tablespace=mvlog_i_data:test_i_data
INCLUDE=TABLE:"IN ('T_ACCESS1','T_USER1')"   ★テーブル指定も可能

$ impdp testdocomo/xxxxxxxxxxxx parfile=testdocomo.par1_0820 
(4)DDLファイルを編集し、テーブルおよびインデックス以外を削除
TABLE, INDEX, CONSTRAINT以外を削除します。
特に、マテビューログのSYS用DDLは、元のスキーマ名で設定するので注意。
また、ビットマップインデックスは、通常のインデックスとは別項目で出力することも注意。
$ grep "^-- new obj" sss01_db_i_20100902.sql 
-- new object type path is: SCHEMA_EXPORT/TABLE/TABLE
-- new object type path is: SCHEMA_EXPORT/TABLE/INDEX/INDEX
-- new object type path is: SCHEMA_EXPORT/TABLE/CONSTRAINT/CONSTRAINT
-- new object type path is: SCHEMA_EXPORT/TABLE/INDEX/STATISTICS/INDEX_STATISTICS
-- new object type path is: SCHEMA_EXPORT/TABLE/COMMENT
-- new object type path is: SCHEMA_EXPORT/TABLE/INDEX/FUNCTIONAL_AND_BITMAP/INDEX
-- new object type path is: SCHEMA_EXPORT/TABLE/INDEX/STATISTICS/FUNCTIONAL_AND_BITMAP/INDEX_STATISTICS
-- new object type path is: SCHEMA_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
-- new object type path is: SCHEMA_EXPORT/TABLE/POST_TABLE_ACTION
-- new object type path is: SCHEMA_EXPORT/TABLE/MATERIALIZED_VIEW_LOG
(5)編集したDDLを実行してcreate table|index
テーブルおよびインデックス作成例
$ sqlplus testdocomo/xxxxxxxxxxxx
SQL> @sss01_db_i_20100820.sql
(6)エクスポートデータからレコードデータのみをインポート
レコードデータのインポート例
$ cat testdocomo.par2_0820 
directory=expdp_data
dumpfile=sss01_db_i_dp20100820.dmp
logfile=sss01_db_i_sql20100820.log
job_name=job_impdp
remap_schema=sss01docomo:testdocomo
remap_tablespace=sss01_i_data:test_i_data
remap_tablespace=sss01_i_idx:test_i_idx
remap_tablespace=mvlog_i_data:test_i_data
CONTENT=DATA_ONLY   ★レコードデータのみを指定
INCLUDE=TABLE:"IN ('T_ACCESS1','T_USER1')"   ★テーブル指定も可能

$ impdp testdocomo/xxxxxxxxxxxx parfile=testdocomo.par2_0820 
(7)analyze
データ量が多いときはやった方が精神衛生上よいです。
analyze table TBL_SG1_0820 compute statistics;   ★インデックスもanalyze

2011年2月18日金曜日

スキーマの表領域へのアクセス制限を確認する

スキーマ作成および権限付与(grant)をしても、特定の表領域を参照できないときは確認してみるといいでしょう。
表領域への割り当て制限設定がされていないと、権限があっても参照できません。
SQL> SELECT * FROM user_ts_quotas;
MAX_BYTES  ・・・  利用できる上限。負の値は無制限

TABLESPACE_NAME                     BYTES  MAX_BYTES     BLOCKS MAX_BLOCKS DRO
------------------------------ ---------- ---------- ---------- ---------- ---
SSS01_INDEP3_DATA                       0         -1          0         -1 NO
MVLOG_I_DATA                    161480704         -1      19712         -1 NO
SSS01_MASTER_IDX                        0         -1          0         -1 NO
SSS01_HISTORY_IDX                       0         -1          0         -1 NO
SSS01_MASTER_DATA                       0         -1          0         -1 NO
SSS01_HISTORY_DATA                      0         -1          0         -1 NO
SSS01_I_DATA                   4600102912         -1     561536         -1 NO
CCCC01TOWN_DATA                         0         -1          0         -1 NO
MVLOG_I2_DATA                           0         -1          0         -1 YES
SSS01_I_IDX                    3890216960         -1     474880         -1 NO
SSS01_INDEP1_DATA                       0         -1          0         -1 NO
CCCC01TOWN_IDX                          0         -1          0         -1 NO
SSS01_INDEP1_IDX                        0         -1          0         -1 NO
SSS01_INDEP2_IDX                        0         -1          0         -1 NO
SSS01_INDEP2_DATA                       0         -1          0         -1 NO
SSS01_INDEP3_IDX                        0         -1          0         -1 NO

スキーマ(ログインユーザ)を作成する

参照する表領域すべてについて割り当て制限(quota)設定が必要です。
grantで権限付与しても、quotaしないと当該表領域にアクセスできないので注意。
create user cccc01townusr
 identified by XXXXXXXXXX
 default tablespace CCCC01TOWN_DATA
 quota unlimited on CCCC01TOWN_DATA
 quota unlimited on CCCC01TOWN_IDX
 quota unlimited on SSS01_I_DATA
 quota unlimited on SSS01_I_IDX
 temporary tablespace TEMP;

2011年2月17日木曜日

共有プールの利用状況を確認する

負荷特性の異なる処理を混在させている場合、共有プールの変化をウォッチしておくとボトルネックを見つけられることがあります。
sql area   ・・・   SQL文そのもののキャッシュ
CCursor/PCursor   ・・・   カーソルキャッシュ
library cache   ・・・   コンパイル済SQLのキャッシュ
free memory   ・・・   空きメモリ

set pages 10000
set lines 100
set time on
col name for a30
col bytes for 999,999,999,999
select name,bytes from (
 select row_number() over (order by bytes desc) as rn,name,bytes from v$sgastat
 where pool = 'shared pool'
) where rn <= 20;

NAME                                      BYTES
------------------------------ ----------------
sql area                          2,484,421,928
free memory                       1,734,338,672
CCursor                             678,436,864
PCursor                             472,727,184
library cache                       352,787,688
sql area:PLSQL                      346,800,984
kglsim object batch                 182,272,608
gcs resources                       128,586,016
kglsim heap                         104,469,120
Cursor Stats                         98,273,576
gcs shadows                          76,999,136
db_block_hash_buckets                47,185,920
ASH buffers                          30,408,704
ges enqueues                         19,842,976
ges big msg buffers                  15,936,168
trace buffer                         14,057,472
KGLS heap                            13,290,704
event statistics per sess            12,296,000
FileOpenBlock                        11,575,096
ges resource                         11,342,888
似たSQLが多いWebサイト処理と、SQL数が多くなりがちな大量更新バッチを混在させていると次のグラフのようになることがあります。 バッチを実行していない時はfreeがかなり多いためボトルネックを見つけづらいと思います。

2011年2月15日火曜日

推奨パッチの検索

四半期ごとのPSU以外にもクリティカルなバグFixは、My Oracle Supportにて「その他推奨」に分類されます。
ここではOracle社の推奨パッチを検索する方法を紹介します。

1.PSR
最新版は、OiSCトップ(ヘッドライン)の最新パッチ情報-システム製品-に表示されます。
またはOiSCの「パッチ/メディア」タブから当該バージョンで確認することもできます。
OiSC   ・・・   http://support.oracle.co.jp/support/
2.CPU
最新版は、OiSCのトップ(ヘッドライン)の重要技術情報に表示されます。
過去分は後述するPSUと同じように検索します。

3.PSU、PSE
概要情報は、OiSCのKRWON検索で"PSU"→132780を参照します。
パッチ詳細やダウンロードはMy Oracle Supportで取得できます。
My Oracle Support   ・・・   https://support.oracle.com/

パッチと更新版>パッチ検索タブ>Search 
  製品→Oracle Database 
  検索条件を「+」ボタンで増やす 
  リリース→直近のリリース(10.2.0.4.5を探すなら10.2.0.4.4) 
  プラットフォーム→Linux x86-64など
  分類→その他推奨,セキュリティ

  検索後、右上の「検索の編集」で検索条件を保存

2011年2月11日金曜日

適用済パッチのバージョン確認

1.Oracle Database
$ export ORACLE_SID=sss1
$ $ORACLE_HOME/OPatch/opatch lsinventory
Invoking OPatch 10.2.0.4.8

Oracle Interim Patch Installerバージョン10.2.0.4.8
Copyright (c) 2009, Oracle Corporation.  All rights reserved。

Oracleホーム       : /opt/app/oracle/product/10.2.0/db
中央インベントリ : /opt/app/oracle/oraInventory
   元           : /etc/oraInst.loc
OPatchのバージョン    : 10.2.0.4.8
OUIのバージョン       : 10.2.0.4.0
OUIの場所      : /opt/app/oracle/product/10.2.0/db/oui
ログ・ファイルの場所 : /opt/app/oracle/product/10.2.0/db/cfgtoollogs/opatch/opatch2010-02-04_19-29-06午後.log

Patch history file: /opt/app/oracle/product/10.2.0/db/cfgtoollogs/opatch/opatch_history.txt

Lsinventory Output file location : /opt/app/oracle/product/10.2.0/db/cfgtoollogs/opatch/lsinv/lsinventory2010-02-04_19-29-06午後.txt

--------------------------------------------------------------------------------
インストールされた最上位製品(2): 

Oracle Database 10g                                                  10.2.0.1.0
Oracle Database 10g Release 2 Patch Set 3                            10.2.0.4.0  ★PSRのバージョン
このOracleホームには2の製品がインストールされています。

仮パッチ(4) :

Patch  7588384      : applied on Wed Dec 30 19:29:17 JST 2009
Unique Patch ID:  11943540
   Created on 11 Nov 2009, 07:28:48 hrs PST8PDT
   Bugs fixed:
     7588384
   This patch overlays patches:
     8833280
   This patch needs patches:
     8833280
   as prerequisites

Patch  8833280      : applied on Wed Dec 30 17:41:50 JST 2009  ★DB PSUのバージョン
Unique Patch ID:  11733883
   Created on 10 Sep 2009, 06:30:20 hrs PST8PDT
   Bugs fixed:
     6418420, 7835247, 7207654, 7592346, 6724797, 7936993, 7331867, 7552067
     5879114, 5457450, 8344348, 7272297, 7136866, 7196894, 7013124, 7196532
     8568395, 8309587, 7557226, 6509115, 8568397, 8568398, 6052226, 7424804
     6817593, 7553884, 6469211, 7527650, 8309592, 6945157, 6403091, 7552082
     6711853, 8304589, 8199266, 6327692, 5756769, 7460818, 6268409, 6687381
     6972843, 8230457, 6800507, 7027551, 6778714, 6200820, 6645719, 7393804
     3934160, 6683178, 6650256, 7528105, 6378112, 5126719, 7036453, 8426816
     8433026, 7270434, 7172531, 6451626, 8247855, 6874522, 7175513, 6960489
     7341598, 8576156, 6797677, 8342923, 5895190, 7150470, 7593835, 7356443
     7044551, 8227106, 4695511, 7298688, 5747462, 7197445, 5348308, 7937113
     8341623, 7569205, 8409848, 6163771, 6181488, 6375150, 7295780, 6345573
     7033630, 6954722, 7457766, 7309458, 8324577, 6840740, 6804746, 7375611
     8268054, 6988017, 7375613, 8344399, 7340448, 7375617, 8362683, 8251247
     5933656, 6599920, 7238230, 6452375, 6352003, 6833965, 7136489, 6610218
     7612639, 6392076, 5476236, 7609057, 7609058, 6374297, 6193945, 4693355
     7039896, 7432514, 7330909, 6952701, 7190270, 8287155, 7207932, 6802650
     7189447, 6615740, 7155655, 6749617, 7159505, 5727166, 5868257, 7173005
     6917874, 7691766, 7385253, 7225720, 7244238, 7363767, 7257770, 6941717
     8267348, 7710551, 7247217, 8328954, 6681695, 8702276, 8217011, 7661251
     6265559, 6823287, 6991626, 6954829, 5259835, 6500033, 5923486, 7432601
     8534387, 6653934, 7375644, 5147386, 7662491, 6490140, 8331466, 6070225
     5623467, 7396409, 6638558, 7038750, 6838714, 6870937, 7219752, 7263842
     7278117, 6882739, 5404871, 8836667, 8373286, 6678845, 6903051, 7936793
     7155248, 4966512, 7155249, 8836308, 8568402, 8568404, 8568405, 6343150
     6923450, 7643632, 8836671, 6145177, 6640411, 8347704, 8836675, 7155250
     7155251, 8836677, 7155252, 8836678, 7155253, 7155254, 8292378, 6219529
     7411865, 8227091, 8340379, 7276960, 5863926, 7123643, 6413089, 6596564
     6851438, 8836681, 8836683, 8836684, 7579469, 8836686, 7315642, 7494333
     8340383, 8340387, 6926448, 7600026, 6679303, 7197583, 7172752, 7008262
     7477934, 6733655, 6084232, 7499353, 6980597, 6799205, 6014513, 7140204
     7254987, 8833280, 7693128, 6120004, 6051177, 6858062, 7189645, 5630796
     7196863, 7378661, 7378735, 8290506, 6658484, 8309623, 7599944, 7125408
     6987790, 7257461, 5883691, 6919819, 7568556, 6955744, 6857917, 7149004
     6074620, 8283650, 7552042, 6506617, 8287504, 6271590, 5386204, 6976005
     7606362, 7043989, 8309632, 6870047, 8309637, 8309639, 6827260, 6752765
     6024730, 6628122, 8239142, 4637902, 8309642, 7345904, 6994160, 6919764
     7597354, 7523787, 6029179, 6455659, 5231155

Patch  6079224      : applied on Thu Oct 22 15:19:42 JST 2009
   Created on 15 Sep 2008, 03:58:35 hrs PST8PDT
   Bugs fixed:
     6079224

Patch  8436582      : applied on Thu Oct 22 15:11:28 JST 2009
Unique Patch ID:  11560856
   Created on 14 Jul 2009, 11:10:20 hrs IST
   Bugs fixed:
     8436582

複数のノードで構成されるRACシステム
  Local node = sssdb1
  Remote node = sssdb2

--------------------------------------------------------------------------------
OPatch succeeded.

2.Oracle Clusterware
$ export ORACLE_HOME=$ORA_CRS_HOME
$ $ORACLE_HOME/OPatch/opatch lsinventory
Invoking OPatch 10.2.0.4.2

Oracle Interim Patch Installer version 10.2.0.4.2
Copyright (c) 2007, Oracle Corporation.  All rights reserved.

Oracleホーム       : /opt/crs/oracle/product/10.2.0/app
中央インベントリ : /opt/app/oracle/oraInventory
   元           : /etc/oraInst.loc
OPatchのバージョン    : 10.2.0.4.2
OUIのバージョン       : 10.2.0.4.0
OUIの場所      : /opt/crs/oracle/product/10.2.0/app/oui
ログ・ファイルの場所 : /opt/crs/oracle/product/10.2.0/app/cfgtoollogs/opatch/opatch2011-02-11_22-41-09午後.log

Lsinventory Output file location : /opt/crs/oracle/product/10.2.0/app/cfgtoollogs/opatch/lsinv/lsinventory2011-02-11_22-41-09午後.txt

--------------------------------------------------------------------------------
インストールされた最上位製品(2): 

Oracle Clusterware                                                   10.2.0.1.0
Oracle Database 10g Release 2 Patch Set 3                            10.2.0.4.0
このOracleホームには2の製品がインストールされています。

仮パッチ(1) :

Patch  9294403      : applied on Tue May 18 16:09:18 JST 2010  ★CRS PSUのバージョン
   Created on 19 Mar 2010, 18:59:31 hrs PST8PDT
   Bugs fixed:
     9294403

複数のノードで構成されるRACシステム
  Local node = sssdb3
  Remote node = sssdb4

--------------------------------------------------------------------------------
OPatch succeeded.

Oracleパッチの種類

1.用語
PSR・・・Patch Set Release
PSU・・・Patch Set Updates
PSE・・・Patch Set Exception
CPU・・・Critical Patch Updates
OiSC・・・Oracle internet Support Center
MOS・・・My Oracle Support
CRS・・・Cluster Ready Services(現在のClusterware)

2.パッチの種類

3.注意
Oracle RACの場合、DatabaseとClusterwareのパッチは別々で、DB PSUにはCRS PSUが含まれていないこと。
CRS PSUは、PSRと同じバージョンである必要があります。

2011年2月9日水曜日

マテリアライズドビューの同期エラーを解決する

0.はじめに
マテリアライズドビューは、実体を持つビューのこと。
サーバ間レプリケーションとしても使えるが、設定によってはフルスキャンするので安易に使うべきではありません。
履歴系テーブルの集計など、ビューの内容を保存しておきたい場合に有効。
(用語)
マスタ表・・・同期元のテーブル
レプリケーション表・・・同期先のテーブル。マテリアライズドビュー
リフレッシュ・・・マスタ表からレプリケーション表への同期
完全リフレッシュ・・・マスタ表からレプリケーション表へテーブル全件コピー
マテリアライズドビューログ・・・マスタ表の更新履歴。マテビューログ
高速リフレッシュ・・・マテビューログのレプリケーション表への反映
リフレッシュグループ・・・自動リフレッシュでの実行ジョブの単位
rowidマテリアライズドビュー・・・rowidをキーにしたマテビュー。インデックス参照がないので高速

1.アラートログの確認
エラーは、レプリケーション側のDBのアラートログに出力されます。
$ORACLE_BASE/admin/sss01rep/bdump/alert_sss01rep.log

ここでは、rowidマテビューかつ高速リフレッシュ設定をした場合において、マスタ表をtruncateしてしまったケースを取り上げます。
高速リフレッシュは、更新履歴つまりマスタ表の差分情報だけで同期をするため、マスタ表そのものがなくなるとエラーとなります。
また、今回のケースはリフレッシュグループにより自動リフレッシュを行っています。
ORA-12034: "SSS01DBIUSER"."TBL_SITEITEM1"の
マテリアライズド・ビュー・ログは最終リフレッシュよりも新しいものです。

2.対応手順
完全リフレッシュをすることで解決します。
マテビューログは、完全リフレッシュすることにより自動的にtruncateされます。
手動でマテビューログをtruncateしても解決しません。
システムテーブルにあるマテビュー管理テーブルにスナップショット情報が残っているため不整合が発生します。

2-1.自動リフレッシュの失敗によりジョブが停止していないか確認します
BROKEN=Yの場合、停止しています。
失敗してもリトライしてくれますが、FAILURES≧16となるとジョブが停止します。
set time on
set pages 10000
set lines 100
COLUMN BROKEN FORMAT a6
COLUMN SCHEMA_USER FORMAT a20
COLUMN JOB FORMAT 99999
COLUMN WHAT FORMAT a55
alter session set nls_date_format='yyyy/mm/dd hh24:mi:ss';
select JOB,SCHEMA_USER,LAST_DATE,NEXT_DATE,FAILURES,BROKEN,WHAT from dba_jobs;

   JOB SCHEMA_USER          LAST_DATE           NEXT_DATE             FAILURES BROKEN
------ -------------------- ------------------- ------------------- ---------- ------
WHAT
-------------------------------------------------------
    50 SSS01DBIUSER         2011/02/09 22:46:47 2011/02/09 22:47:47          9 N
dbms_refresh.refresh('"SSS01DBIUSER"."REFRESH_I"');

2-2.アラートログでエラーとなっているテーブルをリフレッシュグループから外します
完全リフレッシュ中に、自動同期と処理が重ならないにするためです。
$ sqlplus sss01dbiuser@SSS01REP
SQL> execute dbms_refresh.subtract(name=>'REFRESH_I',list=>'TBL_SITEITEM1')

2-3.必要であればリフレッシュグループを再開します。
高速リフレッシュの場合、リフレッシュグループが停止している間、マテビューログに更新履歴が溜まり続けます。
マテビューログは必ずフルスキャンなので、溜め過ぎてから再開するとリフレッシュが終わらなくなります。
サーバ間マテビューの場合、UNDO関連など別のエラーが発生して2次災害となります。
$ sqlplus sss01dbiuser@SSS01REP
SQL> exec dbms_job.broken(job=>50,broken=>false);
SQL> commit;

2-4.インデックス情報を調べておき、レプリケーション表のインデックスを削除します
インデックスを貼ったままだと、完全リフレッシュが数倍遅くなります。
SQL> drop index IXT1_SITEITEM1;

2-5.完全リフレッシュを行います
sqlplus sss01dbiuser@SSS01REP
SQL> exec dbms_mview.refresh('SSS01DBIUSER.TBL_SITEITEM1', 'c')

2-6.インデックスを再作成します
sqlplus sss01dbiuser@SSS01REP
SQL> create index IXT1_SITEITEM1 on TBL_SITEITEM1 (USER_ID,ITEM_ID) tablespace SSS01_I_IDX;

2-7.リフレッシュグループに再追加
sqlplus sss01dbiuser@SSS01REP
SQL> exec DBMS_REFRESH.ADD ('REFRESH_I','TBL_SITEITEM1');

2-8.リフレッシュグループが停止していたら再開

2-9.自動リフレッシュのインターバルを待ち、FAILURES=0かつBROKEN=Nであることを確認します

2011年2月8日火曜日

ライブラリキャッシュの利用状況を確認する

SQLチューニングをほとんどしていない環境では、SQLの本数が多すぎることがあります。
その場合、データバッファキャッシュよりライブラリキャッシュがボトルネックになるかもしれません。

v$librarycacheのライブラリキャッシュ情報をウォッチするといいでしょう。

ヒット率は95%以上が理想です。
SQLの本数が多い場合、ラッチ(キャッシュのロック)がボトルネックになるのでgethitratioを注視すべきです。
gethitratio・・・ラッチの取得率
pinhitratio・・・キャッシュ(のデータ)の取得率。

set time on
set pages 10000
set lines 120
col namespace for a20
select namespace,gethitratio,pinhitratio from v$librarycache;

実行例は次の通り。
NAMESPACE            GETHITRATIO PINHITRATIO
-------------------- ----------- -----------
SQL AREA              .872027894  .981766737
TABLE/PROCEDURE       .994262842   .97704901
BODY                  .999516938  .998802497
TRIGGER               .915954808  .921656241
INDEX                 .692952564  .828487881
CLUSTER               .990343307  .990707854
OBJECT                         1           1
PIPE                           1           1
JAVA SOURCE           .194444444  .236842105
JAVA RESOURCE         .194444444  .236842105
JAVA DATA                      1           1


なお、10gR2(?)では、たまにhitratioが1000%を超えたりほぼ0%になる不具合(?)があります。

セッションをKILLできない

alter system kill sessionを実行しても、STATUS=KILLEDのままセッションが消えないことがあります。
接続元クライアントを終了させればセッションが消えますが、それでも残っている場合、OSのプロセスを強制終了します。
set time on
set pages 10000
set lines 100
column username format a10
column status format a10
column sid format 99999
column spid format a6
alter session set nls_date_format='yyyy/mm/dd hh24:mi:ss';
select ses.sid,ses.serial#,proc.spid,ses.logon_time,ses.status 
from v$process proc,v$session ses 
where proc.addr=ses.paddr;
実行結果は次の通り。
SPID(プロセス番号)でkillします。
  SID    SERIAL# SPID   LOGON_TIME          STATUS
------ ---------- ------ ------------------- ----------
   555          1 4740   2011/02/07 12:57:00 ACTIVE
   554          1 4742   2011/02/07 12:57:00 ACTIVE
   553          1 4744   2011/02/07 12:57:00 ACTIVE
   552          1 4746   2011/02/07 12:57:00 ACTIVE
   551          1 4748   2011/02/07 12:57:00 ACTIVE
   550          1 4750   2011/02/07 12:57:00 ACTIVE
   549          1 4752   2011/02/07 12:57:00 ACTIVE
   548          1 4754   2011/02/07 12:57:00 ACTIVE
   547          1 4756   2011/02/07 12:57:00 ACTIVE
   546          1 4758   2011/02/07 12:57:00 ACTIVE
   545          1 4760   2011/02/07 12:57:00 ACTIVE
   544          1 4762   2011/02/07 12:57:00 ACTIVE
   540          7 4770   2011/02/07 12:57:10 ACTIVE
   537          2 4806   2011/02/07 12:57:20 ACTIVE
   536          4 4808   2011/02/07 12:57:20 ACTIVE
   527      19899 22096  2011/02/07 23:23:39 ACTIVE

# kill -KILL 22096

2011年2月7日月曜日

待機しているセッションを調べる

DBサーバ作業中にコマンドが返ってこないなど問題のあるセッションを探すのに使うと効果的。
set time on
set pages 10000
set lines 110
col event for a60
col state for a18
col username for a15
col sid for 99999
select w.sid,s.username,w.state,w.event
from v$session s,v$session_wait w
where s.sid=w.sid
  and w.event not like '%Net message % client'
  and w.event not like 'rdbms ipc message';

   SID USERNAME   STATE                EVENT
------ ---------- -------------------- ----------------------------------------------------------
   536            WAITING              Streams AQ: qmn slave idle wait
   537            WAITING              Streams AQ: waiting for time management or cleanup tasks
   540            WAITING              Streams AQ: qmn coordinator idle wait
   548            WAITING              smon timer
   555            WAITING              pmon timer

セッションを一覧表示する

v$sessionは情報が多すぎるので用途によってクエリを使い分けると効果的。

1.接続元とログイン時間を中心に
SQL> 
set pages 10000
set lines 150
COLUMN USERNAME FORMAT a20
COLUMN STATUS FORMAT a10
COLUMN EVENT FORMAT a60
COLUMN PROGRAM FORMAT a50
COLUMN SID FORMAT 99999
alter session set nls_date_format='yyyy/mm/dd hh24:mi:ss';
select sid,serial#,program,username,logon_time,status
from v$session order by logon_time;

   SID    SERIAL# PROGRAM                                       USERNAME   LOGON_TIME          STATUS
------ ---------- --------------------------------------------- ---------- ------------------- ----------
   547          1 oracle@snwdb0.smc.indexweb.co.jp (RECO)                  2011/02/07 12:57:00 ACTIVE
   554          1 oracle@snwdb0.smc.indexweb.co.jp (PSP0)                  2011/02/07 12:57:00 ACTIVE
   553          1 oracle@snwdb0.smc.indexweb.co.jp (MMAN)                  2011/02/07 12:57:00 ACTIVE
   552          1 oracle@snwdb0.smc.indexweb.co.jp (DBW0)                  2011/02/07 12:57:00 ACTIVE
   544          1 oracle@snwdb0.smc.indexweb.co.jp (MMNL)                  2011/02/07 12:57:00 ACTIVE
   545          1 oracle@snwdb0.smc.indexweb.co.jp (MMON)                  2011/02/07 12:57:00 ACTIVE
   546          1 oracle@snwdb0.smc.indexweb.co.jp (CJQ0)                  2011/02/07 12:57:00 ACTIVE
   555          1 oracle@snwdb0.smc.indexweb.co.jp (PMON)                  2011/02/07 12:57:00 ACTIVE
   548          1 oracle@snwdb0.smc.indexweb.co.jp (SMON)                  2011/02/07 12:57:00 ACTIVE
   549          1 oracle@snwdb0.smc.indexweb.co.jp (CKPT)                  2011/02/07 12:57:00 ACTIVE
   550          1 oracle@snwdb0.smc.indexweb.co.jp (LGWR)                  2011/02/07 12:57:00 ACTIVE
   551          1 oracle@snwdb0.smc.indexweb.co.jp (DBW1)                  2011/02/07 12:57:00 ACTIVE
   540          7 oracle@snwdb0.smc.indexweb.co.jp (QMNC)                  2011/02/07 12:57:10 ACTIVE
   537          2 oracle@snwdb0.smc.indexweb.co.jp (q000)                  2011/02/07 12:57:20 ACTIVE
   536          4 oracle@snwdb0.smc.indexweb.co.jp (q001)                  2011/02/07 12:57:20 ACTIVE
   527      19899 sqlplus@codev0.smc.indexweb.co.jp (TNS V1-V3) PERFSTAT   2011/02/07 23:23:39 ACTIVE

2.実行中のイベントを中心に
SQL> 
set pages 10000
set lines 120
COLUMN USERNAME FORMAT a20
COLUMN STATUS FORMAT a10
COLUMN EVENT FORMAT a60
COLUMN SID FORMAT 99999
alter session set nls_date_format='yyyy/mm/dd hh24:mi:ss';
select sid,serial#,username,event from v$session order by logon_time;

   SID   SERIAL# USERNAME   EVENT
------ ---------- ---------- ------------------------------------------------------------
   547         1            rdbms ipc message
   554         1            rdbms ipc message
   553         1            rdbms ipc message
   552         1            rdbms ipc message
   544         1            rdbms ipc message
   545         1            rdbms ipc message
   546         1            rdbms ipc message
   555         1            pmon timer
   548         1            smon timer
   549         1            rdbms ipc message
   550         1            rdbms ipc message
   551         1            rdbms ipc message
   540         7            Streams AQ: qmn coordinator idle wait
   537         2            Streams AQ: waiting for time management or cleanup tasks
   536         4            Streams AQ: qmn slave idle wait
   527     19899 PERFSTAT   SQL*Net message to client

パフォーマンスツールSTATSPACKの利用

STATSPACKは、定期的に取得したスナップショットからDBのパフォーマンス値を取得するツールです。
スナップショットの差分により、v$sysstatなどのように累積値で記録している値の動きをとらえることができます。

1.STATSPACK用表領域の作成
CREATE TABLESPACE PERFSTAT_DATA
  DATAFILE '/DATA/DATABASE/PERFSTAT_DATA.DBF' SIZE 1024M REUSE AUTOEXTEND ON
  EXTENT MANAGEMENT LOCAL UNIFORM SIZE 1M
  SEGMENT SPACE MANAGEMENT AUTO;

2.STATSPACKのインストール
インストール用のコマンドで作成します。
$ sqlplus sys as sysdba
SQL> @$ORACLE_HOME/rdbms/admin/spcreate.sql
default_tablespaceに値を入力してください: PERFSTAT_DATA ★作成した表領域名
Using tablespace PERFSTAT_DATA as PERFSTAT default tablespace.

Choose the PERFSTAT user's Temporary tablespace.

TABLESPACE_NAME
--------------------------------------------------------------------------------
CONTENTS                    DB DEFAULT TEMP TABLESPACE
--------------------------- --------------------------
TEMP
TEMPORARY                   *

temporary_tablespaceに値を入力してください: TEMP

3.スナップショットの作成
スナップショット間隔が短いほど精度は上がります。
ただし、スナップショットの作成には負荷がかかるので1時間ごとが目安です。

$ sqlplus perfstat@SSS01DB
SQL> execute statspack.snap

セグメント(テーブル等)の情報も欲しい時は、スナップショットレベルを7以上にします。
SQL> execute statspack.snap(i_snap_level => 7) 

4.スナップショットの確認
STATSPACKはスナップショットの「差分」で生成するので、スナップショットが2つ以上必要です。
SQL> select snap_id, snap_time from stats$snapshot;

 SNAP_ID   SNAP_TIM
 --------- -----------------
         1 09-10-27 11:50:02
         2 09-10-27 11:50:18

5.STATSPACKレポートの作成
レポート出力用のコマンドを使ってレポートを作成します。
$ sqlplus perfstat@SSS01DB
SQL> @$ORACLE_HOME/rdbms/admin/spreport.sql;
Current Instance
~~~~~~~~~~~~~~~~

   DB Id    DB Name      Inst Num Instance
----------- ------------ -------- ------------
  190003545 SSS01DEV            1 sss01dev
                      :
Instance     DB Name        Snap Id   Snap Started    Level Comment
------------ ------------ --------- ----------------- ----- --------------------
sss01dev     SSS01DEV             1 27 10月 2009 15:2     5
                                    7
                                  2 27 10月 2009 15:3     5
                                    1

Specify the Begin and End Snapshot Ids
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
begin_snapに値を入力してください: 1 ★開始スナップショットID
Begin Snapshot Id specified: 1

end_snapに値を入力してください: 2 ★終了スナップショットID
End   Snapshot Id specified: 2

Specify the Report Name
~~~~~~~~~~~~~~~~~~~~~~~
The default report file name is sp_1_2.  To use this name,
press  to continue, otherwise enter an alternative.

report_nameに値を入力してください:  ★改行あるいは任意のファイル名

6.スナップショットの削除
スナップショットは削除しないと貯まり続けるので、適度に削除します。
スナップショット単位で削除すると負荷上昇やUNDO消費の原因になるので注意が必要です。

6-1.スナップショット単位で削除
$ sqlplus perfstat@SSS01DB
SQL> @?/rdbms/admin/sppurge
(削除開始スナップID):1
(削除終了スナップID):2

6-2.まるごと削除
$ sqlplus perfstat@SSS01DB
SQL> @?/rdbms/admin/sptrunc

SQL> select count(*) from stats$snapshot;
→ゼロ件であることを確認できます。

テーブルのカラム数を確認

カラム数が多すぎると共有プールのSQLキャッシュが増えすぎる恐れがあります。
新機能を実装するような場合に確認するといいでしょう。

一般的に、マスタ系のテーブルは属性がも多く、カラム数が多くてもやむを得ないことがあります。
ただし、トランザクション系のテーブルでカラムが多いのは設計そのものに問題がある可能性があります。
set time on
set pages 1000
set lines 100
col table_name for a30
col owner for a20
select owner,table_name,count(column_name) as columns
from dba_tab_columns
where owner<>'SYS'
group by owner,table_name
having count(column_name)>30
order by columns desc,owner,table_name;

実行例は次の通り。
この場合、上位4テーブルがゲームクエストのクリア件数をカラムごとに保持していたため、設計の見直しを検討しました。
OWNER                TABLE_NAME                        COLUMNS
-------------------- ------------------------------ ----------
APPLI001EUSER        TBL_USER_MISSION3                     105
APPLI001SUSER        TBL_USER_MISSION2                     105
APPLI002EUSER        TBL_USER_MISSION3                     105
APPLI002SUSER        TBL_USER_MISSION2                     105
HISTSSSUSER          MST_DOWNLOADITEM                       81
SSS01DBEUSER         TBL_USERMYROOM3                        51
SSS01DBSUSER         TBL_USERMYROOM2                        51
SSS01DBWUSER         TBL_USERMYROOM4                        51
SSS01DBEUSER         MST_USERPERSONAL3                      47
SSS01DBSUSER         MST_USERPERSONAL2                      47
SSS01DBWUSER         MST_USERPERSONAL4                      47
PERFSTAT             STATS$SQL_SUMMARY                      43
SYSTEM               LOGMNRC_GTLO                           40
APPLI001EUSER        TBL_APPLI_USER3                        37
APPLI001SUSER        TBL_APPLI_USER2                        37
APPLI002EUSER        TBL_APPLI_USER3                        37
APPLI002SUSER        TBL_APPLI_USER2                        37
PERFSTAT             STATS$SQL_PLAN                         34
SSS01DBSTEST         MST_APPITEM                            33
SSS01DBEUSER         TBL_AUTOUSE_STAT3                      32
SSS01DBSUSER         TBL_AUTOUSE_STAT2                      32
SSS01DBWUSER         TBL_AUTOUSE_STAT4                      32

2011年2月6日日曜日

インデックス情報の確認

テーブルとインデックスの関係だけならuser_indexesだけで十分です。
インデックスのカラムも知りたければこのクエリで確認できます。
set pages 10000
set lines 120
column table_name format a32
column index_name format a30
column column_name format a20
column tablespace_name format a20
select i.table_name,i.index_name,c.column_name,i.tablespace_name
 from dba_indexes i, dba_ind_columns c
 where i.index_name=c.index_name
  and i.owner=c.index_owner
  and i.table_name in ('TBL_USER1','TBL_PAGEACCESS1')
 order by i.table_name,i.index_name,c.COLUMN_POSITION;

実行例は次の通り。
TABLE_NAME        INDEX_NAME        COLUMN_NAME  TABLESPACE_NAME
----------------- ----------------- ------------ ---------------
TBL_PAGEACCESS1   IXT1_PAGEACCESS1  USER_ID      SSS_I_IDX
TBL_PAGEACCESS1   IXT1_PAGEACCESS1  PAGE_ID      SSS_I_IDX
TBL_PAGEACCESS1   IXT2_PAGEACCESS1  USER_ID      SSS_I_IDX
TBL_PAGEACCESS1   IXT3_PAGEACCESS1  PAGE_ID      SSS_I_IDX
TBL_USER1         IXT1_USER1        USER_ID      SSS_I_IDX

追記 2011/02/15
インデックスのowner(スキーマ)を条件に含めないと、別スキーマ同名インデックスが重複するので修正

UNDO表領域の使用率

UNDO表領域の使用率はdba_undo_extentsから計算します。
UNDOエクステントは、使用された後も一定期間は解放されないため
dba_free_spaceでは正確にはわかりません。
そこで、dba_undo_extentsのstatusを確認し、次のように計算します。

UNDO表領域の使用率 = [A] / [A]+[B]+[C]

[A] 使用中のUNDO = statusがACTIVE + UNEXPIRED
col bytes for 999,999,999,999
select status, sum(bytes) as bytes from dba_undo_extents
where tablespace_name = 'UNDOTBS1'
and status in ('ACTIVE','UNEXPIRED') group by status;

[B] 使用後のUNDO = statusがEXPIRED
col bytes for 999,999,999,999
select status, sum(bytes) as bytes from dba_undo_extents
where tablespace_name = 'UNDOTBS1' and status='EXPIRED'
group by status;

[C] 未割当のUNDO = dba_free_space
col bytes for 999,999,999,999
select sum(bytes) as bytes from dba_free_space
where tablespace_name = 'UNDOTBS1';

実行例は次の通り。
STATUS           BYTES
--------- ------------
UNEXPIRED   70,516,736
ACTIVE      13,631,488
EXPIRED     97,517,568

BYTES
----------------
32,044,089,344

UNDO表領域の使用率 = 84148224 / (84148224 + 97517568 + 32044089344) * 100
                   = 0.26 %

表領域の使用状況

表領域単位にデータファイルの使用状況を確認します。
outer joinにしているのは、空き容量が枯渇した場合にdba_free_spaceのレコードがなくなるため。

UNDO表領域は実際の使用量よりはかなり多めに計算されることに注意してください。
これは、解放されたブロックをすぐに再利用できるように、設定された期間(900秒が一般的)は論理削除をしているためです。
再利用可能なexpiredエクステントも使用中とみなされています。
 
実運用監視では、UNDO表領域を監視対象から外し、別の手段で検知するのがベターです。
set time on
set pagesize 10000
set linesize 100
col autoextensible heading "AUTO" for a4
col tablespace_name format a25
col sizemb for 999,999
col usedmb for 999,999
col freemb for 999,999
col ratio for 999.99
select dbf.tablespace_name,
  dbf.bytes/1024/1024 as sizemb,
  (dbf.bytes - sum(nvl(fsp.bytes,0)))/1024/1024 as usedmb,
  sum(nvl(fsp.bytes,0))/1024/1024 as freemb,
  (1-(sum(nvl(fsp.bytes,0))/dbf.bytes))*100 ratio,
  dbf.autoextensible
from sys.dba_free_space fsp
  right outer join (
    select tablespace_name,sum(bytes) as bytes,autoextensible
    from sys.dba_data_files
    group by tablespace_name,autoextensible
  ) dbf
  on dbf.tablespace_name=fsp.tablespace_name
group by dbf.tablespace_name,dbf.bytes,dbf.autoextensible
order by dbf.tablespace_name,autoextensible;

実行例は次の通り。
SIZEMB・・・表領域サイズ
USEDMB・・・使用サイズ
FREEMB・・・未使用サイズ
RATIO・・・使用率
AUTO・・・自動拡張

TABLESPACE_NAME             SIZEMB   USEDMB   FREEMB   RATIO AUTO
------------------------- -------- -------- -------- ------- ----
FUKA_MASTER_DATA             2,048    1,335      713   65.19 YES
FUKA_MASTER_IDX              1,024      442      582   43.16 YES
MVLOG_MASTER_DATA              512      121      391   23.63 YES
PERFSTAT_DATA                1,024      689      335   67.29 YES
SYSAUX                       2,048      285    1,763   13.90 YES
SYSTEM                       2,048      352    1,696   17.17 YES
UNDOTBS1                    32,749       44   32,706     .13 YES