启用MARS时,ODBC调用SQLFetch较慢

时间:2013-11-11 07:58:41

标签: sql-server sql-server-2008-r2 odbc

我们使用ODBC连接到SQL Server 2008 R2实例,并且在连接上启用MARS时,SELECT查询的性能明显变慢。我尝试了不同的驱动程序版本(SQL Server Native Client 10.0,SQL Server Native Client 11.0),但MARS连接总是慢得多。我希望MARS连接中的查询所花费的时间与MARS关闭所用的时间相同,因为我一次只运行一个查询而没有任何交错。

关于SELECT查询: 我还没有查看其他查询,但这个有多个连接的查询在MARS打开时速度较慢。查询返回600K +行。我已在下面进一步粘贴查询。

简单的工作流程 a)使用ODBC连接到SQL Server 2008 R2实例 b)SQLPrepare查询 c)SQLExecute d)SQLFetch多次,直到它返回SQL_NO_DATA

当MARS关闭时: SQLExecute大约需要7秒钟 当SQL_ATTR_ROW_ARRAY_SIZE设置为100时,SQLFetch被调用6000次以上,总提取时间(超过6000个SQLFetch调用)不到300毫秒 我的应用程序通常在7.5秒内获得完整的结果集(600K +行)(即从发出查询到接收最后一行)。

当MARS开启时: SQLExecute大约需要7秒钟 当SQL_ATTR_ROW_ARRAY_SIZE设置为100时,SQLFetch被调用6000次以上,总获取时间为30+秒。 我尝试了不同的行大小,但总提取时间通常为30+秒,因为当行大小设置为更高的数字时,每次SQLFetch调用所花费的时间会增加。 我的应用程序通常在大约40秒内(即从发出查询到接收最后一行)获得完整的结果集(600K +行)。

我尝试了不同的游标类型(包括SQL Server特定的FAST FORWARD-ONLY游标,包括和不包含自动提取),SQL_ATTR_CONCURRENCY,SQL_ATTR_CURSOR_SCROLLABLE和SQL_ATTR_CURSOR_SENSITIVITY。我也尝试了不同的行获取大小。但是,我无法在启用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)

1 个答案:

答案 0 :(得分:0)

  

我觉得MARS正在使用游标,而当MARS关闭时,正在使用默认结果集(“firehose游标”);虽然在Microsoft文档中声明默认结果是启用MARS时的默认结果。

MARS通常不会在TDS级别或更高级别更改数据库的操作,它充当套接字和TDS之间的多路复用层。虽然它不会改变仅前向提取中返回的数据量,但多路复用性质和相关的滑动窗口将需要更多的网络往返才能获得相同的数据。

也许你可以使用两个连接。一个在需要时启用MARS,另一个在需要最大吞吐量时没有它。