针对 sys.fn_dblog 优化查询

Cra*_*ein 5 performance sql-server transaction-log query-performance

寻求帮助改进查询。此查询用于查看 LDF 文件中的最后 N 个事务,然后添加一些有用的信息,如用户、开始时间、查询文本等。

这是查询:

SET NOCOUNT ON
DECLARE @LSN NVARCHAR(46)
DECLARE @LSN_HEX NVARCHAR(25)
DECLARE @tbl TABLE (id INT identity(1,1), i VARCHAR(10))
DECLARE @stmt VARCHAR(256)
DECLARE @NUMOFTRANSACTIONS AS INT = 3;

-- common table expression to get the last N LSNs from the LDF
with currentlsns as (
SELECT TOP(@NUMOFTRANSACTIONS) [Current LSN] FROM fn_dblog(NULL, NULL) WHERE [Transaction SID] IS NOT NULL order by [Transaction ID] DESC
)
-- set the @LSN to the lowest because we are reading forward
SELECT @LSN = MIN([Current LSN]) from currentlsns


-- Convert @LSN to HEX for use in fn_dblog
SET @stmt = 'SELECT CAST(0x' + SUBSTRING(@LSN, 1, 8) + ' AS INT)'
INSERT @tbl EXEC(@stmt)
SET @stmt = 'SELECT CAST(0x' + SUBSTRING(@LSN, 10, 8) + ' AS INT)'
INSERT @tbl EXEC(@stmt)
SET @stmt = 'SELECT CAST(0x' + SUBSTRING(@LSN, 19, 4) + ' AS INT)'
INSERT @tbl EXEC(@stmt)

SET @LSN_HEX =
 (SELECT i FROM @tbl WHERE id = 1) + ':' + (SELECT i FROM @tbl WHERE id = 2) + ':' + (SELECT i FROM @tbl WHERE id = 3)

-- insert everything into a temp table so we only refer to fn_dblog once
IF OBJECT_ID('tempdb..#transactions') IS NOT NULL 
DROP TABLE #transactions

SELECT * INTO #transactions 
FROM fn_dblog (@LSN_HEX, NULL)


-- now show last N transactions and some connection, query info for those transactions
SELECT fd.SPID, es.login_name, text, Description, Operation, Context, [Log Reserve],AllocUnitName,[Begin Time],[Transaction Name], 
[End Time], [Transaction Begin],[Number of Locks] 
FROM
    #transactions,
    (   SELECT
            [Transaction ID] AS [tid],
            [Transaction SID],
            SPID
        FROM #transactions
        WHERE
        [Transaction SID] IN (select top(@NUMOFTRANSACTIONS) [Transaction SID] FROM #transactions WHERE [Transaction SID] IS NOT NULL order by [Transaction ID] desc)
   ) [fd]
INNER JOIN sys.dm_exec_connections c on c.session_id = fd.SPID 
LEFT OUTER JOIN sys.dm_exec_sessions es ON es.session_id = fd.SPID
CROSS APPLY sys.dm_exec_sql_text(c.most_recent_sql_handle) as st
WHERE
    [Transaction ID] = [fd].[tid]
    AND [Transaction ID] IN (select top(@NUMOFTRANSACTIONS) [Transaction ID] FROM #transactions WHERE [Transaction SID] IS NOT NULL order by [Transaction ID] desc
 )
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

这部分查询花费的时间太长

-- common table expression to get the last N LSNs from the LDF
with currentlsns as (
SELECT TOP(@NUMOFTRANSACTIONS) [Current LSN] FROM fn_dblog(NULL, NULL) WHERE [Transaction SID] IS NOT NULL order by [Transaction ID] DESC
)
-- set the @LSN to the lowest because we are reading forward
SELECT @LSN = MIN([Current LSN]) from currentlsns
Run Code Online (Sandbox Code Playgroud)

我只想从事务 SID 不为空的最后一个 LSN 中获取第 N 个。我能想到的唯一方法是创建一个 CTE 并插入最后 N 个匹配的 LSN。

问题: 找到 [Transaction SID] 不为空的最后 N 个当前 LSN 的更好方法是什么?

sta*_*ray 1

SELECT * 进入 dbo.dblog

FROM fn_dump_dblog ( NULL, NULL, N'DISK', 1, N'C:\tranlog.trn', 默认, 默认, 默认, 默认, 默认, 默认, 默认, 默认, 默认, 默认, 默认, 默认, 默认,默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认,默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认、默认) ; 去

然后给表dbo.dblog添加索引等。

  • 我不知道。如果保罗·兰德尔说是这样,那么它就是这样。您始终可以将 tranlog 复制到您的个人计算机并在那里执行,而不是在生产服务器上执行。 (2认同)