2. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 1
Agenda
I. OracleアーキテクチャとSQL処理
II. データとファイルI/O
III. テーブル、索引と実行計画
IV. オプティマイザ統計
V. データベースバッファキャッシュ
VI. SQLの解析と共有プール
VII. ソートとPGA、一時表領域
VIII.まとめ
3. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 2
RDBMSとは / Oracle Databaseとは
• RDBMS(Relational Database Management
System) =表(テーブル)形式のデータを保管するデータベ
ース管理システム
• データ操作用の言語SQLを用いて、クライアントアプリケーシ
ョンからデータの検索および更新を実行できる
• Oracle DatabaseはRDBMS製品の1つ
テーブル
id ename ・・・
87 Steven ・・・
204 Hermann ・・・
ABC xxx ・・・
クライアント
アプリケーション
id ename ・・・
87 Steven ・・・
204 Hermann ・・・
205 Shelly ・・・
SELECT …
① SQL発行
②検索結果
RDBMS
以後 "Oracle Database"を"Oracle"と略記
7. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 6
V$SESSION
• V$ビュー(動的パフォーマンスビュー)はOracleの内部状態を
確認できる特殊なビュー
• V$SESSIONからセッションの状態が確認できる
主要な列名 確認できる情報
SID セッションID
SERIAL# SIDとSERIAL#でセッションを一意に識別できる
USERNAME Oracleユーザー名
PROGRAM クライアントアプリケーションの情報
TYPE 'USER' : Oracleユーザーの接続
'BACKGROUND' : バックグラウンドプロセスの接続
EVENT 発生している待機イベント
8. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 7
Oracleアーキテクチャ - データ・記憶域構造
表領域
テーブル
データファイル
データブロック
行データ
id ename ・・・
87 Steven ・・・
204 Hermann ・・・
205 Shelly ・・・
1つの表領域が複数のデータファイルから構成され
る場合もあります
行データ
9. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 8
SQLの実行とファイルI/O
セッション
SGA
SQLの発行
実行結果の返送
データファイル
サーバープロセス
SQL実行
クライアント
アプリケーション
データベースバッファ
キャッシュ
データブロック
10. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 9
Oracleのテーブル(ヒープ構成表)
• テーブルに格納される行の順序は不定
– ある行の位置を特定できない
• ある行を取得したい場合の処理
1. テーブルのHWM以下の全ブロックを読み
出し
(=TABLE ACCESS FULL、
いわゆるテーブルフルスキャン)
2. 条件に合致した行のみを抽出
(=filter)
• データ量が多い場合はI/Oが大量に発生
し、非効率
– テーブルフルスキャンは一般に避けるべき
ブロック1
ブロック2
id name ・・・
87 Steven ・・・
27 Hermann ・・・
21 Shelly ・・・
id name ・・・
20 Neena ・・・
3 Lex ・・・
1 William ・・・
…
ブロックn
id name ・・・
103 Alexandar ・・・
105 David ・・・
203 Susan ・・・
表
11. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 10
デモ:データ1行取得のためにテーブルフルスキャン
-- 30000行のデータを持つテーブルを作成
set autotrace off
drop table testtbl;
create table testtbl
( id number, n number, name varchar(80), color varchar(4), dummy1 char(2000));
insert into testtbl select level, TRUNC(DBMS_RANDOM.VALUE * 1000), 'aaa', 'red', 'xxx'
from dual connect by level <= 30000;
commit;
exec dbms_stats.gather_table_stats(NULL,'TESTTBL');
SELECT count(*) FROM testtbl;
-- id=1の行(1行)をSELECT → TABLE ACCESS FULL + filter
set autotrace on
set timing on
alter system flush buffer_cache;
SELECT id, name FROM testtbl WHERE id = 1;
12. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 11
索引の仕組み
<DBA5>
<DBA9> <DBA4>
id=1 ブロック1
ブロック2
rowid5
…
id=1
索引
ルートブロック
ブランチブロック
リーフブロック
<DBA8>
ROWID id name ・・・
rowid0 87 Steven ・・・
rowid1 27 Hermann ・・・
rowid2 21 Shelly ・・・
id アドレス
~199 DBA5
~340 DBA…
803~ DBA…
ROWID id name ・・・
rowid3 20 Neena ・・・
rowid4 3 Lex ・・・
rowid5 1 William ・・・
…
id アドレス
~20 DBA9
~35 DBA8
175~ DBA4
id アドレス
1 rowid5
3 rowid4
20 rowid3
…
…
id アドレス
21 rowid2
27 rowid1
35 rowid9
…
id アドレス
175 rowid6
177 rowid8
199 rowid9
…
…
…
索引を用いたアクセス
INDEX UNIQUE SCANオペレーション
TABLE ACCESS BY INDEX ROWID (BATCHED) オペレーション
A
B
ブロックn
ROWID id name ・・・
rowid97 103 Alexandar ・・・
rowid98 105 David ・・・
rowid99 203 Susan ・・・
C
A
id=1
B
表
表を用いたアクセス
TABLE FULL SCANオペレーションC
13. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 12
実行計画とは
• 実行計画は、SQLがOracleで実行される手順を示す
• 実行計画はコストベースオプティマイザ(CBO; Cost-Based
Optimizer)が作成する
– CBOはOracleの内部コンポーネント
– オプティマイザ統計が最新でないと適切な実行計画が作成されないこ
とに注意
• 意図したパフォーマンスが得られない場合、想定した実行計画
で実行されているかチェックする必要がある
--------------------------------------------------------------
| Id | Operation | Name | Rows |... |
--------------------------------------------------------------
| 0 | SELECT STATEMENT | | |... |
| 1 | NESTED LOOPS | | 2 |... |
|* 2 | TABLE ACCESS FULL | PA | 1 |... |
| 3 | TABLE ACCESS BY INDEX ROWID| CH | 2 |... |
|* 4 | INDEX RANGE SCAN | IDX_CHPA | 2 |... |
--------------------------------------------------------------
14. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 13
デモ:索引を作成して実行計画の変化をみる
-- id列に索引を作成
create index testidx1 on testtbl(id);
exec dbms_stats.gather_table_stats(NULL,'TESTTBL');
-- 先ほどと同じSELECT文を実行
set autotrace on
set timing on
-- キャッシュの影響を排除するため、データベースバッファキャッシュをflush
alter system flush buffer_cache;
-- 実行計画とphysical reads をチェック
SELECT id, name FROM testtbl WHERE id = 1;
15. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 14
実行計画と物理I/Oブロック数の比較
--------------------------------------------------
| Id | Operation | Name | Rows |... |
--------------------------------------------------
| 0 | SELECT STATEMENT | | 1 |... |
|* 1 | TABLE ACCESS FULL| TESTTBL | 1 |... |
--------------------------------------------------
統計
----------------------------------------------------------
10098 physical reads
---------------------------------------------------------------------
| Id | Operation | Name | Rows |... |
---------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 |... |
| 1 | TABLE ACCESS BY INDEX ROWID BATCHED| TESTTBL | 1 |... |
|* 2 | INDEX RANGE SCAN | TESTIDX1 | 1 |... |
---------------------------------------------------------------------
統計
----------------------------------------------------------
3 physical reads
索引作成
(出力を整形しています)
(出力を整形しています)
16. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 15
[参考] SQL*Plusのautotrace
• 実行計画と実行統計を表示する
– 実行計画は 内部的にEXPLAIN PLAN +
DBMS_XPLAN.DISPLAYを用いて表示
– 問合せ結果表示のON/OFFも可能
• SQL> set autotrace [パラメータ]
パラメータ 実行計画 実行統計 問合せ結果
ON ○ ○ ○
ON EXPLAIN ○ ー ○
ON STATISTICS ー ○ ○
TRACEONLY ○ ○ ー
OFF ー ー ○
詳細は「SQL*Plusユーザーズ・ガイドおよびリファレンス」
→ 「SQL*Plusのチューニング」、
18. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 17
選択率と最適なアクセス
…
BLUE
BLUE
BLUE
BLUE
BLUE
BLUE
RED
BLUE
BLUE
BLUE
BLUE
BLUE
SELECT …
WHERE color='RED'
SELECT …
WHERE color ='BLUE'
19. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 18
デモ:偏りがある列を検索条件に指定
-- 1行だけ color='blue'に変更
update testtbl set color = 'blue' WHERE id = 1;
-- color列に索引を作成
create index testidx2 on testtbl(color);
exec dbms_stats.gather_table_stats(NULL,'TESTTBL');
-- データの偏りをチェック
set autotrace off
SELECT color, count(*) FROM testtbl GROUP BY color;
-- color='red'の行(29999行)をSELECT → TABLE ACCESS FULL + filter
set autotrace traceonly
-- color列に索引があるにもかかわらず、TABLE ACCESS FULL であることに着目
SELECT * FROM testtbl WHERE color='red';
-- こちらはINDEX RANGE SCAN
SELECT * FROM testtbl WHERE color='blue';
20. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 19
デモ:偏りがある列を検索条件に指定
--------------------------------------------------
| Id | Operation | Name | Rows |... |
--------------------------------------------------
| 0 | SELECT STATEMENT | | 29999 |... |
|* 1 | TABLE ACCESS FULL| TESTTBL | 29999 |... |
--------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("COLOR"='red')
---------------------------------------------------------------------
| Id | Operation | Name | Rows |... |
---------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 |... |
| 1 | TABLE ACCESS BY INDEX ROWID BATCHED| TESTTBL | 1 |... |
|* 2 | INDEX RANGE SCAN | TESTIDX2 | 1 |... |
---------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("COLOR"='blue')
検索ヒット行数= 29999行
検索ヒット行数= 1行
21. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 20
オプティマイザ統計の役割
• 最適な実行計画を作成するためには「データの格納状態」を知
る必要がある
• オプティマイザ統計はデータの格納状態を集約した情報
• 「データの格納状態」が大きく変化した場合は、オプティマイザ
統計を収集する
22. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 21
オプティマイザ統計の収集方法
• DBMS_STATS.GATHER_xxxx プロシージャを使用する
– 従来使用されていたANALYZEコマンドは使用しない
DBMS_STATSのプロシージャ 取得対象オブジェクト
GATHER_DATABASE_STATS データベース全体のオブジェクト
GATHER_SCHEMA_STATS 指定されたスキーマ内のオブジェ
クト
GATHER_TABLE_STATS 指定されたテーブル(+インデッ
クス)
GATHER_INDEX_STATS 指定されたインデックス
26. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 25
デモ:データベースバッファキャッシュの効果
-- 索引スキャンするSQLを2回実行して、キャッシュの効果をみる
set autotrace traceonly
alter system flush buffer_cache;
-- 1回目の実行
SELECT * FROM testtbl WHERE id = 1;
-- 2回目の実行
SELECT * FROM testtbl WHERE id = 1;
-- physical reads がない → キャッシュされている
-- consistent gets → 論理I/Oは実行されている
27. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 26
デモ: データベースバッファキャッシュの効果
---------------------------------------------------------------------
| Id | Operation | Name | Rows |... |
---------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 |... |
| 1 | TABLE ACCESS BY INDEX ROWID BATCHED| TESTTBL | 1 |... |
|* 2 | INDEX RANGE SCAN | TESTIDX1 | 1 |... |
---------------------------------------------------------------------
統計
----------------------------------------------------------
:
4 consistent gets
3 physical reads
統計
----------------------------------------------------------
:
4 consistent gets
0 physical reads
1回目の実行
2回目の実行
28. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 27
バッファヒット率
• Statspack / AWR レポートのInstance Efficiencyセ
クションから確認できる
– Statspack / AWR レポート: 性能分析用の診断レポート
• 最近のシステムでは99%程度も決して珍しくない
– SGAに割り当てられるメモリサイズが大きくなったため
Instance Efficiency Percentages (Target 100%)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Buffer Nowait %: 99.93 Redo NoWait %: 100.00
Buffer Hit %: 70.22 In-memory Sort %: 99.95
Library Hit %: 99.73 Soft Parse %: 98.99
Execute to Parse %: 74.86 Latch Hit %: 99.92
Parse CPU to Parse Elapsd %: 49.76 % Non-Parse CPU: 99.16
Shared Pool Statistics Begin End
------ ------
Memory Usage %: 72.48 70.71
% SQL with executions>1: 62.52 63.39
% Memory for SQL w/exec>1: 53.55 57.10
29. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 28
データベースバッファキャッシュの注意点
• (当然ながら)キャッシュできるブロック数には制限がある
– データベースバッファキャッシュ(or SGA)のメモリサイズに上限がある
ため
– いっぱいになったら、使用頻度が低いものから消去される (age-out)
• ダイレクトパスリードの場合はキャッシュされない
– PGAに直接データが読み込まれる
30. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 29
SQL解析と共有プール
• ハードパースで実施する処理
– SQL構文チェック
– アクセス対象オブジェクトのチェック
– SQLの最適化
– 実行計画の立案
• 解析結果は共有カーソルとして共有プールにキャッシュ
SGAサーバープロセス
クライアント
アプリケーション
共有プール
共有
カーソル
③キャッシュ
① SQL
解析
②ハードパース
31. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 30
共有カーソルのキャッシュ
• 一度実行されたSQLの解析結果(=共有カーソル)は再利用
される
– ソフトパースによる処理効率化:SQL処理時間の短縮、CPU負荷の
軽減
SGAサーバープロセス
解析
クライアント
アプリケーション
共有プール
共有
カーソル
③キャッシュ
サーバープロセス
クライアント
アプリケーション
②ハードパース
②ソフトパース
① SQL
① SQL
33. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 32
デモ:V$SQLと共有プール
-- 同一のSQLを複数回実行して、共有カーソルのキャッシュ効果を見る
-- すでに共有カーソルが存在するとデモの意味がないので、いったん共有プールをflushする
set autotrace off
set timing off
ALTER SYSTEM flush shared_pool;
-- この時点では(実行しようとしているSQLの)共有カーソルは存在しない
/* dummy */ SELECT sql_id,child_number, executions, sql_text FROM V$SQL
WHERE sql_text LIKE 'SELECT%FROM testtbl%';
-- SQLを実行して共有カーソルを確認
SELECT id, name FROM testtbl WHERE id = 1;
/* dummy */ SELECT sql_id,child_number, executions, sql_text FROM V$SQL
WHERE sql_text LIKE 'SELECT%FROM testtbl%';
-- SQLを再実行して共有カーソルが1つである(=再利用されている)ことを確認
-- executions列がカウントアップしていることも見る
SELECT id, name FROM testtbl WHERE id = 1;
/* dummy */ SELECT sql_id,child_number, executions, sql_text FROM V$SQL
WHERE sql_text LIKE 'SELECT%FROM testtbl%';
34. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 33
デモ:V$SQLと共有プール
-- 類似したSQLは別のSQLとして扱われる
SELECT id, name FROM testtbl WHERE id = 2;
/* dummy */ SELECT sql_id,child_number, executions, sql_text FROM V$SQL
WHERE sql_text LIKE 'SELECT%FROM testtbl%';
SELECT id, name FROM testtbl WHERE id = 1;
/* dummy */ SELECT sql_id,child_number, executions, sql_text FROM V$SQL
WHERE sql_text LIKE 'SELECT%FROM testtbl%';
35. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 34
WHERE条件のリテラル値のみが異なるSQL
• (類似していても)文字列として異なるSQLは、共有カーソルが
共有されない
– ハードパースによる処理効率低下:SQL処理時間とCPU負荷増加
– 共有メモリの非効率的な利用:使用メモリ量増加、キャッシュヒット率低下
SGAサーバープロセス
解析
クライアント
アプリケーション
共有プール
共有
カーソル
③キャッシュ
サーバープロセス
クライアント
アプリケーション
②ハードパース
①SELECT …
WHERE id = 1
①SELECT …
WHERE id = 2
共有
カーソル
③キャッシュ
②ハードパース
解析
36. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 35
バインド変数による共有カーソルの再利用
• 一度実行されたSQLの解析結果は再利用される
– ソフトパースによる処理効率化:SQL処理時間の短縮、CPU負荷の
軽減
– 共有メモリの効率的な利用:使用メモリ量削減、キャッシュヒット率向上
SGAサーバープロセス
解析
クライアント
アプリケーション
共有プール
共有
カーソル
③キャッシュ
サーバープロセス
クライアント
アプリケーション
②ハードパース
②ソフトパース
①SELECT …
WHERE id = :n
①SELECT …
WHERE id = :n
n=1
n=2
37. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 36
デモ:V$SQLから共有カーソルの動きを確認
-- リテラルを使用したSQLをバインド変数化して、共有カーソルのキャッシュ効果を見る
-- すでに共有カーソルが存在するとデモの意味がないので、いったん共有プールをflushする
ALTER SYSTEM flush shared_pool;
-- リテラルSQLでは、SQL毎に共有カーソルが作成される
SELECT id, name FROM testtbl WHERE id = 1;
SELECT id, name FROM testtbl WHERE id = 2;
/* dummy */ SELECT sql_id,child_number, executions, sql_text FROM V$SQL WHERE
sql_text LIKE 'SELECT%FROM testtbl%';
-- SQLをバインド変数化
variable n NUMBER
exec :n := 1
SELECT id, name FROM testtbl WHERE id = :n;
/* dummy */ SELECT sql_id,child_number, executions, sql_text FROM V$SQL WHERE
sql_text LIKE 'SELECT%FROM testtbl%';
-- バインド変数値を変えて再実行 → 共有カーソルが再利用される
exec :n := 2
SELECT id, name FROM testtbl WHERE id = :n;
39. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 38
どのような時にソートが実行されるか
• どのような時にソートが実行されるか
– SELECT .. ORDER BY句
– ソートマージジョイン
– DISTINCT, UNIONなど重複排除系処理
• 最近のバージョンではハッシュに置き換えられている
– CREATE INDEX
– オプティマイザ統計の収集
– など
• ソートの負荷は高い
– 要件的に必要なければソートしない
– ソートが避けられない場合は、全量データが必要か検討する
• rownum疑似列を用いたデータ量の絞込み など
• ソート以外のデータ処理 : ハッシュ、ビットマップ
40. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 39
pga_aggregate_target
• 各プロセスのPGAの総サイズを制限
• おおむねpga_aggregate_targetの5%が各プロセス
のPGAの上限値となる
41. Copyright (C) 2015 CO-Sol Inc. All Rights Reserved 40
デモ:ソート
-- ORDER BYを指定した時の実行計画と使用した作業領域を確認
-- pga_aggregate_target を小さい値に
alter system set memory_target = 0;
alter system set pga_aggregate_target = 100M scope=memory;
set autotrace traceonly
set timing on
-- sorts (disk) から一時表領域を使用してソートされていることがわかる
SELECT * FROM TESTTBL ORDER BY n;
-- pga_aggregate_target を大きい値に
alter system set pga_aggregate_target = 400M scope=memory;
-- sorts (memory) からPGAを使用してソートされていることがわかる
SELECT * FROM TESTTBL ORDER BY n;