- - PR -
JDBCで30万件を登録
1
| 投稿者 | 投稿内容 |
|---|---|
|
投稿日時: 2003-03-19 20:18
Tanakaと申します。
Javaで、 ・タブ区切りテキストファイルを1レコードずつ読み込む。 ・読み込んだレコードでデータベースをSELECTし、同一キーを持つ レコードがなければINSERT、あればUPDATEする。 というようなプログラムを作成しました。 SELECT、INSERT、UPDATEなどのSQL文は、それぞれ個別にPreparedして 使用しています。 JDBCドライバはType4(Thin)で、JDKのバージョンは1.4.1_01です。 ORACLEのバージョンは9iになります。 このJavaプログラムをLinuxで実行し、LAN内のWindows2000サーバの ORACLEデータベースにネットワークを介してデータを登録する処理を 実行しました。 データの件数は30万件で、最初の1時間で5万件ほど登録できたので、 6,7時間で終了すると思っていましたが、5万件ほど登録したあとに、 パフォーマンスが落ちて、10時間経過しても10万件ほどしか登録 できませんでした。 サーバとその負荷状況、ネットーワークなどの環境により 一概には言えないと思いますが、ネットワークを介して Type4ドライバで30万件ものデータを登録するとなると、 このくらいの時間はかかってしまうものなのでしょうか? このような経験をして対処されたことのある方、 またJDBCプログラミングで気をつけなければならない点など ありましたら、ご教授してください。 よろしくお願いします。 _________________ -- Tanaka |
|
投稿日時: 2003-03-19 21:04
おっしゃるとおり、一概には言えません。
データ量が増えるにつれ遅くなる原因としては、Oracleサーバ側とJavaクライアント側の両方が考えられます。まずは、それぞれのリソース消費量などを調べて、切り分けてみましょう。 Oracle側だとすると、追加・更新しているテーブルのスキーマやインデックスの張り方が気になります。SELECTやUPDATEが毎回動くとなると、インデックスがキーに張られていなければ件数の増加に伴い遅くなるのは当然です。また、余分なインデックスが張られていれば、UPDATEやINSERTが遅くなります。 Javaクライアント側だとすると、メモリのスラッシングなどが考えられます。テキストファイルからレコードを読み込む際に、オブジェクトを大量に作成していませんか? 文字列クラスをStringBufferクラスに置き換えるなどの工夫できる場合があります。 |
|
投稿日時: 2003-03-19 21:35
sqlldrコマンドは使用できないのでしょうか?
あとは、テーブル構成やselect/update文を見ないとわかりません。 |
|
投稿日時: 2003-03-19 22:20
トランザクションはどうなってます?
1トランザクションで動かしているのならロールバックセグメントが大きくなってパフォーマンスは落ちるかなと思いますが。 |
|
投稿日時: 2003-03-19 23:43
みなさん、さっそくの返答ありがとうございます。
まず、トランザクションは未使用です。 この処理は、通常1日1回1000件前後のデータの登録・更新に 使用します。今回の30万件は初期セットアッップ用にと実行 しました。 ORACLE側のインデックスですが、確かにこの処理で発行する SELECTなどでは使用されないフィールドにもインデックスは 張られています。ですが、他の用途で使用するためこのままに しておきたいと思っています。 Javaプログラムを実行しているLinuxを調査したところ、空き メモリ容量が徐々に減っていっています。psコマンドで確認 できるこのJavaプログラムの実メモリ占有率や使用サイズに 変化はありませんが、このプログラム以外、大してプログラムを 実行していないとなると、当然このプログラムの作りが悪いから なのですね。 そこで、へげもんさんがご指摘して下さった、テキストファイルの レコード読み込みの部分を見直してみました。 おおまかですが、以下のような感じになっています。 ---- private void methodA() { String rec; while ((rec=buff.readLine())!=null) { methodB(rec); } } private void methodB(String rec) { String field[] = rec.split("\t"); [SQL発行->登録・更新処理] } ---- このmethodBのfield[]は、methodBを抜けるとなくなると思います。 field[]がなくなると、rec.splitで作られたStringオブジェクトの 配列は、どこからも参照されなくなり、GCの対象になると思っている のですが・・・ _________________ -- Tanaka |
|
投稿日時: 2003-03-20 00:07
こんにちは。
Oracle側なら、表のエクステント、データファイルの初期サイズや増加サイズなどは どうでしょうか?初期で多めにとっておいたほうがいいと思います。 ま、これが直接の原因で数十時間も処理がかかるとは思えませんが・・・。細かな拡張がない 分、若干処理は上がると思います。 あと、初期セットアップに関係ないインデックスは30万件の初期セットアップ後に作った ほうがいいのではないでしょうか? 基本的なことなので、すでにやってたらごめんなさい。 |
|
投稿日時: 2003-03-20 17:39
こんにちは。
maruさんのアドバイスをもとに、Oracleの該当テーブルを確認 してみると、初期サイスが64Kバイトの設定になっており、 60回以上ものエクステントが発生していました。 おそらく、最初の5万件までは初期サイズ内で収まっていたので、 1時間程度で済み、その後はエクステントにつぐエクステントで パフォーマンスが落ちていたのだと思われます。 実は、このOracleはあるWebシステム・パッケージとともに導入 されたもので、パッケージ販売会社のSEに設定してもらっています。 まだ仮設定の状態ですが、ある程度の容量は確保されていると思い 当処理を実行してみたのです。 実行する前に確認してみるべきでした。 今すぐ、容量拡張して再度実行してみたいところですが、 私にはそのような権限はない(立場的に)ので、 来週パッケージ販売会社のSEが来るまでお預けとなります。 ご返答してくださったみなさま、ありがとうございました。 _________________ -- Tanaka |
|
投稿日時: 2003-03-21 14:41
> Javaで、
> ・タブ区切りテキストファイルを1レコードずつ読み込む。 > ・読み込んだレコードでデータベースをSELECTし、同一キーを持つ > レコードがなければINSERT、あればUPDATEする。 > というようなプログラムを作成しました。 これだけのプログラムなら、Java 以外の言語で作成するのもひとつの方法だと思います。 P.S. 最近の「とにかくJava」風潮に疑問を感じ始めている katsum でした(笑)。 |
1
