web-dev-qa-db-ja.com

Oracle一時表領域を使用しているプロセス/クエリを検出します

Oracle FAQは、一時表スペースを次のように定義します。

一時表領域は、データベースのソート操作およびグローバル一時表の保管のためのスペースを管理するために使用されます。たとえば、2つの大きなテーブルを結合し、Oracleがメモリ内でソートを実行できない場合、ソート操作を実行するためのスペースが一時表領域に割り当てられます。

それは素晴らしいことですが、スペースを正確に使用しているものについての詳細が必要です。アプリケーション設計の癖のため、ほとんどのクエリは何らかの並べ替えを行うため、クライアントの実行可能ファイル、ターゲットテーブル、またはSQLステートメントに絞り込む必要があります。

基本的に、私はこれ(かなり大きなアプリケーション)の何が悪いのかをより正確に教えてくれる手がかりを探しています。 「ソート」よりも正確である限り、あらゆる種類の手がかりが役立つ可能性があります。

10
Simon Gibbs

すでにどの情報を渡さなければならないかは正確にはわかりませんが、次のクエリを使用すると、現在どのプログラム/ユーザー/セッションなどが一時スペースを使用しているかがわかります。

SELECT   b.TABLESPACE
       , b.segfile#
       , b.segblk#
       , ROUND (  (  ( b.blocks * p.VALUE ) / 1024 / 1024 ), 2 ) size_mb
       , a.SID
       , a.serial#
       , a.username
       , a.osuser
       , a.program
       , a.status
    FROM v$session a
       , v$sort_usage b
       , v$process c
       , v$parameter p
   WHERE p.NAME = 'db_block_size'
     AND a.saddr = b.session_addr
     AND a.paddr = c.addr
ORDER BY b.TABLESPACE
       , b.segfile#
       , b.segblk#
       , b.blocks;

どのセッションが損傷を与えているかを見つけたら、実行中のSQLを確認してください。そうすれば、正しい方向に進むはずです。

16
Michael OShea

経験則として、1秒以上かかるほとんどすべてのクエリは、おそらく何らかのTEMPスペースを使用します。これらは、ORDER BYを含むクエリだけでなく、次のことも含みます。

  1. GROUP BY(10.2より前のSORTGROUPBYおよび10.2以降のHASHGROUPBY)
  2. HASHJOINまたはMERGEJOIN
  3. グローバル一時テーブル(明らかに)
  4. インデックスの再構築

場合によっては、一時表領域の使用済み領域がOracleによって解放されないことがあるため(バグ/癖)、表領域からファイルを手動で削除し、ファイルシステムから削除して、別のファイルを作成する必要があります。

マイケル・オシェイの答えに感謝します、

ただし、Oracle RACの複数のインスタンスがある場合は、これが必要になります...

SELECT   b.TABLESPACE
       , b.segfile#
       , b.segblk#
       , ROUND (  (  ( b.blocks * p.VALUE ) / 1024 / 1024 ), 2 ) size_mb
       , a.inst_ID
       , a.SID
       , a.serial#
       , a.username
       , a.osuser
       , a.program
       , a.status
    FROM gv$session a
       , gv$sort_usage b
       , gv$process c
       , gv$parameter p
   WHERE p.NAME = 'db_block_size'
     AND a.saddr = b.session_addr
     AND a.paddr = c.addr
     -- AND b.TABLESPACE='TEMP2'
ORDER BY a.inst_ID , b.TABLESPACE
       , b.segfile#
       , b.segblk#
       , b.blocks;

そしてこれはkillステートメントを生成するためのスクリプトです:どのセッションを強制終了するかを確認してください...

SELECT  b.TABLESPACE, a.username , a.osuser , a.program , a.status ,
       'ALTER SYSTEM KILL SESSION '''||a.SID||','||a.SERIAL#||',@'||a.inst_ID||''' IMMEDIATE;'
    FROM gv$session a
       , gv$sort_usage b
       , gv$process c
       , gv$parameter p
   WHERE p.NAME = 'db_block_size'
     AND a.saddr = b.session_addr
     AND a.paddr = c.addr
     -- AND b.TABLESPACE='TEMP'
ORDER BY a.inst_ID , b.TABLESPACE
       , b.segfile#
       , b.segblk#
       , b.blocks;
3
Najee Ghanim