【Oracle】V$SQLAREA・V$SQLTEXTとは|SQL本文・実行統計を確認する

Oracleで実行済みSQLを調べるときは、まず V$SQLAREA でSQLの概要と統計を確認し、SQL全文が長くて途中で切れる場合は V$SQLTEXT または V$SQLTEXT_WITH_NEWLINES で分割されたSQL文を復元します。

この記事では、V$SQLAREAV$SQLTEXT の違い、SQL_ID からSQL本文を確認する方法、長文SQLの復元、実行回数・経過時間・読み取り量の見方、権限不足で見えないときの確認ポイントまで、運用で使う形に絞って解説します。

先に結論:一覧と統計は V$SQLAREA、長いSQL本文の復元は V$SQLTEXT、実行計画まで見るなら DBMS_XPLAN.DISPLAY_CURSOR を組み合わせます。
スポンサーリンク

V$SQLAREAとV$SQLTEXTの使い分け早見表

目的 使うビュー 見る主な列
SQLの一覧と実行統計を見たい V$SQLAREA SQL_ID, SQL_TEXT, EXECUTIONS, ELAPSED_TIME
長文SQLを全文復元したい V$SQLTEXT SQL_ID, PIECE, SQL_TEXT
改行を含めてSQLを見たい V$SQLTEXT_WITH_NEWLINES PIECE, SQL_TEXT
実行計画も確認したい DBMS_XPLAN.DISPLAY_CURSOR SQL_ID, CHILD_NUMBER

V$SQLAREA だけでもSQL本文は見えますが、列幅や本文長の都合で途中までしか見えないことがあります。SQL全文が必要なときは、V$SQLTEXTPIECE 順に連結して確認します。

V$SQLAREAとは

V$SQLAREA とは、共有プール上にあるSQLをSQL単位で集約して確認できる動的パフォーマンスビューです。SQL本文の先頭、実行回数、合計経過時間、CPU時間、論理読み取り、物理読み取りなどをまとめて見られます。

「どのSQLが多く実行されているか」「どのSQLが時間を使っているか」「どのSQL_IDを詳しく調べるべきか」を探す入口として使います。ただし、SQL全文の表示や子カーソル単位の詳細確認は、V$SQLV$SQLTEXT と組み合わせるのが実務的です。

V$SQLTEXTとは

V$SQLTEXT とは、SQL本文を分割行として保持する動的パフォーマンスビューです。長いSQLは1行の SQL_TEXT だけでは途中で切れることがあるため、SQL_ID で絞り、PIECE 順に並べて全文を確認します。

SQLの改行も見たい場合は V$SQLTEXT_WITH_NEWLINES を使います。SQL本文を調査資料へ貼る、アプリから発行されたSQLを復元する、実行計画確認前に対象SQLを特定する、といった用途で役立ちます。

V$SQLAREAで実行済みSQLを一覧表示する

まずは最近実行されたSQLを LAST_ACTIVE_TIME の新しい順に確認します。

recent-sql.sql
SELECT sql_id,
       child_number,
       executions,
       ROUND(elapsed_time / 1000000, 2) AS elapsed_sec,
       ROUND(cpu_time / 1000000, 2)     AS cpu_sec,
       buffer_gets,
       disk_reads,
       last_active_time,
       SUBSTR(sql_text, 1, 120) AS sql_text
FROM   v$sqlarea
WHERE  last_active_time IS NOT NULL
ORDER BY last_active_time DESC
FETCH FIRST 20 ROWS ONLY;

ELAPSED_TIMECPU_TIME はマイクロ秒単位です。秒に直すには 1000000 で割ります。遅いSQLの切り分け全体は、遅いSQLを特定する方法も合わせて確認すると流れがつかみやすいです。

Oracle 11gなど FETCH FIRST が使えない環境では、外側で ROWNUM を使います。

recent-sql-11g.sql
SELECT *
FROM (
  SELECT sql_id,
         executions,
         ROUND(elapsed_time / 1000000, 2) AS elapsed_sec,
         last_active_time,
         SUBSTR(sql_text, 1, 120) AS sql_text
  FROM   v$sqlarea
  WHERE  last_active_time IS NOT NULL
  ORDER BY last_active_time DESC
)
WHERE ROWNUM <= 20;

古いバージョンのOracleを扱う現場では、12c以降の FETCH FIRST と 11g以前向けの ROWNUM を使い分けると、手元の環境差で詰まりにくくなります。

SQL_IDを指定してV$SQLAREAを見る

SQL_IDが分かっている場合は、対象を絞って統計を確認します。

SELECT sql_id,
       child_number,
       plan_hash_value,
       executions,
       rows_processed,
       buffer_gets,
       disk_reads,
       ROUND(elapsed_time / 1000000, 2) AS elapsed_sec,
       sql_text
FROM   v$sqlarea
WHERE  sql_id = '対象のSQL_ID';

同じ SQL_ID でも実行計画や環境条件によって子カーソルが分かれることがあります。詳細を見るときは CHILD_NUMBER も一緒に控えておくと、実行計画確認へつなげやすくなります。

V$SQLTEXTで長文SQLを復元する

V$SQLTEXT はSQL本文を複数行に分割して持っています。PIECE 順に並べると、長いSQLを前から順に確認できます。

sqltext-by-piece.sql
SELECT piece,
       sql_text
FROM   v$sqltext
WHERE  sql_id = '対象のSQL_ID'
ORDER BY piece;

SQL*PlusやSQLclでそのまま見れば、分割された本文を順番に追えます。改行付きのSQLを確認したい場合は、V$SQLTEXT_WITH_NEWLINES に切り替えます。

sqltext-with-newlines.sql
SELECT piece,
       sql_text
FROM   v$sqltext_with_newlines
WHERE  sql_id = '対象のSQL_ID'
ORDER BY piece;

LISTAGGでSQL本文を1行に連結する

レポートに貼り付ける目的なら、LISTAGG でSQL本文を1行にまとめると扱いやすくなります。

SELECT sql_id,
       LISTAGG(sql_text, '') WITHIN GROUP (ORDER BY piece) AS full_sql_text
FROM   v$sqltext
WHERE  sql_id = '対象のSQL_ID'
GROUP BY sql_id;

ただし、非常に長いSQLでは LISTAGG の戻り値長制限に当たることがあります。長大なSQLを安全に出力したい場合は、行分割のまま出力するか、CLOB化する方法を検討してください。

LISTAGG の長さ制限が気になる場合は、XMLAGG でCLOB寄りに連結する方法もあります。

sqltext-xmlagg.sql
SELECT sql_id,
       RTRIM(XMLAGG(XMLELEMENT(e, sql_text) ORDER BY piece)
             .EXTRACT('//text()').GETCLOBVAL()) AS full_sql_text
FROM   v$sqltext
WHERE  sql_id = '対象のSQL_ID'
GROUP BY sql_id;

SQL本文を画面で軽く確認するだけなら PIECE 順の表示で十分です。レポート化や別ツールへの貼り付けが必要なときだけ、連結SQLを使うと扱いやすくなります。

実行時間が長いSQLを探す

平均実行時間が長いSQLを探す場合は、ELAPSED_TIME / EXECUTIONS を見ます。EXECUTIONS が0の行を避けるため、NULLIF で割り算を保護します。

SELECT sql_id,
       executions,
       ROUND(elapsed_time / 1000000, 2) AS total_elapsed_sec,
       ROUND((elapsed_time / NULLIF(executions, 0)) / 1000000, 2) AS avg_elapsed_sec,
       buffer_gets,
       disk_reads,
       SUBSTR(sql_text, 1, 120) AS sql_text
FROM   v$sqlarea
WHERE  executions > 0
ORDER BY avg_elapsed_sec DESC
FETCH FIRST 20 ROWS ONLY;

合計時間が大きいSQLと、1回あたりが遅いSQLは別物です。頻繁に実行されるSQLは平均が小さくても合計負荷が大きくなるため、TOTAL_ELAPSED_SECAVG_ELAPSED_SEC の両方を見るのが実務的です。

読み取り量が多いSQLを探す

CPU時間よりもI/Oやバッファ読み取りが問題になっていそうな場合は、BUFFER_GETSDISK_READS で並べ替えます。

SELECT sql_id,
       executions,
       buffer_gets,
       ROUND(buffer_gets / NULLIF(executions, 0), 2) AS buffer_gets_per_exec,
       disk_reads,
       SUBSTR(sql_text, 1, 120) AS sql_text
FROM   v$sqlarea
WHERE  executions > 0
ORDER BY buffer_gets_per_exec DESC
FETCH FIRST 20 ROWS ONLY;

読み取り量が多いSQLは、実行計画や索引の使われ方を確認します。実行計画の読み方は DBMS_XPLAN完全ガイドEXPLAIN PLAN完全ガイド に進むとよいです。

現在実行中のセッションからSQL_IDを拾う

今まさに動いているSQLを追う場合は、V$SESSION から SQL_ID を取得して、V$SQLAREAV$SQLTEXT へつなぎます。

SELECT s.sid,
       s.serial#,
       s.username,
       s.status,
       s.sql_id,
       s.event,
       s.seconds_in_wait
FROM   v$session s
WHERE  s.username IS NOT NULL
AND    s.sql_id IS NOT NULL
ORDER BY s.last_call_et DESC;

セッションやロック調査と組み合わせる場合は、セッションの確認・強制切断方法も関連します。待機イベントを見て原因を切り分けるなら、待機イベント完全ガイドも役立ちます。

V$SQLAREAでよく見る列

意味 見るポイント
SQL_ID SQLを識別するID 実行計画・SQL本文確認のキーにする
CHILD_NUMBER 子カーソル番号 同じSQL_IDで複数計画がある場合に重要
EXECUTIONS 実行回数 平均値を出すときの分母にする
ELAPSED_TIME 合計経過時間 マイクロ秒単位。秒換算して見る
CPU_TIME 合計CPU時間 CPU負荷が高いSQLの候補を見る
BUFFER_GETS 論理読み取り 1回あたりの読み取り量を見る
DISK_READS 物理読み取り I/O負荷の候補を見る
LAST_ACTIVE_TIME 最後にアクティブだった時刻 直近のSQLを探す

権限不足で見えないとき

V$SQLAREAV$SQLTEXT は動的パフォーマンスビューです。参照権限がないユーザーでは、エラーになったり、必要な行が見えなかったりします。

-- 権限例。付与はDBAに依頼してください。
GRANT SELECT_CATALOG_ROLE TO app_user;
-- または必要なビューだけ個別に付与
GRANT SELECT ON v_$sqlarea TO app_user;
GRANT SELECT ON v_$sqltext TO app_user;

権限確認の考え方は、Oracleのユーザ権限を確認する方法で整理しています。運用環境では、必要最小限の権限で参照できるようにDBAと調整してください。

V$SQLAREAだけで判断しない注意点

  • 共有プールから消えたSQLは見えないことがある
  • 統計値はインスタンス起動後やカーソル生成後からの累積である
  • 同じSQL_IDでも子カーソルごとに実行計画が違うことがある
  • 過去の問題調査ではAWRやASHのほうが向いている場合がある

V$SQLAREA は「今メモリ上にあるSQLを見る」ための入口です。長期的な傾向や過去時点の調査では、AWR・ASH・SQL Tuning Advisorも合わせて使います。SQL Tuning Advisor完全ガイドも次の確認先になります。

関連ページ

よくある質問

V$SQLAREAとは何ですか?

V$SQLAREA は、共有プール上のSQLをSQL単位で集約し、実行回数・経過時間・CPU時間・読み取り量などを確認する動的パフォーマンスビューです。

V$SQLTEXTとは何ですか?

V$SQLTEXT は、SQL本文を PIECE ごとの分割行として確認するビューです。長文SQLを全文確認したいときに使います。

V$SQLAREAとV$SQLの違いは何ですか?

V$SQL は子カーソル単位の情報を見やすく、V$SQLAREA はSQL単位で集約された統計を見やすいビューです。詳細に追うときは両方を使います。

V$SQLTEXTは何に使いますか?

長いSQL文を分割行として確認するために使います。SQL_ID で絞り、PIECE 順に並べます。

SQL_TEXTが途中で切れるのはなぜですか?

表示列の長さやビューの列仕様により、全文が見えないことがあります。全文確認には V$SQLTEXTV$SQLTEXT_WITH_NEWLINES を使います。

ELAPSED_TIMEの単位は何ですか?

マイクロ秒です。秒として見たい場合は 1000000 で割ります。

過去に実行されたSQLが見つからないことはありますか?

あります。共有プールから消えたSQLは V$SQLAREA では見えません。過去調査にはAWRやASHを検討します。

本番環境で誰でも見られるビューですか?

通常は権限が必要です。SELECT_CATALOG_ROLE や対象ビューへの個別権限が必要になるため、DBAに確認してください。

まとめ

V$SQLAREA は、実行済みSQLの概要、実行回数、経過時間、読み取り量を確認する入口です。一方で、SQL本文が長い場合は V$SQLTEXTPIECE 順に確認して全文を復元します。

調査の流れとしては、V$SESSIONV$SQLAREASQL_ID を見つけ、V$SQLTEXT で本文を確認し、必要に応じて DBMS_XPLAN.DISPLAY_CURSOR で実行計画へ進む、という順番にすると迷いにくくなります。