「DBが遅い原因を特定したい」「何のセッションが負荷をかけているか見たい」——OracleのV$(動的パフォーマンスビュー)は現場DBAの目となり耳となる重要なビュー群です。本記事ではよく使うV$ビューとすぐ使えるSQLをまとめます。
目次
1. V$ビューとは {#about}
V$ビュー(動的パフォーマンスビュー)とは、Oracleが内部情報をリアルタイムに公開する仮想ビューです。
V$SESSION:現在接続中のセッション情報V$SQL:実行されたSQLのパフォーマンス情報V$LOCK:ロックの取得状況GV$xxxx:RAC環境用(全インスタンスを横断)
DBA_(静的)との違い:DBA_で始まるビューはデータディクショナリ(DB設計情報)を示すのに対し、V$は現在のDB稼働状況を示します。
2. セッション・プロセス監視 {#session}
現在接続中のセッション一覧
SELECT
SID,
SERIAL#,
USERNAME,
STATUS, -- ACTIVE/INACTIVE/KILLED
SCHEMANAME,
OSUSER,
MACHINE,
PROGRAM,
SQL_ID,
LAST_CALL_ET AS 経過秒数
FROM V$SESSION
WHERE TYPE = 'USER' -- バックグラウンドプロセスを除外
ORDER BY LAST_CALL_ET DESC;アクティブなセッションのみ確認
SELECT
SID,
SERIAL#,
USERNAME,
SQL_ID,
EVENT AS 待機イベント,
SECONDS_IN_WAIT AS 待機秒数,
STATE
FROM V$SESSION
WHERE STATUS = 'ACTIVE'
AND TYPE = 'USER'
ORDER BY SECONDS_IN_WAIT DESC;長時間実行中のセッションを特定
SELECT
s.SID,
s.SERIAL#,
s.USERNAME,
s.LAST_CALL_ET AS 実行秒数,
ROUND(s.LAST_CALL_ET / 60, 1) AS 実行分数,
q.SQL_TEXT
FROM V$SESSION s
JOIN V$SQL q ON s.SQL_ID = q.SQL_ID
WHERE s.STATUS = 'ACTIVE'
AND s.TYPE = 'USER'
AND s.LAST_CALL_ET > 300 -- 5分以上実行中
ORDER BY s.LAST_CALL_ET DESC;3. SQL実行パフォーマンス監視 {#sql-perf}
直近に実行された重いSQLを確認
-- CPU時間が長いSQLを確認
SELECT
SQL_ID,
ROUND(ELAPSED_TIME / 1000000, 2) AS 経過時間秒,
ROUND(CPU_TIME / 1000000, 2) AS CPU時間秒,
EXECUTIONS AS 実行回数,
ROUND(ELAPSED_TIME / DECODE(EXECUTIONS, 0, 1, EXECUTIONS) / 1000000, 3) AS 平均秒,
DISK_READS AS 物理読み取り,
BUFFER_GETS AS 論理読み取り,
SUBSTR(SQL_TEXT, 1, 80) AS SQL概要
FROM V$SQL
WHERE EXECUTIONS > 0
ORDER BY ELAPSED_TIME DESC
FETCH FIRST 20 ROWS ONLY;フルスキャンが多いSQLを確認(チューニング候補)
SELECT
SQL_ID,
EXECUTIONS,
ROUND(DISK_READS / DECODE(EXECUTIONS, 0, 1, EXECUTIONS)) AS 平均物理読み取り,
ROUND(BUFFER_GETS / DECODE(EXECUTIONS, 0, 1, EXECUTIONS)) AS 平均論理読み取り,
SUBSTR(SQL_TEXT, 1, 100) AS SQL概要
FROM V$SQL
WHERE DISK_READS / DECODE(EXECUTIONS, 0, 1, EXECUTIONS) > 10000
ORDER BY DISK_READS DESC
FETCH FIRST 20 ROWS ONLY;SQL_IDから実際のSQL全文を取得
SELECT SQL_FULLTEXT
FROM V$SQL
WHERE SQL_ID = 'xxxxxxxxx';
-- または
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('xxxxxxxxx'));4. 待機イベント分析 {#wait-events}
待機イベントとは、セッションがDBリソース(I/O・ロック・ラッチ等)を待っている状態のことです。パフォーマンス問題の原因特定に直結します。
現在の待機イベントを確認
SELECT
EVENT,
COUNT(*) AS セッション数,
SUM(SECONDS_IN_WAIT) AS 合計待機秒
FROM V$SESSION
WHERE TYPE = 'USER'
AND STATUS = 'ACTIVE'
AND WAIT_CLASS != 'Idle' -- アイドル状態を除外
GROUP BY EVENT
ORDER BY セッション数 DESC;システム全体の累積待機統計(AWR的な分析)
SELECT
EVENT,
TOTAL_WAITS AS 待機回数,
TIME_WAITED AS 合計待機時間(100分の1秒),
AVERAGE_WAIT AS 平均待機時間
FROM V$SYSTEM_EVENT
WHERE WAIT_CLASS != 'Idle'
ORDER BY TIME_WAITED DESC
FETCH FIRST 20 ROWS ONLY;代表的な待機イベントと意味:
| 待機イベント | 意味 | 対処の方向性 |
|---|---|---|
db file sequential read | インデックス経由の単一ブロック読み取り | インデックス最適化・I/O性能向上 |
db file scattered read | フルスキャンの複数ブロック読み取り | インデックス追加またはパーティション化 |
enq: TX - row lock contention | 行ロック競合 | コミット頻度の改善・ロック設計の見直し |
log file sync | COMMITのREDOログ書き込み待ち | ログファイルのI/O改善・バッチのCOMMIT間隔調整 |
latch: cache buffers chains | バッファキャッシュの競合 | ホットブロック対策(逆キーインデックスなど) |
5. I/O・メモリ監視 {#io-memory}
バッファキャッシュのヒット率を確認
-- ヒット率が95%以上が目安(低い場合はDB_CACHE_SIZEの拡張を検討)
SELECT
ROUND((1 - SUM(DECODE(NAME, 'physical reads', VALUE, 0)) /
(SUM(DECODE(NAME, 'db block gets', VALUE, 0)) +
SUM(DECODE(NAME, 'consistent gets', VALUE, 0)))) * 100, 2) AS ヒット率
FROM V$SYSSTAT
WHERE NAME IN ('physical reads', 'db block gets', 'consistent gets');データファイル別のI/O状況を確認
SELECT
df.NAME AS データファイル,
pf.PHYRDS AS 物理読み取り,
pf.PHYWRTS AS 物理書き込み,
pf.PHYBLKRD AS 読み取りブロック数,
pf.READTIM AS 読み取り時間(100分の1秒)
FROM V$FILESTAT pf
JOIN V$DATAFILE df ON pf.FILE# = df.FILE#
ORDER BY pf.PHYRDS DESC;SGA(共有メモリ)の使用状況を確認
SELECT NAME, ROUND(BYTES / 1024 / 1024, 1) AS MB
FROM V$SGA
ORDER BY BYTES DESC;6. ロック・ブロッキング確認 {#lock}
-- ブロッキング(ロック待ち)の連鎖を確認
SELECT
L1.SID AS ブロックされているSID,
L1.BLOCK AS ブロックしているSID,
S1.USERNAME AS 待機ユーザー,
S2.USERNAME AS ブロックユーザー,
S1.EVENT AS 待機イベント,
S1.SECONDS_IN_WAIT AS 待機秒数
FROM V$LOCK L1
JOIN V$SESSION S1 ON L1.SID = S1.SID
JOIN V$LOCK L2 ON L1.ID1 = L2.ID1 AND L1.ID2 = L2.ID2
JOIN V$SESSION S2 ON L2.SID = S2.SID
WHERE L1.BLOCK = 0
AND L2.BLOCK = 1;7. ログ・リカバリ関連 {#log}
-- オンラインREDOログの状態と切り替え状況
SELECT GROUP#, SEQUENCE#, BYTES/1024/1024 AS MB, MEMBERS, STATUS
FROM V$LOG
ORDER BY GROUP#;
-- ログスイッチの頻度を確認(1時間に何回スイッチするか)
SELECT
TO_CHAR(FIRST_TIME, 'YYYY-MM-DD HH24') AS 時間帯,
COUNT(*) AS スイッチ回数
FROM V$LOG_HISTORY
WHERE FIRST_TIME >= SYSDATE - 1
GROUP BY TO_CHAR(FIRST_TIME, 'YYYY-MM-DD HH24')
ORDER BY 時間帯;8. まとめ:用途別V$ビュー早見表 {#summary}
| 用途 | 使うV$ビュー | 主要な列 |
|---|---|---|
| セッション確認 | V$SESSION | SID, USERNAME, STATUS, SQL_ID |
| 重いSQLを探す | V$SQL | SQL_ID, ELAPSED_TIME, CPU_TIME |
| 待機イベント | V$SESSION, V$SYSTEM_EVENT | EVENT, SECONDS_IN_WAIT |
| ロック確認 | V$LOCK, V$SESSION | BLOCK, ID1, ID2 |
| I/O確認 | V$FILESTAT, V$DATAFILE | PHYRDS, PHYWRTS |
| SGA確認 | V$SGA, V$SGASTAT | NAME, BYTES |
| REDOログ | V$LOG, V$LOG_HISTORY | SEQUENCE#, STATUS |
| アーカイブログ | V$ARCHIVED_LOG | SEQUENCE#, APPLIED |
関連記事:









コメント