更新: SQLExecute
の意味に関する説明を追加しました Accessが準備されたクエリをどのように処理しているか。ありがとう、ボブ!
ODBCリンクテーブルのレコードを参照および表示する場合、Accessは何をしますか?
ODBCトレースシリーズの第2部では、レコードセットタイプがODBCリンクテーブル内に与える影響に焦点を当てます。前回の記事では、ODBC SQLトレースをオンにする方法を学び、出力を確認できるようになりました。少し試してみた方は、AccessクエリとAccessが生成するODBCSQLステートメントがあまり似ていないことに気付いたかもしれません。また、タイプがSELECTクエリの動作にどのように影響するかについても詳しく説明し、スナップショットやダイナセットなどのレコードセットのさまざまなバリエーションについても調べます。
フォローしたい場合は、ここで提供されているサンプルデータベースを使用できます。
SELECTクエリでのRecordsetタイプの影響
レコードセットの種類は、AccessがODBCデータソースと通信する方法に大きな影響を与えます。フォームデザインビューまたはクエリデザインビューで、レコードセットの種類を設定できることに気付いたかもしれません。デフォルトでは、Dynaset
に設定されています 。
VBAには、さらにいくつかのオプションがありますが、今のところ心配する必要はありません。正確にDynaset
とは何かを理解することから始めましょう およびSnapshot
最初を意味します。あまり使用されないタイプのSnapshot
から始めます。 最初。
スナップショットタイプのレコードセット
Snapshot
とても簡単です。これは基本的に、クエリの実行時に結果のスナップショットを取得することを意味します。通常、これはAccessが結果を更新できないことも意味します。ただし、Accessがスナップショットベースのレコードセットを使用してソースをクエリする方法を見てみましょう。次のように新しいAccessクエリを作成できます:
AccessクエリのSQLビューに表示されるSQLは次のとおりです。
SELECT Cities.* FROM Cities;クエリを実行してから、
sqlout.txt
を確認します。 ファイル。読みやすくするためにフォーマットされた出力は次のとおりです。 SQLExecDirect: SELECT "CityID" ,"CityName" ,"StateProvinceID" ,"Location" ,"LatestRecordedPopulation" ,"LastEditedBy" ,"ValidFrom" ,"ValidTo" FROM "Application"."Cities"Accessのクエリで記述した内容と、AccessがODBCに送信した内容との間にわずかな違いがありました。これを分析します。
- Accessはスキーマ名でテーブルを修飾しました。明らかに、Access SQLダイアレクトでは、これは同じようには機能しませんが、ODBC SQLダイアレクトでは、正しいテーブルから選択していることを確認すると便利です。これは
SourceTableName
によって管理されます プロパティ。 - Accessは
Cities.*
のコンテンツを拡張しましたFields
に基づいてAccessがすでに認識しているすべての列の列挙リストに 基になるTableDef
のコレクション オブジェクト。 - アクセスは
"
を使用しました 識別子を引用します。これは、ODBCSQLダイアレクトが期待するものです。 Access SQLとTransact-SQLはどちらも括弧を使用して識別子を引用しますが、これはODBCSQLダイアレクトの有効な構文ではありません。
したがって、テーブルのすべての列を選択する単純なスナップショットクエリのみを実行しましたが、Accessは、AccessクエリデザインビューまたはSQLビューに配置したものと、Accessが実際にデータに出力するものとの間でSQLに多くの変換を行うことがわかります。ソース。ただし、この場合はほとんど構文上のものであるため、元のAccessクエリとODBCSQLステートメントのSQLステートメントに実際の違いはありません。
トレースはSQLExecDirect
も追加しました SQLステートメントの開始時。他のいくつかの例を見てから、その例に戻ります。
ダイナセットタイプのレコードセット
同じクエリを使用しますが、プロパティをデフォルトのDynaset
に戻します。 。
もう一度実行すると、sqlout.txt
から何が得られるかがわかります。 。繰り返しになりますが、読みやすいようにフォーマットされています:
SQLExecDirect: SELECT "Application"."Cities"."CityID" FROM "Application"."Cities" SQLPrepare: SELECT "CityID" ,"CityName" ,"StateProvinceID" ,"Location" ,"LatestRecordedPopulation" ,"LastEditedBy" ,"ValidFrom" ,"ValidTo" FROM "Application"."Cities" WHERE "CityID" = ? SQLExecute: (GOTO BOOKMARK) SQLPrepare: SELECT "CityID" ,"CityName" ,"StateProvinceID" ,"Location" ,"LatestRecordedPopulation" ,"LastEditedBy" ,"ValidFrom" ,"ValidTo" FROM "Application"."Cities" WHERE "CityID" = ? OR "CityID" = ? OR "CityID" = ? OR "CityID" = ? OR "CityID" = ? OR "CityID" = ? OR "CityID" = ? OR "CityID" = ? OR "CityID" = ? OR "CityID" = ? SQLExecute: (MULTI-ROW FETCH) SQLExecute: (MULTI-ROW FETCH)うわー、たくさんのことが起こっています!これは、スナップショットタイプのレコードセットよりも間違いなくおしゃべりです。それらを1つずつ見ていきましょう。
最初のものはCityID
のみを選択します 桁。これがテーブルの主キーですが、さらに重要なのは、Accessがその側で使用しているインデックスです。これは、後でビューを調査するときに重要になります。 Accessはこのクエリを使用してキーを取得し、後で他のクエリに入力するために使用します。
2番目のステートメントは、新しいWHERE
があることを除けば、元のスナップショットクエリにさらに近いものです。 CityID
での句フィルタリング 桁。このことから、単一行のフェッチであることがわかります。最初のクエリで取得したキーを使用して、このクエリの残りの列を収集できます。そのプリペアドステートメントが実行されるたびに、SQLExecute: (GOTO BOOKMARK)
が表示されます。 。
しかし、すべての行に対してこれを実行する必要がある場合、これは非効率的です…そして、次のクエリが出てくるところです。3番目のステートメントは2番目のステートメントに似ていますが、10個の述語があります。この準備されたクエリは、各SQLExecute: (MULTI_ROW FETCH)
で実行されます。 。つまり、フォームやデータシートを読み込んだり、VBAコードでレコードセットを開いたりすると、Accessは単一行バージョンまたは複数行バージョンのいずれかを使用し、最初から取得したキーを使用してパラメーターを入力します。クエリ。
バックグラウンドのフェッチと再同期
ちなみに、フォームやデータシートを開いたときに、ナビゲーションバーに「XofY」が表示されないことに気付いたことがありますか?
これは、Accessが最初のクエリからの結果の収集が完了するまで、その数を知ることができないためです。そのため、大量のデータを返すクエリを開くのが非常に高速であることに気付くことがよくあります。 Accessがバックグラウンドで行をフェッチしている間は、レコードセット全体の小さなウィンドウのみをプレビューしています。 「最後に移動」ボタンをクリックすると、Accessがフリーズする場合があります。ナビゲーションバーに「XofY」が表示される前に、最初のクエリですべてのキーのフェッチが完了するまで待つ必要があります。
したがって、Accessを使用すると、大きなレコードセットでもすばやく開くことができるという錯覚を味わうことができます。ダイナセットタイプのレコードセットであり、通常はユーザーにとって優れたエクスペリエンスです。
最後に、SQLExecDirect
という3種類の実行があったことに注意する必要があります。 、SQLPrepare
およびSQLExecute
。前者の場合、パラメータがないことがわかります。クエリはそのままです。ただし、クエリをパラメータ化する必要がある場合は、最初にSQLPrepare
を使用して準備する必要があります。 その後、SQLExecute
で実行されます 提供されたパラメーターの値を使用します。 SQLExecute
に実際に渡された値を確認できません Accessに表示される内容から推測できますが、ステートメント。単一の行をフェッチしたかどうかしかわかりません(SQLExecute: (GOTO BOOKMARK)
を使用) または複数の行(SQLExecute: (MULTI-ROW FETCH)
を使用 )。 Accessは、複数行バージョンを使用してバックグラウンドフェッチを実行し、レコードセットを段階的に埋めますが、単一行バージョンを使用して1行のみを埋めます。これは、連続フォームまたはデータシートビューとは対照的に、単一のフォームビューの場合、または更新後の再同期に使用する場合があります。
ナビゲート
レコードセットが十分に大きい場合、Accessはすべてのレコードのフェッチを完了できない可能性があります。前述のように、ユーザーにはできるだけ早くデータが表示されます。通常、ユーザーがレコードセット内を前方に移動すると、Accessは、バッファーをユーザーの前に保つために、ますます多くのレコードをフェッチし続けます。
しかし、ユーザーがナビゲーションコントロールに移動し、そこに100と入力して、100行目にジャンプするとしますか?
その場合、Accessは次のクエリを送信します…
SQLExecute: (MULTI-ROW FETCH) SQLExecute: (GOTO BOOKMARK) SQLExecute: (MULTI-ROW FETCH) SQLExecute: (MULTI-ROW FETCH)Accessが、レコードセットを開いたときに作成した準備済みのステートメントをどのように使用するかに注意してください。最初のクエリのキーがすでにあるため、どちらが「100番目」の行であるかを知ることができます。より具体的な例を使用します。
CityID
があったとします 1、3、4、5…99、100、101、102から始まり、CityID = 2
のレコードはありません 。最初のクエリでは、CityID
101は100行目になります。したがって、ユーザーが100にジャンプすると、Accessは最初のクエリで100行目を検索し、CityID
であることを確認します。 101、次にその値を取得し、それをSQLExecute: (GOTO BOOKMARK)
にフィードします。 すぐにそのレコードに移動します。次に、次の10個のレコードを調べ、それらの後続のCityID
を使用します。 バッファを複数のSQLExecute: (MULTI-ROW FETCH)
で埋める 。単一行フェッチの前に複数行フェッチがあることに気付いたかもしれません。 Accessは、実際には複数行のフェッチで101行目から110行目をフェッチし、次の単一行フェッチで100番目のレコードをフェッチしています。 Accessが100番目の行のデータを取得したら、ユーザーをそこに連れて行き、その100番目の行の周りのバッファーをいっぱいにし始めます。これにより、ユーザーは11番目から99番目のすべてのレコードをロードするのを待たずに100番目の行を表示できます。また、ユーザーが要求する前にAccessがバックグラウンドで既にロードしているため、ユーザーが新しい位置から前または次をクリックしたときに、ユーザーは明らかに迅速なブラウジングエクスペリエンスを利用できます。これは、低速のネットワークでも高速であるという錯覚を与えるのに役立ちます。
ただし、ユーザーがフォームを開いたままアイドル状態にした場合でも、Accessはバックグラウンドフェッチとバッファーの更新の両方を実行し続け、ユーザーに古いデータが表示されないようにします。これは、[クライアント設定]タブの[詳細設定]セクションにある[オプション]ダイアログのODBC設定によって管理されます。
ODBC更新間隔のデフォルトは1500秒ですが、変更できます。 VBAを介して変更することもできます。
結論:分厚いまたはおしゃべり
dynasetタイプのレコードセットは更新可能ですが、スナップショットタイプのレコードセットは更新できない主な理由は、Accessがレコードセットの行をサーバーからの最新バージョンに置き換えることができるためです。これは、Accessがレコードセットの行を選択する方法を知っているためです。単一行。そのため、Accessは2つのODBCクエリを管理する必要があります。 1つはキーをフェッチし、もう1つは特定のキーの行の実際の内容をフェッチします。その情報は、スナップショットタイプのレコードセットには存在しませんでした。大量のデータを取得しました。
さらに多くのレコードセットがありますが、2つの主要なタイプのレコードセットを調べました。ただし、その他は、ここで取り上げた2つのタイプの単なる変形です。ただし、今のところ、スナップショットを使用することは、ネットワーク通信で分厚いことであることを覚えておくだけで十分です。一方、ダイナセットを使用するということは、おしゃべりになることを意味します。どちらにも浮き沈みがあります。
たとえば、スナップショットレコードセットは、データを取得した後、サーバーとそれ以上通信する必要はありません。レコードセットが開いたままである限り、Accessはローカルキャッシュ内を自由に移動できます。アクセスは、ロックを保持する必要がないため、他のユーザーをブロックする必要もありません。ただし、スナップショットレコードセットは、すべてのデータを事前に収集する必要があるため、必然的に開くのに時間がかかります。すべてのデータを読み取る場合でも、大規模なレコードセットには適さない場合があります。
100ページの大きなAccessレポートを作成しているとすると、通常はdynasetタイプのレコードセットを使用する価値があります。最初のページをレンダリングするのに十分になるとすぐに、プレビューのレンダリングを開始できます。これは、プレビューのレンダリングを開始する前に、すべてのデータを取得するまで待機するよりも優れています。ダイナセットのレコードセットはロックをかける場合がありますが、通常は短時間です。 Accessがローカルキャッシュを再同期するのに十分な長さです。
ただし、ダイナセットタイプのレコードセットを使用してネットワーク経由でAccessが送信するリクエストの数を考えると、ネットワークレイテンシが低い場合、Accessのパフォーマンスがそれに応じて低下することが簡単にわかります。 Accessが一般的な方法でデータソースを編集および更新できるようにするには、Accessが単一の行を選択および変更するためのキーを追跡する必要があります。これについては、今後の記事で説明します。次の記事では、並べ替えとグループ化がダイナセットタイプのレコードセットにどのように影響するか、およびAccessがダイナセットタイプのレコードセットに使用するキーをどのように決定するかを見ていきます。
Microsoft Accessの詳細については、773-809-5456の専門家に電話するか、[email protected]に電子メールを送信してください。