- ベストアンサー
TruncateしたテーブルへのInsertの遅さが気になる
こんにちわ。 日次処理として、毎晩ワークテーブルをTruncateしてInsertしなおすというプログラムを数年前に作りました。 このプログラムはVB6、ADO、OLE DBプロバイダはOracleのものを使っています。 他のテーブルからSelectし、それを元に1レコードずつInsert文を作っては実行を繰り返す処理で正直遅いのですが、このプログラムの動作が不思議です。 日々数十万件のInsertを行っているのですが、ログを確認すると最初の2万件のInsertには40分掛かるわりに最後の2万件は5分で終わるのです。 今まで処理時間の遅さが問題になることもなく、バグもなく動いているしであまり気にしていなかったのですが、最近なぜこのような動きになるのか気になってきました。 最初も最後もSelect結果に偏りはなく、Insert文を作る処理に掛かっている時間は同じようなものかと思います。 とすると、遅いのはDBでのInsert処理か?と考えています。 レコード件数が少ないうちのInsertには時間が掛かるものなんでしょうか? だとするとそれはなぜ? 別に処理速度を速くしたいとか言うことではなく、なぜInsertの処理時間にこれほどの差が生じるのかが気になっています。 なおこのテーブルは主キー以外に索引を作っていません。 Insert文を作る際の元になるデータは論理的な単位ごとにSelectします。1回がだいたい数十件ぐらいです。 またその論理的な単位の分のデータをInsertしおわるごとにcommitしています(数十件ごとのcommitになります)。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
テーブルの拡張が起きているんではないでしょうか。 storageサイズの指定を確認してみてください。 もしそれなら最終的に拡張されるサイズくらいの大きさでテーブル切り直しておくといいです。
その他の回答 (1)
- 3rd_001
- ベストアンサー率66% (115/174)
テーブルの動的拡張では? テーブルの初期時のExtentの数と最大データ時のExtent数の違いが気になります。 データを入れるたびに領域が足りなくExtentが割り当てられつづける。そして、2万件Insertした時点で増分サイズの設定で全件収まるだけのサイズに拡張されているような気がします。 Insert時にdba_extentsを監視してみると良いでしょう。 あと、該当表領域の管理方式がどちらなのかも気になります。 ・ディクショナリ管理表領域 ・ローカル管理表領域 ディクショナリ管理だとExtentの割り当ての負荷が高いので、 当てはまる可能性は高いです。 Storageを見直すか、Truncateを「REUSE STORAGE」付きで実行してExtentの開放を行わないのもひとつの手です。
お礼
ご回答ありがとうございました。 Extentの分かりやすい解説、助かります。 ちなみに表領域はLocalですが、それでもデータ量に対してStorageのInitial設定が小さすぎるのかも。 「Truncate ~ Reuse Storage」という方法もあるんですね~。
お礼
ご回答ありがとうございました。 現在StorageはInitial 64K、Next 0Kという設定になっていました。 このテーブルに割り当てられているExtentを確認したら、実にExtent総数97、サイズ合計216MBという状態でした。 Extentのサイズは最初のうちは64K、そのうち1M、やがて8Mと増えていくようで、これだと確かにレコード件数が増えていくとInsert処理の速度が上がっていくことの説明がつきます。 テスト環境が構築でき次第、StorageのInitialを大きく設定して一度試してみようと思います。