我正在努力提高使用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分钟一次)。
任何想法或替代解决方案?
答案 0 :(得分:0)
模糊的问题得到了模糊的答案,但现在就去了。
我同意似乎所有FOR XML
连接可能都有所贡献(当然没有看到执行计划或完整的数据库架构,这几乎是我唯一要做的事情)。这里有很多未知因素可能会改变建议。如果您可以包含查询计划和IO统计信息,那将有所帮助。
我也没有声称具体知道为什么或者你是否需要在运行时使用视图或连接值,但这里有一些是探索性的问题:
dbo.Table3
中有多少行(与您连接值的基表?MyConcatenatedId
值中连接了多少行?dbo.another-tbl
似乎没有在提供的子查询中做任何事情(可能在真实版本中做了)。你需要吗?是否需要左连接?我最初的想法是,如果这需要高效而不是,请不要使用视图。如果你必须使用一个视图,可以使用像NOEXPAND这样的索引提示。你有什么选择?
不要序列化:我很难描绘需要在运行时序列化大量数据的场景。如果可能,返回数据集或在数据输入时序列化数据。
持久表/提前工作:可能也需要触发器,但是当底层数据发生更改时,将其写入持久表,并从中读取。或者将Change Data Capture之类的更改排队,然后异步处理这些更改
程序:除非您需要为每次调用都需要所有数据,否则请考虑制作一个可以参数化的过程,以便在需要时仅提取所需的内容。视图仅限于单个查询,并且有关该复杂性的查询的统计信息可能很快变为垃圾。程序可以单独分离语句并以较小的块分隔出来,这样您就可以更频繁地获得一致且更快的计划。