我们正在测试来自jTDS和Microsoft的JDBC驱动程序,并且我们遇到了查询执行中不必要的暂停。我们的应用程序打开了许多ResultSet,并且每个只提取几行。每个查询选择大约100k行,但我们只获取大约50(这足以填充页面)。问题是第一个查询之后的每个查询都包含大约2秒的暂停,驱动程序将前一个ResultSet中的所有行加载到临时存储(内存或磁盘),以便稍后遍历它们。因为在最糟糕的情况下我们有大约6个查询,所以会有大约10秒的暂停,这会使应用程序对用户没有响应。 MSSQL版本是2005年。
要删除此类暂停,我们尝试通过Microsoft JDBC驱动程序的连接字符串参数启用MARS(多个活动结果集)(由于缺少文档,我们尝试了https://sites.google.com/site/sqlconnect/sql2005strings上列出的所有内容)。连接字符串示例:
JDBC:SQLSERVER:// TESTDBMACHINE;实例名= S2005;的databaseName = SAMPLEDB; MarsConn =是
但他们都没有解决问题。 Microsoft JDBC驱动程序似乎接受任何连接字符串 - 如果您通过PleaseBeFast = yes替换MarsConn = yes,MS驱动程序将忽略该参数,甚至不记录该事实。我不知道MARS是否只是一个客户端功能,它只缓存先前活动结果集中的行,或者它是否是服务器功能。我甚至不知道如何从服务器端检测给定连接是否使用MARS。如果您对此发表评论,欢迎提出。
暂停的另一个解决方案是使用可滚动(双向)结果集。这样可以消除暂停,但会使获取时间减慢80%并且消耗更多网络。我们现在正在考虑实现一个JDBC连接包装器,它保留了一组实际连接,并自动向不同的“ResultSet free”连接发出查询。但这有点麻烦,因为我们需要在每个连接和它的活动ResultSet之间保持链接。此外,它会消耗更多来自服务器的连接,并可能给DBA带来麻烦。如果存在活动事务,则此解决方案无效,必须在同一连接上发出所有查询。
您是否知道可以从第二次和后续查询执行中删除暂停的一些参数,配置,特定API,链接或技巧?
答案 0 :(得分:1)
修复你的SQL查询!为什么只使用100k行的前50个左右?使用TOP 100
或类似的东西!应用程序没有理由过滤100k行,这是数据库的工作。
答案 1 :(得分:0)
更重要的是,客户端的困境是服务器端发生的事情。由于您发出查询然后停止读取结果,服务器将不得不在执行过程中暂停查询,因为网络缓冲区已满并且没有空间将结果写入。在执行过程中暂停的查询正在消耗资源的批次:内存,锁,最重要的是,工作线程(其中有very few个)。
仅针对您需要的数据发出查询,使用所有数据,释放连接,更重要的是释放服务器资源。如果您的查询很复杂,请返回绘图板并重新设计您的数据模型,以便有效地正确回答您从中请求的查询。现在你正在咆哮错误的树,你只是在问如何让糟糕的情况变得更糟。
答案 2 :(得分:-1)
我们使用SQL Server驱动程序(Native Client 10 - sqlncli10.dll)创建了一个ODBC数据源。此ODBC数据源配置为启用MARS(键HKEY_CURRENT_USER\Software\ODBC\ODBC.INI\ datasource
,MARS_Connection
的值必须为Yes
)。然后我们使用了Sun的JDBC-ODBC桥,并且瞧!暂停消失了,令人惊讶的是,获取时间变得比JTDS和MSSQL纯Java JDBC驱动程序更快!
根据http://msdn.microsoft.com/en-us/library/ms345109(SQL.90).aspx,MARS是服务器辅助功能。纯Java驱动程序(来自JTDS和MSSQL)似乎不支持基于服务的MARS(至少我们在许多配置更改后无法启用它)。因为我们的大多数使用MSSQL Server的用户都在Windows上运行(毫不奇怪),我们即将从JTDS切换到JDBC-ODBC。 Native Client ODBC驱动程序和JDBC-ODBC桥接器似乎都是成熟的,全功能的和最新的解决方案,所以我想应该没有问题。如果您了解一些,请发表评论!
基于Linux的用户仍将使用JTDS。从现在开始我们知道MARS是一个服务器辅助功能,我们将填写JTDS和Microsoft的功能请求,以支持其纯Java JDBC驱动程序中的MARS。