MFC(VS2010)のCDatabase/CRecordsetを介してODBCを使用するアプリケーションがあります。2つのバックエンドが実装されています。MSSQLとMySQL。
現在、MSSQL(Native Client 10.0で)を使用する場合、SELECTを使用したレコードの取得は低速リンク(VPNなど)を介して劇的に遅くなります。MySQL ODBCドライバーは、この厄介な動作を示しません。
例えば:
CRecordset r(&m_db);
r.Open(CRecordset::snapshot, L"SELECT a.something, b.sthelse FROM TableA AS a LEFT JOIN TableB AS b ON a.ID=b.Ref");
r.MoveFirst();
while(!r.IsEOF())
{
// Retrieve
CString strData;
crs.GetFieldValue(L"a.something", strData);
crs.MoveNext();
}
これで、MySQLドライバーを使用すると、すべてが正常に実行されます。クエリが返され、すべてが非常に高速になります。ただし、MSSQL Native Clientでは、すべてのMoveNext()でドライバーがサーバーと通信するため、処理速度が低下します。
サーバー側のカーソルが原因だと思いますが、無効にする方法が見つかりませんでした。私は使用してみました:
::SQLSetConnectAttr(m_db.m_hdbc, SQL_ATTR_ODBC_CURSORS, SQL_CUR_USE_ODBC, SQL_IS_INTEGER);
しかし、これも役に立ちませんでした。SQLプロファイラーにはまだsp_cursorfetch()などの実行時間の長いexecがあります。SQLAPIとバルクフェッチを使用した小さな参照プロジェクトも試しましたが、FetchNext()でも長時間ハングします(結果セットにレコードが1つしかない場合でも)。ただし、これはLEFT JOINS、テーブル値関数などを使用したクエリでのみ発生し ます。クエリはそれほど長くはかからないことに注意してください。同じ接続を介してSQL Studioを介して同じSQLを実行すると、妥当な時間で返されます。
質問1:どういうわけかネイティブクライアントを取得することは可能ですかすべての結果をローカルに「キャッシュ」するMySQLドライバーが行うように見えるのと同様の方法でローカルカーソルを使用しますか?
たぶんこれは完全に間違ったアプローチですが、他にこれを行う方法がわかりません。
必要なのは、SELECTから一度にすべてのデータを取得し、次のクエリまでサーバーと通信しないことです。レコードセットの更新、削除など、またはそのナンセンスについては気にしません。データを取得したいだけです。そのレコードセットを取得し、すべてのデータを取得して削除します。
質問2:ODBCを使用してMFCでデータを取得するためのより効率的な方法はありますか?