【Oracle】V$SQLビューの使い方|実行済みSQLの確認・パフォーマンス分析まで完全解説

「さっきどんなSQLが実行されたか確認したい」「重いSQLを特定してチューニングしたい」――Oracleの運用でこのような場面は頻繁に発生します。そんなときに役立つのが V$SQLビュー です。

V$SQLはOracle共有プール上にキャッシュされたSQLの情報を保持するビューで、実行済みSQLの検索・実行統計の確認・パフォーマンス分析まで幅広く活用できます。この記事では、基本的な使い方から実務で使えるクエリパターンまで体系的に解説します。

この記事で学べること

  • V$SQLビューの概要とV$SQLAREA・V$SQLTEXTとの違い
  • 直前に発行されたSQLをLAST_ACTIVE_TIMEで取得する方法
  • 特定ユーザー・スキーマ・キーワードでSQLを絞り込む方法
  • 実行回数・CPU時間・実行時間でランキングするTop SQLクエリ
  • V$SESSIONと結合して現在実行中のSQLを確認する方法
  • V$SQLの主要列の意味と実務での活用ポイント
スポンサーリンク

V$SQLビューとは

V$SQLはOracle Databaseの共有プール(Shared Pool)にキャッシュされたSQLカーソルの情報を格納するビューです。SQLが実行されると共有プール上にキャッシュされ、V$SQLから参照できるようになります。

重要:V$SQLは動的パフォーマンスビューであり、データベース再起動・共有プールのフラッシュ(ALTER SYSTEM FLUSH SHARED_POOL)・キャッシュ容量不足によるエージングアウトでデータが消える点に注意してください。永続的な履歴が必要な場合はAWR(DBA_HIST_SQLSTAT)を使用します。

V$SQL・V$SQLAREA・V$SQLTEXTの違い

ビュー 内容 主な用途
V$SQL 子カーソル単位の統計(バインド変数値の違いで分かれる) 詳細な実行統計・個別SQL分析
V$SQLAREA 同一SQL_IDの子カーソルを集約した統計 SQL単位の集計・Top SQL
V$SQLTEXT SQLテキストが64文字ごとに分割されて格納 4000文字を超える長いSQLの全文取得

ポイント:通常の調査では V$SQL を使えば十分です。4000文字を超える長いSQLを確認したい場合は V$SQLTEXT、複数の子カーソルをまとめて分析したい場合は V$SQLAREA を使いましょう。

直前に発行されたSQLを確認する

最後に実行されたSQL(全ユーザー)

LAST_ACTIVE_TIME(最後にアクティブだった時刻)が最大のレコードを取得することで、直前に実行されたSQLを確認できます。

SQL – 直前に実行されたSQLを取得
SELECT  sql_id,  SUBSTR(sql_text, 1, 200) AS sql_text,  last_active_time,  parsing_user_id,  executions,  elapsed_time / 1000000 AS elapsed_secFROM v$sqlWHERE last_active_time = (SELECT MAX(last_active_time) FROM v$sql)ORDER BY last_active_time DESC;

直近N件のSQLを確認する

最後の1件だけでなく、直近の複数件を確認したい場合は ROWNUM で件数を絞ります。

SQL – 直近20件を確認
SELECT *FROM (  SELECT    sql_id,    SUBSTR(sql_text, 1, 300) AS sql_text,    last_active_time,    executions,    ROUND(elapsed_time / 1000000, 3) AS elapsed_sec,    parsing_schema_name  FROM v$sql  ORDER BY last_active_time DESC)WHERE ROWNUM <= 20;

実務で使えるクエリパターン

特定ユーザーが実行したSQLを確認する

PARSING_SCHEMA_NAME(解析時のスキーマ名)で絞り込めます。

SQL – スキーマ名で絞り込み
SELECT  sql_id,  parsing_schema_name,  SUBSTR(sql_text, 1, 300) AS sql_text,  last_active_time,  executionsFROM v$sqlWHERE parsing_schema_name = 'SCOTT'  -- スキーマ名(大文字)ORDER BY last_active_time DESC;

特定のテーブル・キーワードを含むSQLを検索する

SQL_TEXTに対して LIKE 検索で絞り込めます。ただし SQL_TEXT は先頭1000文字のみ格納されるため、全文検索には V$SQLTEXT と組み合わせます。

SQL – SQLテキストをキーワード検索
-- 特定テーブル名を含むSQLを検索SELECT  sql_id,  parsing_schema_name,  SUBSTR(sql_text, 1, 300) AS sql_text,  last_active_time,  executions,  ROUND(elapsed_time / 1000000, 3) AS elapsed_secFROM v$sqlWHERE UPPER(sql_text) LIKE '%ORDERS%'  -- テーブル名(大文字化して検索)  AND UPPER(sql_text) NOT LIKE '%V$SQL%'  -- V$SQL自体を除外ORDER BY last_active_time DESC;

指定時間帯に実行されたSQLを確認する

SQL – 時間帯で絞り込み
SELECT  sql_id,  parsing_schema_name,  SUBSTR(sql_text, 1, 300) AS sql_text,  last_active_timeFROM v$sqlWHERE last_active_time  BETWEEN TO_DATE('2026-03-12 01:00:00', 'YYYY-MM-DD HH24:MI:SS')  AND     TO_DATE('2026-03-12 02:00:00', 'YYYY-MM-DD HH24:MI:SS')ORDER BY last_active_time DESC;

パフォーマンス分析:Top SQLを特定する

実行時間が長いSQLランキング(Top 10)

チューニング対象を探すときは ELAPSED_TIME(合計実行時間)や CPU_TIME でソートします。実行回数で割った「1回あたりの平均時間」も合わせて確認すると効果的です。

SQL – 実行時間Top 10
SELECT *FROM (  SELECT    sql_id,    parsing_schema_name,    SUBSTR(sql_text, 1, 200) AS sql_text,    executions,    ROUND(elapsed_time / 1000000, 3) AS total_elapsed_sec,    CASE WHEN executions > 0      THEN ROUND(elapsed_time / executions / 1000000, 3)      ELSE 0    END AS avg_elapsed_sec,    ROUND(cpu_time / 1000000, 3) AS total_cpu_sec,    buffer_gets,    disk_reads  FROM v$sql  WHERE executions > 0  ORDER BY elapsed_time DESC)WHERE ROWNUM <= 10;

I/O負荷が高いSQLランキング(BUFFER_GETS / DISK_READS)

SQL – 物理読み取りが多いSQLTop 10
SELECT *FROM (  SELECT    sql_id,    parsing_schema_name,    SUBSTR(sql_text, 1, 200) AS sql_text,    executions,    disk_reads,    buffer_gets,    -- 1実行あたりの物理読み取り数    CASE WHEN executions > 0      THEN ROUND(disk_reads / executions)      ELSE 0    END AS disk_reads_per_exec  FROM v$sql  WHERE executions > 0  ORDER BY disk_reads DESC)WHERE ROWNUM <= 10;

実行回数が多いSQLランキング

頻繁に実行されるSQLはチューニング効果が大きいため、実行回数でランキングするのも有効です。

SQL – 実行回数Top 10
SELECT *FROM (  SELECT    sql_id,    parsing_schema_name,    SUBSTR(sql_text, 1, 200) AS sql_text,    executions,    ROUND(elapsed_time / executions / 1000000, 4) AS avg_elapsed_sec,    ROUND(buffer_gets / executions) AS avg_buffer_gets  FROM v$sql  WHERE executions > 10  ORDER BY executions DESC)WHERE ROWNUM <= 10;

V$SESSIONと結合:現在実行中のSQLを確認する

V$SQLだけでは「今まさに実行中のSQL」を特定できません。V$SESSIONと結合することで、現在アクティブなセッションが実行しているSQLをリアルタイムで確認できます。

SQL – 現在実行中のSQL一覧
SELECT  s.sid,  s.serial#,  s.username,  s.status,  s.machine,  s.program,  SUBSTR(q.sql_text, 1, 300) AS sql_text,  q.sql_id,  ROUND(q.elapsed_time / 1000000, 3) AS elapsed_secFROM v$session sJOIN  v$sql    q ON s.sql_id = q.sql_id                AND s.sql_child_number = q.child_numberWHERE s.status = 'ACTIVE'  AND s.type   = 'USER'ORDER BY q.elapsed_time DESC;

ポイント:結合条件に sql_child_number を必ず含めてください。V$SQLは同一SQL_IDで複数の子カーソルを持つため、sql_id のみで結合すると行が重複します。

V$SQLの主要列一覧

列名 データ型 説明
SQL_ID VARCHAR2(13) SQLのユニーク識別子。バインド変数が異なっても同じ値になる
SQL_TEXT VARCHAR2(1000) SQLテキスト(先頭1000文字)
LAST_ACTIVE_TIME DATE 最後にアクティブだった時刻(最後の実行時刻の目安)
EXECUTIONS NUMBER このカーソルが共有プールにキャッシュされてからの実行回数
ELAPSED_TIME NUMBER 合計実行時間(マイクロ秒)。÷1000000で秒換算
CPU_TIME NUMBER 使用したCPU時間の合計(マイクロ秒)
BUFFER_GETS NUMBER バッファキャッシュからの論理読み取りブロック数(合計)
DISK_READS NUMBER ディスクからの物理読み取りブロック数(合計)。多いとI/Oボトルネックの可能性
PARSE_CALLS NUMBER パース呼び出し回数。多いとハードパースが頻発している可能性
ROWS_PROCESSED NUMBER 処理(返却)した行数の合計
PARSING_SCHEMA_NAME VARCHAR2(128) SQLをパースしたスキーマ名
CHILD_NUMBER NUMBER 子カーソル番号(V$SESSIONとの結合に使用)

V$SQL使用上の注意点

注意事項 詳細
データが消える DB再起動・共有プールフラッシュ・容量不足によるエージングアウトでキャッシュが消える。過去のSQLを永続的に保持したい場合はAWR(DBA_HIST_SQLSTAT)を使う
SQL_TEXTは1000文字まで 1000文字を超えるSQLは切り捨てられる。全文は V$SQLTEXT(PIECE列を ORDER BY PIECE で結合)から取得する
SELECT権限が必要 V$SQLはデフォルトでSYS・DBAロールのみ参照可能。一般ユーザーには GRANT SELECT ON V_$SQL TO ユーザー; で権限を付与する
自身のSQLが混入する V$SQLを検索するSQLも V$SQL に記録される。WHERE UPPER(sql_text) NOT LIKE '%V$SQL%' で除外する

まとめ

V$SQLビューはOracle運用・チューニングの現場で欠かせないツールです。各クエリの用途を整理しておきましょう。

やりたいこと 使うクエリ・列
直前に実行されたSQLを確認 WHERE last_active_time = (SELECT MAX...)
特定ユーザーのSQLを確認 WHERE parsing_schema_name = 'USER'
テーブル名でSQLを検索 WHERE UPPER(sql_text) LIKE '%TABLE%'
重いSQLをランキング ORDER BY elapsed_time DESC + ROWNUM
I/O負荷の高いSQLを特定 ORDER BY disk_reads DESC
現在実行中のSQLをリアルタイム確認 V$SESSION JOIN V$SQL + WHERE status='ACTIVE'

V$SQLは共有プールのキャッシュに依存するため、過去の長期履歴はAWRスナップショット(DBA_HIST_SQLSTAT)で補完するのが実務での定石です。両方を使い分けて、効率的なSQL調査とパフォーマンスチューニングに役立ててください。