我想知道如何提高SQL语句的性能和效率。 有没有人有一些想法或建议?
DECLARE @RoleName NVARCHAR(MAX)
DECLARE @result INT
SELECT @result = COUNT(DurchlaufVorgang.Durchlaufname)
FROM DurchlaufVorgang
INNER JOIN RoleDepartment
ON DurchlaufVorgang.AbteilungID = RoleDepartment.ID
WHERE DurchlaufVorgang.Depricated = 'FALSE'
AND RoleDepartment.RoleName = @RoleName
AND RoleDepartment.Depricated = 'FALSE'
SELECT Antraege.AntragID
FROM ArtikelMitteilung,
Antraege
WHERE ArtikelMitteilung.Status = 'Opened'
AND Antraege.AntragID NOT IN
(SELECT Antraege.AntragID
FROM Vorgang,
Antraege
WHERE Vorgang.StepID IN
(SELECT DurchlaufVorgang.ID
FROM DurchlaufVorgang
INNER JOIN RoleDepartment
ON DurchlaufVorgang.AbteilungID = RoleDepartment.ID
WHERE DurchlaufVorgang.Depricated = 'FALSE'
AND RoleDepartment.RoleName = @RoleName
AND RoleDepartment.Depricated = 'FALSE')
AND Vorgang.AntragsID = Antraege.ID
GROUP BY Antraege.AntragID
HAVING COUNT(Antraege.AntragID) >= @result)
AND ArtikelMitteilung.AntragsID = Antraege.ID
GROUP BY Antraege.AntragID
我很感谢你的帮助。
答案 0 :(得分:1)
查看实际的查询计划,并查看索引扫描和表扫描的位置。找到使用索引寻求消除这些瓶颈的方法。
我可能会猜测你所拥有的所有谓词都没有编入索引,也许最有选择性的谓词可能被编入索引,这将极大地帮助查询计划程序选择索引寻求识别要返回的行。
您还可以尝试在WHERE子句中使用NOT EXISTS
表单而不是NOT IN
表单。有时这可能有所帮助,您应该运行检查每个查询执行计划。
编辑:
同时删除冗余代码。例如,
(SELECT Antraege.AntragID
FROM Vorgang,
Antraege
WHERE Vorgang.StepID IN
(/* your subquery */)
AND Vorgang.AntragsID = Antraege.ID
GROUP BY Antraege.AntragID
HAVING COUNT(Antraege.AntragID) >= @result)
可以简化:
(SELECT Vorgang.AntragsID
FROM Vorgang
WHERE Vorgang.StepID IN
(/* your subquery */)
GROUP BY Vorgang.AntragsID
HAVING COUNT(Vorgang.AntragsID) >= @result)
答案 1 :(得分:1)
你的查询中没有做任何明显错误的事情。 SQL优化器将采用类似的大型语句,并找出执行它的最佳方法。如果你的指数碎片化或不存在,你可能遇到问题的地方。
从SQL Server Management Studio中,单击“显示执行计划”,然后查看是否建议任何其他索引。对索引进行解组(如果您处于测试环境中,则可以删除并重新添加它们)。
如果你的直觉是一个大的声明对性能不利,那么这不应该是这种情况。事实上,它应该有助于优化器,因为它为如何执行它提供了更多选择。
答案 2 :(得分:1)
取决于表的大小,将列表放入索引列可能会有很大帮助。
declare @tab (AntragID int primary key clustered)
insert @tab
(AntragID)
SELECT Antraege.AntragID
FROM Vorgang,
Antraege
WHERE Vorgang.StepID IN
(SELECT DurchlaufVorgang.ID
FROM DurchlaufVorgang
INNER JOIN RoleDepartment
ON DurchlaufVorgang.AbteilungID = RoleDepartment.ID
WHERE DurchlaufVorgang.Depricated = 'FALSE'
AND RoleDepartment.RoleName = @RoleName
AND RoleDepartment.Depricated = 'FALSE')
AND Vorgang.AntragsID = Antraege.ID
GROUP BY Antraege.AntragID
HAVING COUNT(Antraege.AntragID) >= @result
SELECT Antraege.AntragID
FROM
Antraege
INNER JOIN ArtikelMitteilung
ON Antraege.ID = ArtikelMitteilung.AntragsID
LEFT JOIN @tab x
ON Antraege.AntragID = X.AntragID
WHERE
ArtikelMitteilung.Status = 'Opened' AND
X.AntragID IS NULL
GROUP BY
如果未从子查询返回唯一的AntragID,则使用临时表而不是表变量,并在AntragID上创建索引。
create table #tab (AntragID int)
create clustered index cix_antragid_tab on #tab(AntragID)
insert #tab
(AntragID)
SELECT Antraege.AntragID
FROM Vorgang,
Antraege
WHERE Vorgang.StepID IN
(SELECT DurchlaufVorgang.ID
FROM DurchlaufVorgang
INNER JOIN RoleDepartment
ON DurchlaufVorgang.AbteilungID = RoleDepartment.ID
WHERE DurchlaufVorgang.Depricated = 'FALSE'
AND RoleDepartment.RoleName = @RoleName
AND RoleDepartment.Depricated = 'FALSE')
AND Vorgang.AntragsID = Antraege.ID
GROUP BY Antraege.AntragID
HAVING COUNT(Antraege.AntragID) >= @result
SELECT Antraege.AntragID
FROM
Antraege
INNER JOIN ArtikelMitteilung
ON Antraege.ID = ArtikelMitteilung.AntragsID
LEFT JOIN #tab x
ON Antraege.AntragID = X.AntragID
WHERE
ArtikelMitteilung.Status = 'Opened' AND
X.AntragID IS NULL
GROUP BY
如果你发布了exec计划,那么可以优化查询的逻辑。
答案 3 :(得分:-1)
NOT IN条款往往效率不高。尝试使用LEFT JOIN代替。然后测试连接表(右侧)中的AntragID是否为空。
SELECT *
FROM
Antrage A
LEFT JOIN Antrage B
ON A.AntragID = B.AntragID
WHERE
B.AntragID IS NULL AND
...
SELECT Antraege.AntragID
FROM
Antraege
INNER JOIN ArtikelMitteilung
ON Antraege.ID = ArtikelMitteilung.AntragsID
LEFT JOIN
(SELECT Antraege.AntragID
FROM Vorgang,
Antraege
WHERE Vorgang.StepID IN
(SELECT DurchlaufVorgang.ID
FROM DurchlaufVorgang
INNER JOIN RoleDepartment
ON DurchlaufVorgang.AbteilungID = RoleDepartment.ID
WHERE DurchlaufVorgang.Depricated = 'FALSE'
AND RoleDepartment.RoleName = @RoleName
AND RoleDepartment.Depricated = 'FALSE')
AND Vorgang.AntragsID = Antraege.ID
GROUP BY Antraege.AntragID
HAVING COUNT(Antraege.AntragID) >= @result) X
ON Antraege.AntragID = X.AntragID
WHERE
ArtikelMitteilung.Status = 'Opened' AND
X.AntragID IS NULL
GROUP BY
Antraege.AntragID