通过 JDBC 检索 SQL Server 查询统计信息

Posted

技术标签:

【中文标题】通过 JDBC 检索 SQL Server 查询统计信息【英文标题】:Retrieve SQL Server query statistics through JDBC 【发布时间】:2012-06-19 12:01:41 【问题描述】:

我想通过JDBC接口检索SQL Server在使用SET STATISTICS IO ON时返回的统计信息。

获取执行计划非常简单,因为在运行SET SHOWPLAN_XML ON 之后,调用Statement.execute() 的结果将是执行计划。使用 SET STATISTICS XML OFF 时,Statement 实例会返回第二个 ResultSet。

但是,在使用Statement.execute() 之前运行SET STATISTICS IO ON 时,只会返回查询结果。没有更多的结果集,没有任何警告。

有人知道我如何获得这些信息吗?它可能隐藏在哪里?

我尝试对 SQL Server 2005、SQL Server 2008R2 和 SQL Server 2012 使用 jTDS 以及 Microsoft 的 JDBC 驱动程序(3.0 和 4.0)。

我检查了查询返回的所有结果集(使用Statement.getMoreResults() 检查),以及Connection.getWarnings()Statement.getWarnings() 返回的警告对象。

【问题讨论】:

【参考方案1】:

SET SHOWPLAN_XML ON 将任何后续语句的结果集更改为计划而不是查询结果相反,SET STATISTICS IO ON 不会。

SET STATISTICS IO ON 让查询执行并将统计信息显示为消息。 见http://msdn.microsoft.com/en-us/library/ms131350.aspx

在 ADO.NET 中,SqlConnection 对象上有一个名为 InfoMessage 的事件,您可以在该事件上插入一个处理程序并获取服务器显示的任何消息,例如打印或 IO 统计信息。

我很快查看了 SQL Server 的 MS JDBC 驱动程序,但没有找到任何接近的东西,我发现最好的是:Is there a way to display PRINT results with SQL server JDBC driver?。 我的 Java 知识很薄弱,尽管 SQL Server 消息结果上的上述链接仅提及“SQL Server Native Client OLE DB 提供程序”,但其他驱动程序中可能存在类似的东西。


多看之后,我发现您可以让消息运行跟踪(使用探查器),并且该消息显示为“用户错误消息”事件类下的跟踪消息,其中包含您可以使用的 TransactionID用于将其与您的批次相关联。

在 SQL Server 的后台运行默认跟踪。 请参阅http://www.simple-talk.com/sql/performance/the-default-trace-in-sql-server---the-power-of-performance-and-security-auditing/ 和http://www.sqlservercentral.com/articles/sql+server+2005/64547/,您可能会在跟踪中插入您需要的事件,或者运行另一个事件然后从中读取。

说实话,希望你能找到更好的解决方案。

编辑:

我不知道为什么您可以使用 JDBC 函数获取打印消息但不能获取 IO 统计信息,但我可以按照我开始跟踪的方向提出其他建议。

您可以使用扩展事件来做到这一点,在正确的事件上放置一个句柄,然后使用以下内容读取跟踪:

首先在数据库上执行:

CREATE EVENT SESSION QueryStats ON SERVER
ADD EVENT sqlserver.error_reported
(
    ACTION(sqlserver.sql_text)
    WHERE (severity = 10
        AND state = 0
        AND user_defined = 0
        AND error = 3615)
)
ADD TARGET package0.ring_buffer
WITH(max_dispatch_latency = 1 seconds)
GO

然后围绕你的陈述:

ALTER EVENT SESSION QueryStats ON SERVER STATE = START

SET STATISTICS IO ON

select * from MyTable -- your statement(s)

SET STATISTICS IO OFF

WAITFOR DELAY '00:00:01'; -- you have to wait because you can't set under 1 second of max_dispatch_latency 
WITH QueryStats
AS (
    SELECT CAST(target_data AS xml) AS SessionData
    FROM sys.dm_xe_session_targets st
        INNER JOIN sys.dm_xe_sessions s ON s.address = st.event_session_address
    WHERE name = 'QueryStats'
)
SELECT
    error.value('(@timestamp)[1]', 'datetime') as event_timestamp
    ,error.value('(action/value)[1]', 'nvarchar(max)') as sql_text
    ,error.value('(data/value)[5]', 'varchar(max)') as [message]
FROM QueryStats d 
    CROSS APPLY SessionData.nodes ('//RingBufferTarget/event') AS t(error)
ALTER EVENT SESSION QueryStats ON SERVER STATE = STOP
GO

然后您将获得第二个包含 IO 统计信息的结果集。

不过,解决方案远未最终确定,因为需要消除等待时间并更好地确定跟踪范围,这可能是可能的。 您还可以让跟踪运行并在以后及时获取所有语句/IO 统计信息,具体取决于您打算如何处理这些。

【讨论】:

感谢您的回答。使用PRINT“发送”的消息可以使用提到的Statement.getWarnings()Connection.getWarnings() 检索。我已经用它来获取这些信息。但它们都没有返回 IO 统计信息。

以上是关于通过 JDBC 检索 SQL Server 查询统计信息的主要内容,如果未能解决你的问题,请参考以下文章

如何对通过 MS JDBC 驱动程序运行的 MS SQL Server 查询强制执行查询超时?

检索sql server中新插入行的值

如何最好地从 Java/JDBC 中的 SQL 查询中检索 SELECT COUNT(*) 的结果 - Long?大整数?

使用 PYMSSQL 通过 *** 从 SQL Server 检索数据

JDBC如何连接SQL Server数据库实现增删改查

使用 JDBC 根据用户输入从 SQL 数据库中检索数据? [复制]