[delphi-users:2368] TClientDataSetで更新を繰り返すと遅くなる

551 views
Skip to first unread message

moru

unread,
Dec 27, 2011, 2:33:13 AM12/27/11
to delphi-users
いつもお世話になっております。
件名の通り、TClientDataSetで更新を繰り返すと遅くなる問題の解決策を探しています。
VCLの構成は以下の通りです。
TIBDataSet - TDataSetProvider - TClientDataSet

TClientDataSetのSetRangeなどのIndexを利用するためにこのような構成にしています。
原因の特定のために、TClientDataSetだけの構成で、Integer型フィールドを1つだけ持たせて添付のソースで更新を繰り返してみました。添付のソースのボタン押下でレスポンスが低下していきます。
対処策としてLogChangesプロパティも試してみましたが、データベースへの更新がかからなくなりました。(データベース接続しているとやはりだめなのでしょうか、、)
いつも教えていただいてばかりで申し訳ございませんが、どうぞよろしくお願いします。
稲庭 宏

環境:Delphi7、FireBird2.5、IBX


procedure TForm1.FormCreate(Sender: TObject);
var
    i : Integer;
begin
    DS.CreateDataSet;

    for i := 1 to 10000 do begin
        DS.Append;
        DS.FieldByName('int').AsInteger := i;
        DS.Post;
    end;
    DS.First;
end;

// 値の更新
procedure TForm1.Button1Click(Sender: TObject);
begin
    DS.First;
    while (not DS.Eof) do begin
        DS.Edit;
        DS.Fields[0].AsInteger := DS.Fields[0].AsInteger + 1;
        DS.Next;
    end;
end;

ありい

unread,
Dec 27, 2011, 2:52:36 AM12/27/11
to delphi...@freeml.com
 稲庭さん、こんにちは。

 LogChangesプロパティではなく、Button1Clickの最後でApplyUpdates
メソッドを呼び出してみては如何でしょう。

#環境がないのでノーテストですが...

 LogChangesプロパティでは上手くいかない理由は、ヘルプに書いて
あります。

(以下ヘルプから引用)
> データの変更は直接 Data プロパティに対して行われ,プロバイダを
> 介してデータベースまたはソースデータセットに適用することはでき
> ません。

 ApplyUpdatesもヘルプを読んでみて下さいね!

ありい


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
毎日豪華プレゼントキャンペーン開催中!くまポン
http://ad.freeml.com/cgi-bin/sa.cgi?id=hHkCP
------------------------------------------------------[freeml byGMO]--

moru

unread,
Dec 27, 2011, 3:52:06 AM12/27/11
to delphi...@freeml.com
ありい様、返信ありがとうございます。
ApplyUpdatesについて確認しました。
レスポンスは悪化しませんが、DataSetの更新とApplyUpdatesを合わせると結構時間がかかってしまいます。
ユーザーが1行追加する度に関連する行に更新をかけており、レスポンスをもっとあげたい考えです。
(具体的には明細書の計上順序を更新しています)
LogChangesプロパティについては、ヘルプ記載の事項理解していましたが、ダメもとで試してみました。
 
2011年12月27日16:52 ありい <delphi...@freeml.com>:

ありい

unread,
Dec 27, 2011, 5:13:38 AM12/27/11
to delphi...@freeml.com
> ApplyUpdatesについて確認しました。
> レスポンスは悪化しませんが、DataSetの更新とApplyUpdatesを合わせると結構時間がかかってしまいます。
> ユーザーが1行追加する度に関連する行に更新をかけており、レスポンスをもっとあげたい考えです。
> (具体的には明細書の計上順序を更新しています)

 ApplyUpdatesのタイミングはどのようにされましたか?

// 値の更新
procedure TForm1.Button1Click(Sender: TObject);
begin
DS.First;
while (not DS.Eof) do begin
DS.Edit;
DS.Fields[0].AsInteger := DS.Fields[0].AsInteger + 1;
DS.Next;

// (1)ココ
end;

// (2)ココ
end;

 もし(1)のタイミングで遅いと感じられているのでしたら、
(2)に変更してどうなるか確認してみて下さい。

 もし(2)で遅いということでしたら、これに対する一般的
な回答は難しいです。プログラム上の修正で改善するのか、
DBサーバのH/Wの性能が悪いのか、ディスク性能の問題なの
か、テーブル設計に問題があるのか...

 H/WやDB設計の問題はどうにもならないのでプログラム上の
話を少し補足します。

> TIBDataSet - TDataSetProvider - TClientDataSet

 一般論として上記構成を取るメリットは、データ変更を一旦
CDS内で溜めておくことで、いちいち変更の度にDBに書き込み
に行かずに済むので操作レスポンスが改善する、というものと
理解しています。

 残る問題は、溜まった変更データを「いつ」DBに反映するか
(ApplyUpdatesを呼ぶか)、になりますが、例えば(1)のように
変更の都度呼んでいたら、最初に書いたメリットを捨てている
のと同じことです。

 もし(2)で遅いということでしたら変更データを溜めすぎて
反応が悪い、ということになります。

 そうなるとプログラム上、(1)と(2)の間を取ることを考える
訳ですが、例えば100件更新したら反映するとか、ユーザーに
「反映」ボタンを押して貰ってその時に砂時計にして反映する
とか...

 この部分は稲庭さんが考えて試行錯誤されるしかないと思い
ます。

 少しでも参考になれば幸いです。

ありい


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
使い方はいろいろ♪一部のメンバーだけにMLメールを送ろう!
http://ad.freeml.com/cgi-bin/sa.cgi?id=hHm74
------------------------------------------------------[freeml byGMO]--

moru

unread,
Dec 27, 2011, 4:08:14 PM12/27/11
to delphi...@freeml.com

ありい様、ありがとうございます。
ApplyUpdatesのタイミングですが、(2)です。

>そうなるとプログラム上、(1)と(2)の間を取ることを考える
>訳ですが、例えば100件更新したら反映するとか、ユーザーに
>「反映」ボタンを押して貰ってその時に砂時計にして反映する
>とか...

一定数更新したらApplyUpdates実行はよさそうです。
方法を考えてみたいと思います。
報告まで少し時間が掛かると思いますが、改めて結果を報告いたします。
ありがとうございました。
稲庭 宏

2011年12月27日19:13 ありい <delphi...@freeml.com>:
Reply all
Reply to author
Forward
0 new messages