通过 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 查询强制执行查询超时?
如何最好地从 Java/JDBC 中的 SQL 查询中检索 SELECT COUNT(*) 的结果 - Long?大整数?