当前,我正在使用以下代码来总结已审核的固定资产的报告。最初,这没问题,三年后,我注意到系统现在非常慢。我重新查看该代码,然后发现该代码为何系统运行缓慢。当我删除子字符串部分时,系统运行速度更快。这附近有工作吗?
SELECT
ENTITY
, [ASSET NUMBER]
, [YEAR AUDITED]
, SUM(COUNT) AS AUDITED
, SUBSTRING
(
(
SELECT
', ' + [SCANNED BY].USERNAME
FROM dbo.vwAUDITED as [SCANNED BY]
WHERE vwAUDITED.[ASSET NUMBER] = [SCANNED BY].[ASSET NUMBER]
AND vwAUDITED.ENTITY = [SCANNED BY].ENTITY
AND vwAUDITED.[YEAR AUDITED] = [SCANNED BY].[YEAR AUDITED]
ORDER BY [SCANNED BY].[ASSET NUMBER] FOR XML PATH('')
), 2, 1000
) AS [SCANNED BY]
, MAX(DATE) AS [COMPLETION DATE]
FROM dbo.vwAUDITED
GROUP BY ENTITY
, [ASSET NUMBER]
, [YEAR AUDITED]
答案 0 :(得分:1)
一种方法是添加一个user-defined aggregate function,以替代您的MS SQL Server版本中缺少的STRING_AGG函数。然后用该函数替换该子查询。
中找到不涉及数据库管理员的另一种方法是使用临时表,该临时表在用于通过FOR XML
联接子查询的字段上使用复合索引。
在 db <>小提琴here
上进行测试-- Just assuming the datatypes here, so change them to the correct types.
IF OBJECT_ID('tempdb..#tmpAUDITED') IS NOT NULL DROP TABLE #tmpAUDITED;
CREATE TABLE #tmpAUDITED
(
[ENTITY] INT NOT NULL,
[ASSET NUMBER] INT NOT NULL,
[YEAR AUDITED] INT NOT NULL,
[COUNT] INT,
[DATE] DATE,
[USERNAME] VARCHAR(100),
INDEX idx_1 NONCLUSTERED ([ENTITY], [ASSET NUMBER], [YEAR AUDITED])
);
INSERT INTO #tmpAUDITED (
[ENTITY], [ASSET NUMBER],[YEAR AUDITED], [COUNT], [DATE], [USERNAME]
)
SELECT
[ENTITY], [ASSET NUMBER],[YEAR AUDITED], [COUNT], [DATE], [USERNAME]
FROM dbo.vwAUDITED;
-- Now using the temp table instead of the view.
SELECT
[ENTITY],
[ASSET NUMBER],
[YEAR AUDITED],
SUM([COUNT]) AS AUDITED,
SUBSTRING
((
SELECT ', ' + s.[USERNAME]
FROM #tmpAUDITED AS s
WHERE s.[ENTITY] = [AUDITED].[ENTITY]
AND s.[ASSET NUMBER] = [AUDITED].[ASSET NUMBER]
AND s.[YEAR AUDITED] = [AUDITED].[YEAR AUDITED]
-- ORDER BY s.[ENTITY], s.[ASSET NUMBER], s.[YEAR AUDITED], s.[USERNAME]
FOR XML PATH('')
), 2, 1000) AS [SCANNED BY],
MAX([DATE]) AS [COMPLETION DATE]
FROM #tmpAUDITED AS [AUDITED]
GROUP BY [ENTITY], [ASSET NUMBER], [YEAR AUDITED];
另外,值得检查一下视图中的查询是否可以优化。或者在表上添加某些索引(用于视图中)可以提高视图本身的性能。
答案 1 :(得分:1)
最好的连接方式是:
declare @str nvarchar(max) = space(0);
select @str += [column] from [yourTable];
select @str;
但是,您的情况有所不同。 根据您的情况,串联效果很好,并且由于视图结构可能会导致性能下降。如果您看不到视图结构, 您可以通过使用主视图记录集作为CTE来最大程度地降低性能问题,然后在CTE而不是视图上执行成本高昂的资源交换操作:
;with [data] as (
select [entity], [asset number], [year audited], [username], [date], [count] from [dbo].[vwAUDITED]
)
select
[entity] = [d].[entity]
,[asset number] = [d].[asset number]
,[year audited] = [d].[year audited]
,[audited] = sum([d].[count])
,[scanned by] = substring((
select
', ' + [username]
from
[dbo].[vwAUDITED]
where
[asset number] = [d].[asset number]
and [entity] = [d].[entity]
and [year audited] = [d].[year audited]
order by
[asset number]
for xml path('')
), 2, 1000)
,[completion date] = max([d].[date])
from
[data] as [d]
group by
[d].[entity]
,[d].[asset number]
,[d].[year audited];