【问题标题】:FOR XML PATH Performance Improvement challengeFOR XML PATH 性能改进挑战
【发布时间】:2017-10-20 21:52:19
【问题描述】:

我正在通过 FOR XML PATH('') 函数改进使用 20 列的视图性能。该视图还使用非集群视图 CTE、子查询和 CAST 函数调用其他字段,但此时我并不关心它们。

视图是非集群视图,每 5 分钟由作业选择一次,以向客户端应用程序显示新数据。因此,底层源表每 5 分钟更新和插入一次。

我已经在合适的地方创建了聚集索引和非聚集索引。在创建相应索引之前和之后测试源表上的各个视图组件,然后选择最佳路由。所以,我在索引方面做得很好。所有索引的填充因子值几乎都是 100。

我的假设是查询速度变慢了很多,因为我在视图中的 20 列上使用了 FOR XML PATH ('')...

CREATE VIEW MyView
AS 
col1,
Col2,
(SELECT CAST(Mytbl.[EmpId] AS NVARCHAR(50)) + '|' FROM MyDB.dbo.Mytbl_Optimized AS t1 (NOLOCK) 
            LEFT OUTER JOIN AnotherDB.dbo.Another-tbl AS t2 WITH (NOLOCK)
            ON t1.EmpId = t2.EmpId 
WHERE AnotherDB.dbo.Table3.MyId = t1.MyId
FOR XML PATH('')) AS MyConcatenatedID
FROM AnotherDB.dbo.Table3 

我尝试使用 CASE 语句来确定每列是否带有 FOR XML PATH('') 任何内容以逐行连接,然后仅在 is 具有 2 个或更多值时使用 FOR XML PATH('')连接到一个字符串。但是我预期的表现很糟糕......

,CASE
        WHEN 
            (SELECT
                LEN(EmpId) - LEN(REPLACE(EmpId, '|', '')) AS [CountOfConcatinated_EmpId] 
            FROM ISSearch..SearchBid WITH (NOLOCK)
            ) > 1  -- this determis if values are concatenated or not. 
        THEN 
            (SELECT CAST(Mytbl.[EmpId] AS NVARCHAR(50)) + '|' FROM MyDB.dbo.Mytbl_Optimized AS t1 (NOLOCK) 
                LEFT OUTER JOIN AnotherDB.dbo.Another-tbl AS t2 WITH (NOLOCK)
                ON t1.EmpId = t2.EmpId 
                WHERE AnotherDB.dbo.Table3.MyId = t1.MyId
        FOR XML PATH(''))

        ELSE
            (SELECT CAST(Mytbl.[EmpId] AS NVARCHAR(50)) + '|' FROM MyDB.dbo.Mytbl_Optimized AS t1 (NOLOCK) 
                LEFT OUTER JOIN AnotherDB.dbo.Another-tbl AS t2 WITH (NOLOCK)
                ON t1.EmpId = t2.EmpId 
                WHERE AnotherDB.dbo.Table3.MyId = t1.MyId)
        END AS EmpId 
FROM AnotherDB.dbo.MyView;

我现在正在考虑将所有 20 列的 FOR XML PATH('') 函数字符串连接为视图上的单独列的缓存选项,但它需要不断更新(每 5 分钟一次)。

有任何想法或替代解决方案吗?

【问题讨论】:

  • 我假设AnotherDB.dbo.Another-tbl as t2 是一个虚拟名称,但这些是否需要左连接(或根本没有)?至少在提供的查询中,他们似乎没有做任何事情。我想知道的其他几件事:1)MyConcatednatedId 的每个值连接了多少行 2)Table3 中有多少行 3)现在执行速度有多慢 4)你有多快需要吗?
  • 使用Paste The Plan @ brentozar.com 分享您的执行计划,以下是说明:How to Use Paste the Plan

标签: sql-server view query-performance correlated-subquery for-xml-path


【解决方案1】:

含糊的问题得到含糊的答案,但这里是这样。

我同意,似乎所有FOR XML 连接可能都在起作用(当然没有看到执行计划或完整的数据库架构,这几乎是我唯一需要做的事情)。这里有很多未知数可能会改变建议。如果您可以包含查询计划和 IO 统计信息,那将有所帮助。

我也没有声称知道具体原因,或者您是否需要在运行时使用视图或连接值,但这里有一些探索性问题:

  1. dbo.Table3 中有多少行(您要连接值的基表?
  2. 每个MyConcatenatedId 值连接了多少行?
  3. 现在执行速度有多慢,需要多快?
  4. 此视图每分钟/秒大约读取多少次?
  5. dbo.another-tbl 似乎在提供的子查询中没有做任何事情(也许它在真实版本中做了)。你需要那个吗?需要左连接吗?

我最初的想法是,如果这需要高性能而不是,请不要使用视图。如果您必须使用视图,可以尝试使用诸如 NOEXPAND 之类的索引提示,您有哪些替代方案?

不要序列化:我很难想象需要在运行时序列化大量数据的场景。如果可能,在数据放入时返回数据集或序列化数据。

  • 优点
    • 在数据库方面很容易
  • 缺点
    • 可能无法满足您的需要

持久化表/提前做工作:可能也需要触发器,但是当底层数据发生变化时,将其写入持久化表并从中读取。或者在 Change Data Capture 之类的地方排队更改,然后异步处理这些更改

  • 优点
    • 快速阅读
  • 缺点
    • 维护和触发器的痛苦可能会增加繁重的开销

过程:除非您每次调用都需要所有数据,否则请考虑创建一个可以参数化的过程,以便在需要时只提取您需要的东西。一个视图仅限于单个查询,并且这种复杂性查询的统计信息可能很快就会变成垃圾。一个过程可以将语句单独分离成更小的块,这样您就可以更频繁地获得一致且更快的计划。

  • 优点
    • 比视图更可定制,您可以做更多优化操作
  • 缺点
    • 无法直接查询它们(尽管我认为这不是不使用它们的好理由)

【讨论】:

  • 可以使用(可能是嵌套的?)openquery 恶作剧查询存储过程:D
猜你喜欢
  • 1970-01-01
  • 2021-02-10
  • 1970-01-01
  • 2015-05-02
  • 1970-01-01
  • 2018-01-03
  • 2014-04-13
  • 2022-10-04
  • 2011-09-21
相关资源
最近更新 更多