vb.netでテキストファイルを解析してからOracle(10g)に登録するプログラムを作成しています。
接続にはODP.netでOracleDataAdapterのFillメソッドを使ってます。
動きには問題ないのですが時間がかかります。
大体何十万行数十MBほどのテキストファイルを解析し、数千件ぐらいのデータにしてからそれを10あまりのテーブルに登録してます。
こういう場合、一個一個の処理の速さは早いためチューニングにも限界があるような気がします。
このようにInsertが多数発生する場合に何か速度改善の方法はないでしょうか?
事情によりvb.netでの開発を辞めるとかテキストファイルのフォーマットを変えるなんていうあまりに抜本的な変更は出来ません。
こんにちは。
わたしも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データ・ファイルに直接書き込みます。この場合、通常のデータ処理は無視されます。 ダイレクト・パスによるロードは、従来型ロードと比較して高速ですが、多少制限があります。
パラレル・ダイレクト・パスによるロードは、複数のパスによるロード・セッションが可能なため、同じデータ・セグメントを同時にロードできます。 パラレル・ダイレクト・パスは、ダイレクト・パスと比較して制限があります。
素人なのにすみません。
#それこそ、抜本的な改革はできないといわれているのに開発環境を根底から覆すような提案になってしまいました。
ちょっと前に同じような質問がありました。
テキストファイルを解析・変換しておいて、それをOracleの機能を用いてインポートする方法が考えられます(Oracleには詳しくありませんが、おそらくそういう機能が存在すると思います)
あとはindexが多く設定されている場合、insert前に取り除くなりしておいて完了してから再度設定しなおすのも効果があるかもしれません。
そのほかVB.NETのプログラムで、insert1回ごとにcommitするような作りになっていないかを確認してはいかがでしょうか(おそらくすでに確認済みだとは思いますが)
こんにちは。
わたしも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データ・ファイルに直接書き込みます。この場合、通常のデータ処理は無視されます。 ダイレクト・パスによるロードは、従来型ロードと比較して高速ですが、多少制限があります。
パラレル・ダイレクト・パスによるロードは、複数のパスによるロード・セッションが可能なため、同じデータ・セグメントを同時にロードできます。 パラレル・ダイレクト・パスは、ダイレクト・パスと比較して制限があります。
素人なのにすみません。
#それこそ、抜本的な改革はできないといわれているのに開発環境を根底から覆すような提案になってしまいました。
コメント(0件)