- PR -

OracleDataReaderでの処理時間について

投稿者投稿内容
masa
大ベテラン
会議室デビュー日: 2004/10/28
投稿数: 161
投稿日時: 2007-02-14 09:10
本題から離れてしまいましたね。

ところで説明にあるコードはミニマムコードでしょうか。

一定件数のところでレスポンスが落ちるとのことですが、
ループ内にメモリを大量に使い捨てするような処理が含まれているために
GCが頻発に発生しているとか。可能性は低そうですけどね。

int i = 0;
while ( reader.Read() ) {
 ++i;
}

のように単純に読み込みだけを行うコードでもある件数あたりでレスポンスが落ちるかどうか、現象の絞込みを行ってみてはどうでしょうか。


extream
ベテラン
会議室デビュー日: 2005/12/26
投稿数: 83
投稿日時: 2007-02-14 11:35
みなさん、回答、アドバイスありがとうございます。

>int i = 0;
>while ( reader.Read() ) {
> ++i;
>}
>
>のように単純に読み込みだけを行うコードでもある件数あたりでレスポンスが落ちるか>どうか、現象の絞込みを行ってみてはどうでしょうか。

whileの処理だけ(CSV出力なし)にした場合でも、レスポンスは遅かったです。
厳密に言うと、
int i=0;
while ( reader.Read() )
{
if (i%100 == 0)
{
// ログ出力(時間出力)
}
continue;
}
とやって、処理時間を図りました。


 ・time_CSV += (dtEndcsv - dtStartcsv);
としていますが、最後の読み込みの時にしか時間が計られ無いのでしょうか?
すいません、どこが変なのか気づかなくて。。。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2007-02-14 21:55
 ああ、、、どうしてコードで語るかなぁ?あなたの日常語は、C# ですか?私の日常語は日本語なので、翻訳中に誤りました。

 一言、「while 文の、全体とブレースの内側とでかかった時間を計測して差を出すことで、read にかかった時間を計測しました」と加えてくれれば、コードを読まなくても何をしているのかわかるのに。。。


*コードの意味を知って、その意味に沿っているか検証するためにコードを読む
*コードの意味を知るためにコードを読む

 この2つで、読まなければならない量、考えなければならないことが違ってきます。ここで、私は「時間を計測した」ということだけに注目して、コードを読みました。その為、2つの時間の差がなんなのか、読み解けるまでコードを読みませんでした。どのタイミングで時間を計っているか、だけに注目しました。よって、コードを読み誤りました。

 計測のためだけにコードを書き直してもいいんだし。。。
 次のようなコードであれば、だれも time_Read の意味を間違いませんよね。
コード:
while (true) {
    DateTime dtStartRead = DateTime.Now;
    if (reader.Read() == false) break;
    time_Read += (DateTime.Now - dtStartRead);
    ...
}




 また、「OracleDataReaderを使う場合、多少の時間ロスは仕方ないのでしょうか??」という表現も、よくわかりませんでした。比較の対象は、何でしょう?
 OracleDataReader だと何秒、OleDbDataReader だと何秒、OracleClientDataReader だと何秒、というように書かれていれば、「OracleDataReader を使う場合は、」と書かれていても意味が通ります。

 でも、そうではない。いったい、何を計りたかったのでしょう?

 また、重要な、環境についても書かれていません。Oracle は、実験しているマシンに、ローカルに接続されているのでしょうか。または、ネットワークの向こうにあるのでしょうか。そして、Oracle が動いているマシンにメモリはどれくらい積んであって、どれくらい、Oracle に割り当てられているのでしょう?
 また、動作中に他のタスクが CPU 時間を食ったりしていないでしょうか。
 もちろん、そんなことがないことは、見ているあなたには分かり切ったことでしょう。でも、見えていない私には、考慮すべき点なのです。
_________________
extream
ベテラン
会議室デビュー日: 2005/12/26
投稿数: 83
投稿日時: 2007-02-15 10:17
Jittaさん>
説明不足、説明下手が重なってしまい、申し訳ありませんでした。
jittaさんがおっしゃられているように、コードで語るのではなく、今後は日本語でちゃんと説明できるように心がけます。
ご指摘ありがとうございました。m(__)m


環境は、
 Oracle … スタンドアロン環境
 Cpu   … PentiumD 3GHz
 メモリ … 1GB
です。
また、SQLで取得対象のフィールドは13フィールドを対象としています。
(同一表のフィールドです。)


例にあげている関数の処理中は、メモリは1GBを超えています。
(タスクマネージャにて確認。) 
計測中は、アンチヴィルス以外は起動しないようにしています。
(アンチヴィルスも、スキャンは行わず、常駐しているだけにしています。)


>でも、そうではない。いったい、何を計りたかったのでしょう?

アプリを作成し、各処理の処理時間を計測したところ、例にあげている関数が最も処理時間がかかっていました。
そこで、この関数のどの部分に時間がかかっているのかを調査したくて、処理時間の計測を行いました。
計測結果をみたところ、While文の中と外で処理時間が異なっており、なぜ処理時間が大きく違うのかが分からなかったため、本スレッドを立てて、みなさまに教えていただこうと思いました。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2007-02-15 16:00
引用:

extreamさんの書き込み (2007-02-15 10:17) より:

アプリを作成し、各処理の処理時間を計測したところ、例にあげている関数が最も処理時間がかかっていました。
そこで、この関数のどの部分に時間がかかっているのかを調査したくて、処理時間の計測を行いました。
計測結果をみたところ、While文の中と外で処理時間が異なっており、なぜ処理時間が大きく違うのかが分からなかったため、本スレッドを立てて、みなさまに教えていただこうと思いました。


 普通、そういう計り方はしないと思う。


 まず、Oracle 単体で、計測してみましょう。OTN などで、「実行計画」をキーに検索すると、それなりに出てくると思います。
 その結果を見て、データベース検索で、時間を短縮できるところがないか、調べましょう。

 次に、文字コードの変換をしていないか、調べます。.NET は UTF-8 なので、Oracle が Shift-JIS ならば、途中で文字コードを変換していることになります。この変換が必要ないなら、それなりにスピードアップが望めるでしょう。
_________________
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2007-02-16 21:40
ええと、微妙に話がおかしな方に行ってしまったので一応補足しておきます。

別にStringBuilderが遅いとか、StringBuilderを使うこと自体がだめ
などということは言ってません。
また、最初の書き込みにあったような使い方が、悪いとか間違ってるとかは
行ってません。

ただ、盲目的に文字列連結にはStringBuilderを使うというように、
意味や効果を考えない風潮があるように感じたので書きました。

実際、パフォーマンスを上げるためだと堂々といいながら、
おかしな(意味がない)使い方をしているのをよく見かけます。

例えば、

・固定個数の文字列(変数の値とか、列のデータとか)を連結する際に、
 パフォーマンスが、という理由でStringBuilderを使う。

→固定個数の文字列連結は、+ でくっつける方が効率は良いです。
 ただ、コードの記述上などの理由で、あえてStringBuilderで書くことはあります。
 また、StringBuilderを使ったからって特別に悪いわけではないです。
 ※パフォーマンスが、という理由でこういう記述にするのは変、という話です

・今回のような、CSVへの書き出し(TextWriterなどへの書き出し)で、
 パフォーマンスが、という理由でStringBuilderを使う。

→そもそも、TextWriterに直接Writeするのがもっとも効率的です(通常は)。
 わざわざバッファを解して文字列連結する意味がありません。
 これも、別にこういうやり方が即悪い、といっているわけではありません。
 が、パフォーマンスが、という理由ならこれは本末転倒です。
 ※そもそも連結する必要がありません。


ちなみに(ちなまんでも)もっともやってはいけないのは、全レコードを
文字列としてくっつけようとするようなやり方です。
レコード件数の上限が少ない数だと分かっているならそれほど弊害はありませんが、
このまま件数が想定できないような処理に持っていくと、場合によっては
とんでもないことになります。
そして、たとえ現在件数が少ないことが分かっていても、何も考えずにまねされたり
今後件数が増えていく可能性などを考えると、最初からやるべきではありません。


話変わって、時間の計測などはStopwatchクラスを利用することをお勧めします。
自分で引き算などして分かりにくくしてしまうよりも、Stopwatchなら非常に
直感的な使い方で、簡単に計測が必要な部分だけの時間を計れます。
ぼのぼの
ぬし
会議室デビュー日: 2004/09/16
投稿数: 544
投稿日時: 2007-02-18 18:12
引用:

なちゃさんの書き込み (2007-02-16 21:40) より:
話変わって、時間の計測などはStopwatchクラスを利用することをお勧めします。
自分で引き算などして分かりにくくしてしまうよりも、Stopwatchなら非常に
直感的な使い方で、簡単に計測が必要な部分だけの時間を計れます。


引用:

extreamさんの書き込み (2007-02-13 17:41) より:
- 開発環境 -
Oracle 10g(リリース1)
Windows XP SP2
VS2003
- - - - - - -


http://msdn2.microsoft.com/ja-jp/library/system.diagnostics.stopwatch(VS.80).aspx
引用:

このクラスは、.NET Framework version 2.0 で新しく追加されたものです。


私も同じ指摘をしようと思いましたが、気づいてやめたのです。
extream
ベテラン
会議室デビュー日: 2005/12/26
投稿数: 83
投稿日時: 2007-02-19 09:52
みなさん、回答ありがとうございます。


最近は何も考えずに、文字列の連結はStringBuilderを使うようになっていました。
なちゃさんの言っているように、パフォーマンスがという理由なら、直接吐き出した方が効率的ですね。

今後は、場面場面でもっとも適した処理を行うように検討しようと思います。
アドバイスありがとうございました。

スキルアップ/キャリアアップ(JOB@IT)