OracleDatabase
2019-10-08

多数のInsertをしたいが、遅い

enq: HW - contentionが高騰

複数のセッションから同時に更新を書けた場合に発生する場合がある。
HighWaterロック待ちで、実際にSQLを実行する準備段階で時間を食っている。
解決には、HWロックを極力減らす、つまり①FREELISTSを大きく取る10g以降は自動セグメントスペース管理が有効になっており、FREELISTSは無視されるので意味なし②エクステントサイズ均一の多きさで大きめに取ることが有効。
(もしテーブルロックが不要な処理なのにテーブルロックが作用してしまっている場合には、テーブルロックを無効化することも有効)

FREELISTSの変更/変更した状態でCREATE TABLE

#sh(sql){{

/* 既存のテーブルの変更:表領域を移動させる操作のついでに属性を変更させる */
ALTER TABLE ${TABLE_NAME} MOVE TABLESPACE USERS STORAGE ( FREELISTS ${MUCH_LARGE_NUMBER} )
ALTER TABLE ${TABLE_NAME} MOVE TABLESPACE ${NEW_TABLESPACE} STORAGE ( FREELISTS ${MUCH_LARGE_NUMBER} ) /* 必要に応じてINDEX再作成 */


/* 新規作成の場合 */
CREATE TABLE ( ${TABLE_DEFINITION} ) STORAGE ( FREELISTS ${MUCH_LARGE_NUMBER} )

}}

エクステントサイズの変更/変更した状態でCREATE TABLE

#sh(sql){{

/* エクステントサイズは表領域単位なので、エクステントサイズを大きくとった表領域をまずは作成 */
CRAEATE TABLESPACE ${NEW_TABLESPACE} SIZE ${BASE_SIZE} AUTOEXTEND ON NEXT ${EXTENT_SIZE} MAXSIZE UNLIMITED;

/* 新しい表領域にテーブルを移動 */
ALTER TABLE ${TABLE} MOVE TABLESPACE ${NEW_TABLESPACE};

/* 場合によってはデフォルトテーブルスペースを変更しておく */
ALTER USER ${USERNAME} DEFAULT TABLESPACE ${NEW_TABLESPACE};

}}

ただし、ALTER TABLEでテーブルを移動した場合インデックスが有効に作用しなくなるので、後述のインデックスの再作成を行わないと
著しくパフォーマンスが低下するので注意。

テーブルロックの無効化

#sh(sql){{

/* 対象の確認 */
SELECT TABLE_NAME FROM USER_TABLES WHERE TABLE_LOCK = 'ENABLED';

/* 無効化 */
ALTER TABLE ${TARGET_TABLE} DISABLE TABLE LOCK;

}}

CPUが高騰

通常、CPU(ユーザ空間の)使用率が高いのは理想的な状態であるが、I/O性能やCPU性能からして本来出るはずのパフォーマンスが出ていない場合には、インデックスが正しく作用していないことが疑われる。

ALTER TABLEした直後の場合

テーブルスペースを移動すると無効化されてしまうので、再作成を行う。

#sh(sql){{

/* インデックス名を確認 */
SELECT INDEX_NAME, TABLE_NAME FROM USER_INDEXES;

/* インデックスの再構築 */
ALTER INDEX ${INDEX_NAME} REBUID;

}}

参考:

プレースホルダーを使わないでINSERTしている場合

プレースホルダーを使わずにプログラム側でSQL文を組み立てて発行している場合には、Database側でSQLの解析を都度行っているがために余分なCPU処理を使ってしまっている。
安全対策の目的以外にもプレースホルダーにはSQLの解析結果の使い回しによる速度向上効果があるので、プレースホルダーを使って発行するようプログラムを改良する。


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2019-10-14 (月) 05:52:41