28

私は、週単位で標準的なレポート セットを生成するカスタム ビルドの社内アプリケーションを使用しています。私はアプリケーションのソース コードにアクセスできません。また、誰もが、Oracle データベース スキーマに関するドキュメントは入手できないと言っています。(ああ!)

既存のレポートのバリエーションの仕様を定義するように依頼されました (たとえば、追加のフィルターを適用してデータ セットを制限し、レイアウトを少し変更します)。これは原理的には簡単に思えますが、既存のドキュメントがなければ難しいものです。

レポートはデータベースに対してのみクエリを実行するため、ログが役に立たないことは理解しています。実際にはデータベースの値を挿入、削除、または更新しないため、ログに記録するものはありません (これは正しいですか?)。

私の質問は次のとおりです。レポート生成ジョブがまだ実行されている間に実行されている実際の SQL ステートメントを確認するために使用できるツールまたはユーティリティ (Oracle またはその他) はありますか? 既存のレポートを作成するために実際にどのテーブルがアクセスされているかがわかれば、スキーマを調査し、自分のレポートに使用する正しい SQL を決定するための非常に良い出発点になると思います。

4

6 に答える 6

24

データ ディクショナリ側では、 Schema Spyなどに使用できる多くのツールがあります。

どのクエリが実行されているかを調べるには、ビュー sys.v_$sql と sys.v_$sqltext を見てください。sys.all_users へのアクセスも必要になります。

パラメータを使用するクエリは、次のようなエントリで一度表示されることに注意してください。

and TABLETYPE=’:b16’

次のように複数回表示されないものもあります。

and TABLETYPE=’MT’

実際のこれらのテーブルの例は、上位 20 の diskread ホグを見つける次の SQL です。WHERE rownum <= 20を削除し、おそらくORDER BY moduleを追加することでこれを変更できます。多くの場合、このモジュールはクエリを実行しているソフトウェアに関するおかしな手がかりを提供します (例: "TOAD 9.0.1.8"、"JDBC Thin Client"、"runcbl@somebox (TNS V1-V3)" など)。

SELECT 
 module, 
 sql_text, 
 username, 
 disk_reads_per_exec, 
 buffer_gets, 
 disk_reads, 
 parse_calls, 
 sorts, 
 executions, 
 rows_processed, 
 hit_ratio, 
 first_load_time, 
 sharable_mem, 
 persistent_mem, 
 runtime_mem, 
 cpu_time, 
 elapsed_time, 
 address, 
 hash_value 
FROM 
  (SELECT
   module, 
   sql_text , 
   u.username , 
   round((s.disk_reads/decode(s.executions,0,1, s.executions)),2)  disk_reads_per_exec, 
   s.disk_reads , 
   s.buffer_gets , 
   s.parse_calls , 
   s.sorts , 
   s.executions , 
   s.rows_processed , 
   100 - round(100 *  s.disk_reads/greatest(s.buffer_gets,1),2) hit_ratio, 
   s.first_load_time , 
   sharable_mem , 
   persistent_mem , 
   runtime_mem, 
   cpu_time, 
   elapsed_time, 
   address, 
   hash_value 
  FROM
   sys.v_$sql s, 
   sys.all_users u 
  WHERE
   s.parsing_user_id=u.user_id 
   and UPPER(u.username) not in ('SYS','SYSTEM') 
  ORDER BY
   4 desc) 
WHERE
 rownum <= 20;

クエリが長い場合は、v_$sqltext をクエリする必要があることに注意してください。これにより、クエリ全体が保存されます。ADDRESS と HASH_VALUE を調べて、すべてのピースを取得する必要があります。例えば:

SELECT
 *
FROM
 sys.v_$sqltext
WHERE
 address = 'C0000000372B3C28'
 and hash_value = '1272580459'
ORDER BY 
 address, hash_value, command_type, piece
;
于 2008-09-11T06:45:01.540 に答える
8

短い回答で申し訳ありませんが、遅くなりました。Google「オラクル イベント 10046 SQL トレース」。v$sql からどの SQL がどのセッションに属しているかを特定するのは、それが共有 SQL で複数のユーザーによって使用されている場合は容易ではないため、個々のセッションをトレースするのが最善です。

Oracle DBA の友人に感銘を与えたい場合は、イベント 10046 で Oracle トレースを設定する方法、待機イベントの意味を解釈する方法、および上位の CPU 消費者を見つける方法を学んでください。

Quest には、クライアント側から送信された SQL をキャプチャできる無料の製品がありましたが、お使いの製品/バージョンの Oracle で動作するかどうかはわかりません。これについては、Google の「quest oracle sql monitor」を参照してください。

おやすみなさい。

于 2008-09-11T06:59:55.793 に答える
3

V$SQLAREAテーブルには、探しているものが含まれていると思います (列SQL_TEXTおよびSQL_FULLTEXT を参照)。

于 2008-09-11T06:44:44.397 に答える
2

ええ、それは間違いなく可能です。v$sql ビューにはその情報が含まれています。このコードのようなものは、正しい方向を示しているはずです。私はその特定のコードを自分で試したことはありません。現在、Oracle DB の近くにはありません。

[編集] すでに他の2つの回答をくそー。次回はもっと速く入力する必要があります;-)

于 2008-09-11T06:46:04.720 に答える
1

-- 私は、asktom から盗んだ概念といくつかのコードを使用して、このようなものを使用しています。
-- 改善のための提案は大歓迎です

WITH
sess AS
(
SELECT *
FROM V$SESSION
WHERE USERNAME =
SIDによるユーザーの順序
)
SELECT si.SID,
si.LOCKWAIT,
si.OSUSER,
si.PROGRAM,
si.LOGON_TIME,
si.STATUS,
(
SELECT ROUND(USED_UBLK*8 /1024,1)
FROM V$TRANSACTION,
sess
WHERE sess.TADDR = V$TRANSACTION.ADDR
AND sess.SID = si.SID

) rollback_remaining,

(
SELECT (MAX(DECODE(PIECE, 0,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 1,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 2,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 3,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 4,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 5,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 6,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 7,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 8,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 9,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 10,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 11,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 12,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 13,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 14,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 15,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 16,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 17,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 18,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 19,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 20,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 21,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 22,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 23,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 24,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 25,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 26,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 27,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 28,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 29,SQL_TEXT,NULL)))
FROM V$SQLTEXT_WITH_NEWLINES
WHERE ADDRESS = SI.SQL_ADDRESS AND
PIECE < 30
) SQL_TEXT
FROM sess si;

于 2008-09-16T17:00:57.883 に答える
0

私はJavaアプリケーションで同様の問題を抱えていました。すべての出力がログ ファイルに送信されるように、Oracle ドライバーの周りに JDBC ドライバー ラッパーを作成しました。

于 2008-09-16T14:51:45.197 に答える