ODBC を使用して SQL Server 2008 R2 インスタンスに接続していますが、接続で MARS が有効になっていると、SELECT クエリのパフォーマンスが大幅に低下します。さまざまなドライバー バージョン (SQL Server Native Client 10.0、SQL Server Native Client 11.0) を試しましたが、MARS 接続は常に非常に遅くなります。インターリーブなしで一度に 1 つのクエリしか実行していないため、MARS 接続でのクエリにかかる時間は、MARS をオフにした場合と同じであると予想されます。
SELECT クエリについて: 私はまだ他のクエリを調べていませんが、複数の結合を持つこの 1 つのクエリは、MARS をオンにすると遅くなります。クエリは 600K+ 行を返します。クエリをさらに下に貼り付けました。
単純なワークフロー: a) ODBC を使用して SQL Server 2008 R2 インスタンスに接続する b) SQL クエリを準備する c) SQLExecute d) SQL_NO_DATA が返されるまで、SQLFetch を複数回実行する
MARS がオフの場合: SQLExecute には約 7 秒かかります SQL_ATTR_ROW_ARRAY_SIZE が 100 に設定されている場合、SQLFetch は 6000 回以上呼び出され、合計フェッチ時間 (6000 回以上の SQLFetch 呼び出し全体) は 300 ミリ秒未満です アプリケーションは通常、完全な結果セット (600K+ 行) を取得します) 7.5 秒 (つまり、クエリの発行から最後の行の受信まで)。
MARS がオンの場合: SQLExecute には約 7 秒かかります。SQL_ATTR_ROW_ARRAY_SIZE が 100 に設定されている場合、SQLFetch は 6000 回以上呼び出され、合計フェッチ時間は 30 秒以上になります。さまざまな行サイズを試してみましたが、行サイズがより大きな数値に設定されると、各 SQLFetch 呼び出しに費やされる時間が増加するため、合計フェッチ時間は通常 30 秒以上です。私のアプリケーションは通常、約 40 秒 (つまり、クエリの発行から最後の行の受信まで) で完全な結果セット (60 万行以上) を取得します。
SQL_ATTR_CONCURRENCY、SQL_ATTR_CURSOR_SCROLLABLE、および SQL_ATTR_CURSOR_SENSITIVITY など、さまざまな種類のカーソル (SQL Server 固有の FAST FORWARD-ONLY カーソルを含む) を試しました。さまざまな行フェッチ サイズも試しました。しかし、MARS を有効にしてもクエリのパフォーマンスを向上させることはできませんでした。
MARS はカーソルを使用しているように感じますが、MARS がオフの場合はデフォルトの結果セット (「firehose カーソル」) が使用されます。ただし、Microsoft のドキュメントでは、MARS が有効になっている場合、デフォルトの結果がデフォルトであると主張されています。
私が使用しているクエリは以下のとおりです。クエリで使用される各列のデータ型は指定していませんが、ここでは省略します。この問題を解決するためにその情報が必要な場合は、間違いなく提供できます。
私のクエリには、MARS が既定の結果セットを使用しない原因となっている特性があるのでしょうか? MARS でクエリを高速化するためにできることはありますか? アプリケーションで MARS を有効にする必要があります。
SELECT [G].[iteration] AS [iter],
[A].[area] AS [area],
[B].[status] AS [status],
DATEADD(minute, DATEDIFF(minute, 0, [B].[dt]), 0) AS [mydate],
MAX([Z].[title]) AS [title1],
MIN([Z].[title]) AS [title2],
MAX((CASE
WHEN 0 = ISNUMERIC(CAST([G].[estimate] AS VARCHAR)) THEN NULL
ELSE CAST(CAST([G].[estimate] AS VARCHAR) as float) END)) AS [calculation]
FROM [dbo].[Z] [Z]
INNER JOIN [dbo].[A] [A] ON ([Z].[idA] = [A].[idA])
INNER JOIN [dbo].[B] [B] ON ([Z].[idB] = [B].[idB])
INNER JOIN [dbo].[C] [C] ON ([Z].[idC] = [C].[idC])
INNER JOIN [dbo].[D] [D] ON ([Z].[idFF] = [D].[idFF])
INNER JOIN [dbo].[E] [E] ON ([Z].[idP] = [E].[idP])
LEFT JOIN [dbo].[F] [F] ON ([Z].[idB] = [F].[idB])
LEFT JOIN [dbo].[G] [G] ON ([Z].[idB] = [G].[idB])
LEFT JOIN [dbo].[H] [H] ON ([B].[idQ] = [H].[idQ])
INNER JOIN [dbo].[J] [J] ON ([Z].[idB] = [J].[idJ])
WHERE (([A].[area] >= 'AA') AND ([A].[area] <= 'ZZ'))
GROUP BY [G].[iteration],
[A].[area],
[B].[status],
DATEADD(minute, DATEDIFF(minute, 0, [B].[dt]), 0)