【发布时间】: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