プログラムの速度改善の相談です。

vb.netでテキストファイルを解析してからOracle(10g)に登録するプログラムを作成しています。
接続にはODP.netでOracleDataAdapterのFillメソッドを使ってます。
動きには問題ないのですが時間がかかります。
大体何十万行数十MBほどのテキストファイルを解析し、数千件ぐらいのデータにしてからそれを10あまりのテーブルに登録してます。
こういう場合、一個一個の処理の速さは早いためチューニングにも限界があるような気がします。
このようにInsertが多数発生する場合に何か速度改善の方法はないでしょうか?
事情によりvb.netでの開発を辞めるとかテキストファイルのフォーマットを変えるなんていうあまりに抜本的な変更は出来ません。

回答の条件
  • 1人2回まで
  • 登録:
  • 終了:2007/06/13 08:58:15
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:wm5775 No.2

回答回数351ベストアンサー獲得回数4

ポイント40pt

こんにちは。

わたしも1番さんと同じで、データベースのもつダイレクトローディングの機能を使用するのが良いと思います。

Oracleはあまり知りませんが、すこし調べたら2通りくらいのダイレクトローディングの機能があるようで、このあたりはおそらくInsert文を使うのではなく、ダイレクトにDBの物理記憶領域に書き込みに行くと思うのでInsert文によるオーバーヘッドは回避できるのではないでしょうか?

ODP.netについても良くわかりませんが、おそらくその手のデータベースラッパーはいちいちInsertやUpdate、Commitを乱発するでしょうし、Wrapperのオーバーヘッドがバカにならないのだと思います。

すでに、


何十万行数十MBほどのテキストファイルを解析し、数千件ぐらいのデータにしてからそれを10あまりのテーブルに登録してます。

とあるので、安物DBならまだしも、数千件程度のInsertで遅いと感じるのがちょっと異常な感じがします。ローディングすべきデータの処理がすでに済んでいるわけですから、わざわざODP.netを介する必要はないんではないでしょうか?(というか、今後もそのODP.netのコードを保守したり、バグに引きずられるコストもばかになりません。)

#SQL*Loaderによるパラレルダイレクトパスであれば、平行してデータのロードができるようですので、10のテーブルについての尾ロードを一気に発行しても処理できるのではないでしょうか?

Oracle Data PumpとOracle SQL*Loader

http://otn.oracle.co.jp/products/database/utilities/index.html

Data Pump ImportはオリジナルImportの15~45倍です。

Oracle SQL*Loader

http://otndnld.oracle.co.jp/products/database/oracle10g/utility/...

ダイレクト・パスによるロード

ダイレクト・パスによるロードは、メモリー内にデータ・ブロックを作成し、現在ロード中の表に割り当てられたエクステントに直接保存します。ダイレクト・パスによるロードは、フィールド仕様を使用して、Oracleデータ・ブロック全体を作成し、Oracleデータ・ファイルに直接書き込みます。この場合、通常のデータ処理は無視されます。 ダイレクト・パスによるロードは、従来型ロードと比較して高速ですが、多少制限があります。

パラレル・ダイレクト・パスによるロードは、複数のパスによるロード・セッションが可能なため、同じデータ・セグメントを同時にロードできます。 パラレル・ダイレクト・パスは、ダイレクト・パスと比較して制限があります。

素人なのにすみません。

#それこそ、抜本的な改革はできないといわれているのに開発環境を根底から覆すような提案になってしまいました。

その他の回答1件)

id:lizy No.1

回答回数45ベストアンサー獲得回数14

ポイント40pt

ちょっと前に同じような質問がありました。

question:1180856737

テキストファイルを解析・変換しておいて、それをOracleの機能を用いてインポートする方法が考えられます(Oracleには詳しくありませんが、おそらくそういう機能が存在すると思います)

あとはindexが多く設定されている場合、insert前に取り除くなりしておいて完了してから再度設定しなおすのも効果があるかもしれません。

そのほかVB.NETのプログラムで、insert1回ごとにcommitするような作りになっていないかを確認してはいかがでしょうか(おそらくすでに確認済みだとは思いますが)

id:wm5775 No.2

回答回数351ベストアンサー獲得回数4ここでベストアンサー

ポイント40pt

こんにちは。

わたしも1番さんと同じで、データベースのもつダイレクトローディングの機能を使用するのが良いと思います。

Oracleはあまり知りませんが、すこし調べたら2通りくらいのダイレクトローディングの機能があるようで、このあたりはおそらくInsert文を使うのではなく、ダイレクトにDBの物理記憶領域に書き込みに行くと思うのでInsert文によるオーバーヘッドは回避できるのではないでしょうか?

ODP.netについても良くわかりませんが、おそらくその手のデータベースラッパーはいちいちInsertやUpdate、Commitを乱発するでしょうし、Wrapperのオーバーヘッドがバカにならないのだと思います。

すでに、


何十万行数十MBほどのテキストファイルを解析し、数千件ぐらいのデータにしてからそれを10あまりのテーブルに登録してます。

とあるので、安物DBならまだしも、数千件程度のInsertで遅いと感じるのがちょっと異常な感じがします。ローディングすべきデータの処理がすでに済んでいるわけですから、わざわざODP.netを介する必要はないんではないでしょうか?(というか、今後もそのODP.netのコードを保守したり、バグに引きずられるコストもばかになりません。)

#SQL*Loaderによるパラレルダイレクトパスであれば、平行してデータのロードができるようですので、10のテーブルについての尾ロードを一気に発行しても処理できるのではないでしょうか?

Oracle Data PumpとOracle SQL*Loader

http://otn.oracle.co.jp/products/database/utilities/index.html

Data Pump ImportはオリジナルImportの15~45倍です。

Oracle SQL*Loader

http://otndnld.oracle.co.jp/products/database/oracle10g/utility/...

ダイレクト・パスによるロード

ダイレクト・パスによるロードは、メモリー内にデータ・ブロックを作成し、現在ロード中の表に割り当てられたエクステントに直接保存します。ダイレクト・パスによるロードは、フィールド仕様を使用して、Oracleデータ・ブロック全体を作成し、Oracleデータ・ファイルに直接書き込みます。この場合、通常のデータ処理は無視されます。 ダイレクト・パスによるロードは、従来型ロードと比較して高速ですが、多少制限があります。

パラレル・ダイレクト・パスによるロードは、複数のパスによるロード・セッションが可能なため、同じデータ・セグメントを同時にロードできます。 パラレル・ダイレクト・パスは、ダイレクト・パスと比較して制限があります。

素人なのにすみません。

#それこそ、抜本的な改革はできないといわれているのに開発環境を根底から覆すような提案になってしまいました。

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません