我在SQL Server 2012
上运行了以下(模糊处理的) SQL,需要显著提高其性能。它是有效的,但有时需要超过60秒才能恢复。
我想提取JOINS
,但this post似乎表明这是不可能的(因为MIN
和MAX
) -那么如何提高性能并简化/改进这些连接呢?
SELECT
wm.id, wm.uid, wm.em, wm.fn, wm.ln, c, y, RTRIM(LTRIM(yCode)) AS yCode, wm.d1, ISNULL(wm.ffn, wm.pp) as ffn, wm.ada,
case
when wm.mss & 2=2
then 'false'
else 'true'
end AS isa,
(
SELECT ', '+RTRIM(p1.cKey)
FROM profile p1
inner join loc stl on p1.cKey=stl.cKey
WHERE p1.id = wm.id and p1.s = 'A'
FOR XML PATH('')
) [lst],
lishc.[lstCount],
TotalCount = COUNT(*) OVER(),
la.lsa, wskp.cKey AS pid
FROM wmm wm
LEFT JOIN profile p1 ON wm.id = p1.id
LEFT JOIN (
SELECT UA.id, CONVERT(datetime, UA.ins, 1) As lsa
FROM actlog UA
INNER JOIN (
select id, max(ins) as laa
from actlog
group by id
) UAJ on UA.id=UAJ.id and UA.ins=UAJ.laa
) la on la.id=wm.id
LEFT JOIN (
SELECT id, cKey FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY id ORDER BY d1 desc) AS ROWNUM
FROM keypro where sc = 'SAP' AND cKeyDesc = 'SAP Agent ID'
) x WHERE ROWNUM = 1
) wskp ON wskp.id = wm.id
LEFT JOIN (
(SELECT p1.id ,COUNT(p1.cKey) AS [lstCount]
FROM profile p1
inner join loc stl on p1.cKey=stl.cKey
where p1.s = 'A'
GROUP BY p1.id)
) lishc ON lishc.id = wm.id
WHERE (@id = 0 OR wm.id = @id)
AND (@uid IS NULL OR wm.uid LIKE '%' + @uid + '%')
AND (@c IS NULL OR wm.c LIKE '%' + @c + '%')
AND (@fn IS NULL OR wm.fn LIKE '%' + @fn + '%')
AND (@ln IS NULL OR wm.ln LIKE '%' + @ln + '%')
AND (@em IS NULL OR wm.em LIKE '%' + @em + '%')
AND (@ffn IS NULL OR (wm.ffn LIKE '%' + @ffn + '%' OR wm.pp LIKE '%' + @ffn + '%'))
AND (@pid IS NULL OR wskp.cKey LIKE '%' + @pid + '%' )
AND (@Date1 IS NULL OR (CAST(wm.d1 AS DATE) BETWEEN CAST(@Date1 AS DATE) AND CAST(@Date2 AS DATE)))
AND (@lsa1 IS NULL OR (CAST(la.lsa AS DATE) BETWEEN CAST(@lsa1 AS DATE) AND CAST(@lsa2 AS DATE)))
AND (@Active IS NULL OR (wm.mss & 2 != 2))
AND (@Inactive IS NULL OR (wm.mss & 2 = 2))
AND (@External IS NULL OR (wm.ada = 'biz'))
AND (@Internal IS NULL OR (wm.ada <> 'biz'))
AND (@ApplyyFilter =0 OR (wm.yCode IN (SELECT @yCode WHERE 1 = 0)))
AND (@ApplylstFilter = 0 OR(p1.cKey IN (SELECT @ShipToList WHERE 1 = 0)))
AND (@ApplylstFilter = 0 OR(p1.s = 'A'))
AND (@ApplyNoFilter = 0 OR (lishc.[lstCount] is null))
AND (@lstCount = 0 OR lishc.[lstCount] = @lstCount)
AND (@ApplyLimitedFilter = 0 OR (wm.id IN (0)))
AND (@ApplyMoreFilter = 0 OR (wm.id IN (SELECT @idss WHERE 1 = 0)))
GROUP BY wm.id, wm.uid, wm.em, wm.fn, wm.ln, y, yCode,c,wm.d1,wm.ffn,wm.mss,wm.ada, la.lsa, wskp.cKey, lishc.[lstCount], wm.pp
ORDER BY lsa DESC
OFFSET @PageOffset ROWS FETCH NEXT @PageSize ROWS ONLY
发布于 2021-03-30 00:45:38
这里的捷径是添加OPTION (RECOMPILE)
,以便SQL Server可以消除与null参数相对应的谓词,并为每次搜索创建一个新计划。
你看,通常是Dynamic Search Conditions in T‑SQL
下一步要做的就是尽可能地去掉通配符搜索。
并改变这一点
(CAST(la.lsa AS DATE) BETWEEN CAST(@lsa1 AS DATE) AND CAST(@lsa2 AS DATE)))
转换成一个SARGable模式,比如
la.lsa >= @lsa1 and la.lsa < @lsa2
然后开始拆分这个查询,并为最常见或最关键的情况手写单独的查询。
https://stackoverflow.com/questions/66858124
复制相似问题