[Delphi:91181] DelphiでAccessのようなインターフェイスを作成するための最適な方法

2,001 views
Skip to first unread message

kato_shinji

unread,
Mar 15, 2009, 11:36:47 AM3/15/09
to Del...@ml.users.gr.jp
こんにちは、kato(s)です。

以前、DelphiでAccessのようなインターフェイスを持った
汎用的なテーブルメンテナンスツールを作成していました。

BDEを利用することで複数のDBMSに対応しており、
TTable、TDBGridコンポーネントをカスタマイズしていました。

最近よくBDEは先がないという話題が出ていますが、BDEを
利用せず上記のようなアプリを作成するにはどのコンポーネント
を使用するのがベストなのでしょうか?

最近あまりDelphiを触っておらず無知のため間違っているかも
しれないですが、dxExpressは単方向のデータセットしか扱えない
ので、TDBGridと連動させて利用できない。
TClientDatasetは、非接続型のデータセットなので、大量のデータ
(数万~数十万件)を扱う場合にデータセットを開くまでに時間が
かかる。といった問題があるのかと思っています。

TTableでも大量のデータを扱うとパフォーマンスは落ちますが、
接続型・双方向データセットのため、最初にデータを開くまでの
パフォーマンスと、TDBGridで操作できる点が重宝しました。

Accessのようなインターフェイス(TDBGridを使用)、汎用的な
データメンテナンス(複数DBMS対応、コードの共通化)、大量
データでのパフォーマンス劣化を極力防ぐという点でアドバイス
頂ければと思います。

どのような開発スタイルが一般的なのでしょうか?
よろしくお願いいたします。


Makoto Watanabe

unread,
Mar 15, 2009, 2:34:11 PM3/15/09
to Del...@ml.users.gr.jp
kato_shinji 様、こんにちは。
  渡邊誠人です。現在時刻:2009/03/16 3:30:42

「Mon, 16 Mar 2009 00:36:47 +0900」頃に
「Microsoft Windows Mail 6.0.6001.18000 」によって書かれた
「[Delphi:91181] DelphiでAccessのようなインターフェイスを作成するための最適な方法」
に関する返答です。

> Accessのようなインターフェイス(TDBGridを使用)、汎用的な
> データメンテナンス(複数DBMS対応、コードの共通化)、大量
> データでのパフォーマンス劣化を極力防ぐという点でアドバイス
> 頂ければと思います。

 一般的かどうかは解らないのですが、私はODBCを利用しています。
楽をする為に、TAK さん作成の ODBCアクセスコンポーネントのシェアウェア
を使っています。
 Dephi 7使いですので、十分役目を果たしている状況です。

 何が主流になろうとも、Delphi 7 を使い続ける限り、データベース接続は、
ODBCを選択する事になってくると思います。

--
 ヘ ヘ     ・. ・‥…………………………………………‥・Becky! 2.50
ミ・.・ミ  ・.●・          .NET 研究所 http://www.dotnet.jp/
(m m)~ ●・                         渡邊誠人


kato_shinji

unread,
Mar 16, 2009, 10:42:08 PM3/16/09
to Del...@ml.users.gr.jp
渡邊誠人さん

情報ありがとうございました。

早速試してみましたが、ODBCを使用するのが前提ですが良さそうです。
価格も手ごろでD2009の最新の環境まで対応しているようなので購入も
検討してみようと思います。
http://homepage1.nifty.com/TAK/

ただサポート面が気になるのですが、今回
SQLServer2005では、問題なく動作確認できましたが、
Oracle10gでは、下記のエラーが発生しました(Delphi7で確認)

※プロパティの設定が、
ODBCVersion=ODBC20
⇒[Oracle][ODBC]ドライバが機能しません  …A

ODBCVersion=ODBC30,ODBC35
⇒[Oracle][ODBC]オプション機能が実装されていません  …B

Bは非対応かなというのは想像できるのですが、Aは原因不明です。

Accessで同じODBC接続を使用して問題なくデータの参照・更新が
出来ているので困りました。何か情報ありましたらお願いします。

また、上記のコンポーネント以外の選択肢も
あるようでしたら情報お願い致します。


以上、よろしくお願い致します。

Value平野

unread,
Mar 16, 2009, 11:28:12 PM3/16/09
to Del...@ml.users.gr.jp
平野と申します。

> 最近よくBDEは先がないという話題が出ていますが、BDEを
> 利用せず上記のようなアプリを作成するにはどのコンポーネント
> を使用するのがベストなのでしょうか?

私の経験の範囲ですが、

TADOConnection → ADO Provider → ODBC → 各DBMS

が良いと思います。

このあたりが参考になると思います。
http://www.sunvisor.net/modules/pico/Delphi/Oracle.htm

> Accessのようなインターフェイス(TDBGridを使用)、汎用的な
> データメンテナンス(複数DBMS対応、コードの共通化)、大量
> データでのパフォーマンス劣化を極力防ぐという点でアドバイス
> 頂ければと思います。

私も数種類のRDBMSに接続する汎用ツールを作成していますが、
この接続方法が原因でのトラブルは今のところありません。
(ODBCドライバに由来する不具合は除きます)

ちょっと宣伝、、
ValueSQL -- For all SQL developers --
http://gwsrv.valuenet.co.jp/ValueSQL/pukiwiki.php


DataAccessコンポーネントや、他のDataAccessコンポーネント群
及びDataControlsはBDEと共通のものを使用するはずなので、
これまで蓄積された TDBGrid などを使用するソースコードは
大部分がそのまま移行できると予想できます。

なお、ADO-ODBC経由のパフォーマンス劣化については
一概に言えないので、アドバイスできませんが(私の体感では)
気になるほどではないと思っています。


kato_shinji

unread,
Mar 18, 2009, 6:29:56 AM3/18/09
to Del...@ml.users.gr.jp
平野さん

情報ありがとうございました。

> このあたりが参考になると思います。
> http://www.sunvisor.net/modules/pico/Delphi/Oracle.htm


丁寧に書かれていてわかりやすいサイトでした。


実際に、ADOでのデータ取得を試してみました。


> なお、ADO-ODBC経由のパフォーマンス劣化については
> 一概に言えないので、アドバイスできませんが(私の体感では)
> 気になるほどではないと思っています。

TADOConnectionとTADOTableを利用し、DBGridに表示させた際、
Oracleでカラム数200程度、データ件数10万件がDBGridに表示
されるまでに3分以上かかりました。

同じ内容をBDEのTDatabaseとTTableで接続した場合は、3秒程度で
開きました。

前者はやはり最初に全件取得しているんでしょうか?開いた後は
パフォーマンスは良いのでしょうが、今、求めているのはサクッと開き、
スクロール時に多少DBアクセスは発生してもAccessのような感じの
テーブルメンテアプリを作りたいという点です。

ADOのコンポーネントで関係ありそうなプロパティを触ってみましたが、
状況は変わらずでしたがこれという設定があるんでしょうか?

※ちなみにValueSQLも試させて頂きましたが、上記テーブルから全件取得
するSQLを実行したら10分以上たっても応答が帰りませんでした。
同じSQLをTQueryを使えば、数秒程度で開きます。

以上、何か情報ありましたらお願い致します。


⇒また、上記のようなことをADO.NETでは可能なんでしょうか?
Delphiではないですが、Delphiとの比較のため、ご存知の
方いましたらご教授願います。ADO.NETのデータテーブルは
双方向のカーソルですが、非接続データアクセスのため、
データをFillする時に全件読み込んでしまうのではないかと
想像しています。接続型アクセスで、必要時にデータを取得する
BDEのような動きをさせたいのですが、ADO.NETでは可能でしょうか?
Accessはこのような動きになっているので可能なような気はするの
ですが…いかがでしょうか?

Value平野

unread,
Mar 18, 2009, 9:41:15 PM3/18/09
to Del...@ml.users.gr.jp
kato(s)さん

こんにちは、平野です。

> TADOConnectionとTADOTableを利用し、DBGridに表示させた際、
> Oracleでカラム数200程度、データ件数10万件がDBGridに表示
> されるまでに3分以上かかりました。

3分ですか。。かかりますねぇ。
TCustomADODataSet系のコンポーネントも遅延読み込みをしている
はずなので、私の予想(数秒)より時間がかかっている印象です。

ちなみに、今開発されているアプリではなく、単純なテスト
アプリでもそのくらいかかってしまうのでしょうか?

ValueSQLには、「グリッド表示機能」(DelphiのDBグリッド)
があるので、SQL実行前に、結果画面の左側にあるグリッド
表示ボタン(グリッドマーク)をONにして試してみてください。
この表示は、ほとんどTADOQuery+TDBGridの素の状態なので、
速さの計測には向いていると思います。
http://gwsrv.valuenet.co.jp/ValueSQL/pukiwiki.php
→ 左のメニュー:結果表示モード→グリッドをご参照ください。

(デフォルトのテキスト出力モードは、出力を桁合わせ整形する
のでかなり時間がかかってしまいます。すみません、、、)

ADO.NETについては、未経験です、、

お役に立てば幸いです

kato_shinji

unread,
Mar 19, 2009, 3:45:00 AM3/19/09
to Del...@ml.users.gr.jp
平野さん

私が試したのは本当に簡単なテストアプリです。
フォームに、TDBGrid、TDatasouuce、TADOConnection、TADOTable
だけを貼りつけて、アプリ起動時にテーブルをオープンして、
グリッドに描画され、操作できるようになるまでの時間を計測しました。

> ValueSQLには、「グリッド表示機能」(DelphiのDBグリッド)
> があるので、SQL実行前に、結果画面の左側にあるグリッド
> 表示ボタン(グリッドマーク)をONにして試してみてください。

こちらも試しましたが、ログは以下のとおりです。
2分ほどですね。

Provider=OraOLEDB.Oracle.1
Password=********
Persist Security Info=True
User ID=********
Data Source=********
Extended Properties=""
へ接続しました
自動コミットモードです

■GRID OUT■ G#1

結果:96875件 (128578ms)


⇒結果が表示された後は、全件、追加アクセス無しで参照できてそうな
動きをしていたので、やはり最初に全件読み込んでいそうな感じです。


----- Original Message -----
From: "Value平野" <hir...@valuenet.co.jp>
To: <Del...@ml.users.gr.jp>

Value平野

unread,
Mar 19, 2009, 4:52:22 AM3/19/09
to Del...@ml.users.gr.jp
平野です。

> 結果:96875件 (128578ms)

やっぱりこのくらいかかりますか、、、

以前、H2DatabaseにODBC経由で接続し、結果の量と無関係に
遅くなる事象に遭ったことがあります。
その時は、ODBCの設定で回避できるとH2DatabaseのMLで教えて
もらったことがありました。(20秒→0.1秒)

> ⇒結果が表示された後は、全件、追加アクセス無しで参照できてそうな
> 動きをしていたので、やはり最初に全件読み込んでいそうな感じです。

となると、遅延読み込みしてないみたいですね。

あとは、TADOQueryや、TADOTableの CacheSizeプロパティーの調整
くらいしか思いつきません、、

Takuo Nakamura

unread,
Mar 21, 2009, 1:37:14 PM3/21/09
to Del...@ml.users.gr.jp
中村@ブレーンです。

ADOのデータセットは既に読み込んだレコード数に正確に反比例して
Next メソッドが遅くなります。このため実用になるのはいっぺんに
読み込むレコード数が1万件程度までです。

普通のアプリでは千件程度でレコードの読み込みを打ち切るように工夫するので
問題はありませんが、ADOで一度に大量のデータを扱うには、
工夫が必要だと思います。

#以前、データ移行に ADO を使ってひどいめにあったことが有ります。
#Delphi の ADO でカーソルが一定の速さで動くようにする方法が
#あればぜひ知りたいです。

"[Delphi:91206] Re: DelphiでAccessのようなインターフェイスを作成するための最適な方法" において
Value平野 <hir...@valuenet.co.jp> さんは書きました

>No virus found in this incoming message.
>Checked by AVG - www.grisoft.jp
>Version: 8.0.238 / Virus Database: 270.11.22/2015 - Release Date: 03/20/09 19:01:00

+---------------------------------------------+
|Takuo Nakamura from Hino City, Tokyo JAPAN |
+---------------------------------------------+

takashi

unread,
Mar 21, 2009, 8:55:13 PM3/21/09
to Del...@ml.users.gr.jp
どもです。

話が横道に入って申し訳ありませんが

> #以前、データ移行に ADO を使ってひどいめにあったことが有ります。
どの方式をお使いですか

私自体は ADO を使っています。一度に大量のデータを扱う事はあまりないので
特に困っている事はないのですが、皆さんはどんな方式で利用されているのか
興味があります。


--
takashi <taka...@csjpn.com>


Takuo Nakamura

unread,
Mar 21, 2009, 11:00:26 PM3/21/09
to Del...@ml.users.gr.jp
中村@ぶれーんです。

"[Delphi:91213] Re: DelphiでAccessのようなインターフェイスを作成するための最適な方法" において
takashi <taka...@csjpn.com> さんは書きました


>話が横道に入って申し訳ありませんが
>
>> #以前、データ移行に ADO を使ってひどいめにあったことが有ります。
>どの方式をお使いですか

Oracle 9i から ADO でデータを受け取って処理するというものです。
データ量は1千万件から1億件。

ADOのカーソルは、サーバカーソルとクライアントカーソルを使いましたが、
双方ともカーソルを回してゆくうちに読み込んだレコード数に反比例して
Nextメソッドが遅くなってゆきました。
カーソルタイプをいろいろ変えてみましたが効果はありませんでした。

また、サーバカーソルはクライアントカーソルに比べて 速いのですが、
メモリを馬鹿食いするので使えませんでした。

#結局、SQL を工夫して、分割してデータを読み取ることで乗り切りました(^^;
#ただ、時間の制約からデータセットのプロパティの組み合わせを全て試していません。
#ひょっとすると大量データに都合のいいモードがあるかも...

takashi

unread,
Mar 22, 2009, 5:22:11 AM3/22/09
to Del...@ml.users.gr.jp
どもです。

> Oracle 9i から ADO でデータを受け取って処理するというものです。
> データ量は1千万件から1億件。

恐ろしい件数ですね。
当面、そんなに大量なデータを扱う事はありませんが、
既存のDelphiでどこまで行けるか時々心配になることがあってお聞きしました。

ユーザーインターフェース以外に NET対応する具体的なメリットが見えないけど
唯一心配なのがDB対応なんです。


--
takashi <taka...@csjpn.com>


中村拓男

unread,
Mar 23, 2009, 2:26:05 AM3/23/09
to Del...@ml.users.gr.jp
中村@ブレーンです。

いろいろ試して見ましたが、TClientDataset & TADODataSet でうまく行くかんじです。

1) 構成は以下のようにする。

TADOConnection -- TADODataSet -- TDataSetProvider -- TClisentDataSet -- TDataSource -- TDBGrid

# TADOConnection を使わないと 2) の設定ができません。

2) TADODataSet の ExecuteOptions を [eoAsyncFetchNonBlocking] に設定。
3) TClientDataSet の PacketRecords を 50 程度に設定

こうすると10万件のクエリでもほぼ瞬時に DBGrid に内容が表示され、
DBGridをスクロールすると順次足りないレコードを読み込んでいるかんじでした。

以上です。

#まだあまり試してないので問題があるかも...

kato_shinji さんは書きました:

----------
東京都 日野市 中村拓男

中村拓男

unread,
Mar 23, 2009, 2:44:37 AM3/23/09
to Del...@ml.users.gr.jp
中村@ブレーンです。

Takuo Nakamura さんは書きました:


>Oracle 9i から ADO でデータを受け取って処理するというものです。
>データ量は1千万件から1億件。
>
>ADOのカーソルは、サーバカーソルとクライアントカーソルを使いましたが、
>双方ともカーソルを回してゆくうちに読み込んだレコード数に反比例して
>Nextメソッドが遅くなってゆきました。
>カーソルタイプをいろいろ変えてみましたが効果はありませんでした。

これ、解決しました(^^;

1) TADOataSet の ExecuteOptions を [eoAsynchFetch] に設定
2) TADODataSet の CacheSize を 100 程度に設定
3) TADODataSet の Open 前に DisbleControls メソッドを呼ぶ。

1)、2) の処置で、巨大なレコードセットを返すクエリでもカーソルが
速やかに返る様になり、全てのレコードセットを読み込む前に処理が
開始できるようになります。

3) の処置で Nextメソッドの処理速度が一定になります。

3) の処置は、DBコントロールの有無とは無関係に効き、効果絶大です(^^

手元のマシン(Celeron 2.4GHz) では Oracle 10g の 100万件のデータ処理が
3時間から20分に短縮されました。

参考:
'Serious' ADO Speed Techniques with Delphi - Part I  -- Steve Burch
http://edn.embarcadero.com/jp/article/27790

----------
東京都 日野市 中村拓男

kato_shinji

unread,
Mar 23, 2009, 5:03:54 AM3/23/09
to Del...@ml.users.gr.jp
中村さん

返信ありがとうございました。


私もその後調べていたんですが、少し古いですが以下の記事を見て、

http://www.borland.com/resources/jp/pdf/products/delphi/delphi_bde_to_dbexpress_jp.pdf

dbExpressでもDatasetProviderを利用して双方向カーソルと同じ動きができ、
キャッシュを利用したスムーズな動作ができそうなことが書いていたので試しました。
環境:Delphi7+devart dbExpressDriver+Oracle10g

http://www.devart.com/dbx/download.html

実はこの構成でも初期表示と、スクロールは軽快に動くようになったのですが、
一点問題があり、”Last”メソッドでカーソルを動かす場合極端に遅くなり、
約10万件のレコードで5分以上かかりました。

それで、中村さんのADO+DatasetProviderを利用した方法も試しましたが、
上記同様、初期表示とカーソル移動は軽快になりましたが、”Last”メソッドを
呼び出した際にパフォーマンスが極端に悪くなります(上記と同様5分以上)

あと一歩なんですが、なかなか良い設定の組み合わせが
見つからない(そもそも無理?)状態で行き詰っています。

※同様の操作は、BDEで接続した場合には、遅くとも数秒程度で
レスポンスは返ってくるのでなんとか同じ状態にできないでしょうか?


よろしくお願いいたします。

----- Original Message -----
From: ""中村拓" "男"" <tknak...@brain-tokyo.jp>
To: <Del...@ml.users.gr.jp>

Eddie

unread,
Mar 23, 2009, 8:07:59 AM3/23/09
to Del...@ml.users.gr.jp
横からですが、Eddieです。

> 実はこの構成でも初期表示と、スクロールは軽快に動くようになったのですが、
> 一点問題があり、”Last”メソッドでカーソルを動かす場合極端に遅くなり、
> 約10万件のレコードで5分以上かかりました。

ClientDataSetのAfterScrollイベントに

if (DataSet.State = dsBrowse) and (DataSet.RecNo = DataSet.RecordCount)
then
ClientDataSet..GetNextPacket;

のように記述したらどうでしょうか? Lastの動作が抑制されると思うのですが。

的外れな場合は無視してくださいませ。^^


畑井 和幸

unread,
Mar 23, 2009, 9:28:53 AM3/23/09
to Del...@ml.users.gr.jp
畑井です。

以前、ADOでいろいろとチャレンジしたのですが、この方法があったのですね。

Openするといつも全レコードを読み込もうとしてメモリーに蓄積してしまい
大容量レコードには向かないなと思って使用しないようにしていたのですが、
以下の方法だとメモリーに蓄積しない動作みたいです。

スクロールバーを一番下にドロップしても最後のレコードに一瞬で移動し
ます。
Nextメソッドで処理速度が一定になるのはメモリーに蓄積しない動作のためと
思います。
Accessでのダイナセットみたいな動作です。
スロールバーの動作は貧弱ですが。

> 1) TADOataSet の ExecuteOptions を [eoAsynchFetch] に設定
> 2) TADODataSet の CacheSize を 100 程度に設定
> 3) TADODataSet の Open 前に DisbleControls メソッドを呼ぶ。
>
> 1)、2) の処置で、巨大なレコードセットを返すクエリでもカーソルが
> 速やかに返る様になり、全てのレコードセットを読み込む前に処理が
> 開始できるようになります。
>
> 3) の処置で Nextメソッドの処理速度が一定になります。
>
> 3) の処置は、DBコントロールの有無とは無関係に効き、効果絶大です(^^


━━━━━━━━━‥‥‥‥………
 畑井和幸
 e-mail: ha...@cospec.co.jp
‥‥‥‥‥………━━━━━━━━


中村拓男

unread,
Mar 24, 2009, 1:56:21 AM3/24/09
to Del...@ml.users.gr.jp
中村@ブレーンです。

kato_shinji さんは書きました:


>それで、中村さんのADO+DatasetProviderを利用した方法も試しましたが、
>上記同様、初期表示とカーソル移動は軽快になりましたが、”Last”メソッドを
>呼び出した際にパフォーマンスが極端に悪くなります(上記と同様5分以上)
>

ちょっと試して見ましたが、lastメソッドを呼ぶ場合、Oracle の OLE DB だと
おそいようです。MS の ORACLE用 OLE DB では数秒で表示されました。
ひょっとすると、Oracle の OLE DBも 接続文字列を弄れば 速くなるかも。

ただ、多くのクライアントツールでは大きなテーブルの最後の方を見るのは
時に困難なのが普通なので、ツールとしてテーブルの最後を見る機能は
必須ではないと思います。
条件を加えて絞ったり、順序を変えてみられるようにすれば、ツールとしては問題ないと思います。

1) 環境

Client OS: Windows XP SP3
Server OS: Windows 2000 Server
Delphi: Delphi 7.1
Oracle Server: 10g(Windows版)
Oracle Client: 11g

対象テーブル: 37 項目 150万件 のデータ中 10万件をアクセス(select * from XXX where rownum <= 100000)

2) 設定(既定値以外)

TADOConnection:
接続文字列: Provider=MSDAORA.1;Password=YYYY;User ID=XXXX;Data Source=ZZZZ;Persist Security Info=True

TADODataset:
ExeciteOptions = [eoAsyncFetchNonBlocking]
Prepared = True
CursorType = ctStatic

TClientDataset:
PacketRecords = 50

----------
東京都 日野市 中村拓男

Reply all
Reply to author
Forward
0 new messages