web-dev-qa-db-ja.com

Oracle 11.BLOBフィールドを更新しています。 Dbファイルのシーケンシャル読み取りが不適切に遅いですか?

私とOracle(11 Enterprise)スキーマとテーブル

 CREATE TABLE USER.WSP_BUNDLE ( 
    NODE_ID     RAW(16) NOT NULL,
    BUNDLE_DATA BLOB NOT NULL 
    );
CREATE UNIQUE INDEX USER.WSP_BUNDLE_IDX ON USER.WSP_BUNDLE(NODE_ID);

およびそれを操作するサードパーティライブラリ(Java 6、JDBC-最新のjdbcドライバ)。

Oracleプロファイラー(tkprof)は、libがそのようなステートメントを実行する全体の時間の約50%:を示しています。

update WSP_BUNDLE set BUNDLE_DATA = :1 where NODE_ID = :2

TKProfデータ

Plan Hash: 4085453680
update WSP_BUNDLE set BUNDLE_DATA = :1  where NODE_ID = :2 


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse      264      0.00       0.00          0          0          0           0
Execute    400     30.59     382.88     141451    1623163    3233827         400
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total      664     30.59     382.88     141451    1623163    3233827         400

Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 87  

Rows     Row Source Operation
-------  ---------------------------------------------------
      0  UPDATE  WSP_BUNDLE (cr=8753 pr=707 pw=706 time=0 us)
      1   INDEX UNIQUE SCAN WSP_BUNDLE_IDX (cr=3 pr=0 pw=0 time=0 us cost=2 size=104 card=1)(object id 75730)


Elapsed times include waiting on following events:
  Event waited on                             Times   Max. Wait  Total Waited
  ----------------------------------------   Waited  ----------  ------------
  db file sequential read                    141251        5.53        328.04
  direct path write                             402        0.09          0.43
  SQL*Net more data from client              142158        1.04         11.89
  direct path read                              200        0.03          0.07
  Disk file operations I/O                        1        0.00          0.00
  SQL*Net message to client                     400        0.00          0.00
  SQL*Net message from client                   400        0.29          0.50
  log file switch (private strand flush incomplete)
                                                  5        0.05          0.23
  asynch descriptor resize                   139723        7.46          8.57
  buffer busy waits                               2        0.00          0.00
  log file switch (checkpoint incomplete)         3        0.18          0.27
  log file sync                                   2        0.00          0.00

誰かが私に何が起こっているのか説明/ヒントを与えることができますか?なぜ更新がとても遅いのですか?

テーブルWSP_BUNDLEには、約200 + k行が含まれています。同時に、同じスキーマ内に、同様の更新が正しく機能する600 + k行を含むblob(より具体的にはCLOB)を持つ他のテーブルがあります。

2
FoxyBOA

Oracleでは、LOB(BLOBを含む)は次のように格納されます。

  • テーブル内LOB-LOBが3900バイトより小さい場合は、テーブル行内に格納できます。 DISABLE STORAGE IN ROWを指定しない限り、デフォルトでこれは有効になっています。
  • 通常のLOB-テーブルの外側の別のセグメントに格納され、別のテーブルスペースに配置することもできます。これらのために:
    • 最小のCHUNKバイトが割り当てられ、完全にREDOログに記録されます(LOBに1バイトしかない場合でも)
    • lOB列の背後に内部中間インデックスがあります。これは更新について論争を起こし、実際にそれらをシリアル化する可​​能性があります。
    • アクセスはマルチレベルであるため、比較的低速です
    • nOCACHEオプションを使用すると、ウェイターは「ダイレクトパス読み取り」になります-デフォルト
    • cACHEオプションを使用すると、ウェイターは「dbファイルの順次読み取り」になります。
      • ここで、CACHE_SIZE_THRESHOLDは考慮されないため、大きなLOBはキャッシュを浪費する可能性があります

したがって、LOBが4 kBより大きい場合、LOBは比較的遅くなります。 そしてこれは単にあなたの場合かもしれません。サイズを調べてみます。

USER_LOBS(またはDBA_LOBS)を調べて、「良い」LOB列と「遅い」LOB列の定義がどのように異なるかを確認します。

MetalinkノートID66431.1はこれを説明しており、アクセスできる場合は興味があるかもしれません。

[〜#〜] update [〜#〜]:一見説明できないほどの大量の「dbファイルシーケンシャル読み取り」に魅了され、少しやりました検索の結果、 大量のDELETEの後にlobインデックスで奇妙なことが起こる可能性がある であることがわかりました。推測ですが、あなたの場合と非常によく似ています。もしそうなら、私は lob列を完全に再構築する 。 (lob列を移動すると、lobインデックスも再構築される可能性があります-よくわかりません)。

3
kubanczyk