sql-server – 使用XML阅读器优化计划
我已经从问题中显示的版本中反转了连接的书面顺序,因为连接提示(上面的INNER HASH JOIN)也强制整个查询的顺序,就像已经指定了FORCE ORDER一样.必须进行反转以确保Expr1000出现在探头侧.执行计划的有趣部分是: 使用探针端定义的表达式,该值被缓存: Expr1000的评估仍然推迟到第一个操作符需要该值(上面的堆栈跟踪中的启动过滤器),但计算的值被缓存(CValHashCachedSwitch)并重新用于XML读取器和流聚合的后续调用.下面的堆栈跟踪显示了XML Reader重用的缓存值的示例. 当强制连接顺序使得Expr1000的定义出现在散列连接的构建端时,情况就不同了: SELECT CAST ( REPLACE ( REPLACE ( XEventData.XEvent.value ('(data/value)[1]','</victim-list><process-list>') AS XML) AS DeadlockGraph FROM (SELECT CAST (target_data AS XML) AS TargetData FROM sys.dm_xe_session_targets st INNER HASH JOIN sys.dm_xe_sessions s ON s.address = st.event_session_address WHERE [name] = 'system_health') AS Data CROSS APPLY TargetData.nodes ('//RingBufferTarget/event') AS XEventData (XEvent) WHERE XEventData.XEvent.value('@name','varchar(4000)') = 'xml_deadlock_report' 在开始探测匹配之前,散列连接完全读取其构建输入以构造哈希表.因此,我们必须存储所有值,而不仅仅是从计划的探测端处理每个线程的值.因此,散列连接使用tempdb工作表来存储XML数据,并且后来运算符对Expr1000的结果的每次访问都需要昂贵的tempdb之旅: 以下显示了慢速访问路径的更多详细信息: 如果强制合并连接,则对输入行进行排序(阻塞操作,就像对散列连接的构建输入一样),从而导致类似的安排,因为数据的大小需要通过tempdb排序优化的工作表进行慢速访问. 由于执行计划中不明显的各种原因,操纵大型数据项的计划可能会出现问题.使用散列连接(在正确的输入上使用表达式)不是一个好的解决方案.它依赖于未记录的内部行为,但不保证它将在下周以相同的方式工作,或者在稍微不同的查询上. 消息是XML操作可能是当今优化的棘手问题.在粉碎之前将XML写入变量或临时表是一个比上面显示的更加可靠的解决方法.一种方法是: DECLARE @data xml = CONVERT ( xml,( SELECT TOP (1) dxst.target_data FROM sys.dm_xe_sessions AS dxs JOIN sys.dm_xe_session_targets AS dxst ON dxst.event_session_address = dxs.[address] WHERE dxs.name = N'system_health' AND dxst.target_name = N'ring_buffer' ) ) SELECT XEventData.XEvent.value('(data/value)[1]','varchar(max)') FROM @data.nodes ('./RingBufferTarget/event[@name eq "xml_deadlock_report"]') AS XEventData (XEvent) WHERE XEventData.XEvent.value('@name','varchar(4000)') = 'xml_deadlock_report'; 最后,我只想在下面的评论中添加Martin非常漂亮的图形: (编辑:晋中站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |