我有一个存储过程在WHILE
循环中运行几个查询,特别是这些查询比SP的其余部分指数长得多,这大大降低了我的性能。
我已经在一些地方读过,如果您只是从第一个表中提取列,那么使用IN
与INNER JOIN
可以提高性能,这正是我正在做的事情
然而,问题是我没有第一个线索可以用INNER JOIN
子句替换IN
。我认为IN
的语法与INNER JOIN
非常不同,但我不知道从哪里开始。
作为一个脚注,SQL不是我的强项。非常感谢所有建议。
这是其中一个查询。它们在逻辑上几乎完全相同。
SELECT @CurrentKey = riv.Key
FROM ResourceInfo_VW riv
INNER JOIN (SELECT Track,
Code,
[Language]
FROM ResourceInfo_VW
WHERE Key = @CurrentKey) AS riv2
ON riv.Track = riv2.Track
AND riv.Code = riv2.Code
AND riv.[Language] = riv2.[Language]
INNER JOIN UserGroupCourseCatalog_VW ugcc
ON riv.Key = ugcc.Key
WHERE riv.[Type] = 'a'
AND ugcc.UserGroupKey = @UserGroupKey
答案 0 :(得分:2)
一个选项是创建一个表变量来存储中间结果。
首先在@UserGroupKey
循环中插入while
s。然后针对您的真实数据表运行单个update ... select
。这将是该行动中最昂贵的部分。
表变量现在可以查找UserGroupKey
到Key
,并且执行速度比搜索原始表要快得多。
declare @t table (UserGroupKey nvarchar(255), Key nvarchar(255))
while (...)
begin
insert into @t(UserGroupKey) values (@UserGroupKey)
end
-- this is the expensive part, but it only happens once
update @t
set Key = riv.KEY
FROM ResourceInfo_VW riv
INNER JOIN (SELECT Track,
Code,
[Language]
FROM ResourceInfo_VW
WHERE KEY = @Key) AS riv2
ON riv.Track = riv2.Track
AND riv.Code = riv2.Code
AND riv.[Language] = riv2.[Language]
INNER JOIN UserGroupCourseCatalog_VW ugcc
ON riv.KEY = ugcc.KEY
WHERE riv.[Type] = 'a'
AND ugcc.UserGroupKey = @t.UserGroupKey
while (...)
begin
select @Key = Key
from @t
where @t.UserGroupKey = @UserGroupKey
end
答案 1 :(得分:2)
我注意到的第一件事是存在“相关子查询”,这实际上并不是必需的。 您已选择输入变量,这意味着即使存在多个KEY,也只会在最后选择一个值。 在这种情况下,在变量中选择哪个键取决于SQL服务器,因为没有order by子句。
考虑添加Top和order by,以便您知道在多行满足WHERE条件的情况下,将获得什么结果。 每次运行相同的查询时,结果应至少保持一致。
我会在下面重写查询。如果表上有适当的索引,性能应该不错。
请注意,添加了TOP 1,因为在变量中无论如何都无法存储多个值。因此,找出您要存储的ONE值。 MIN,MAX,TOP1等......
此外,我认为不需要对表“ResourceInfo_VW”进行SELF JOIN。如果我在这里错了,你可以纠正我。
SELECT
TOP 1
@Key= riv.KEY
FROM ResourceInfo_VW riv
INNER JOIN UserGroupCourseCatalog_VW ugcc
ON riv.KEY = ugcc.KEY AND riv.[Type] = 'a'
WHERE ugcc.UserGroupKey = @UserGroupKey
只是为了说明,如果你试图理解为什么这个查询以当前的方式编写的逻辑,那么只有你可以进入下一步,在你的情况下,使用不同的运算符重写查询。
答案 2 :(得分:1)
是的格式非常不同,它们在技术上做了不同的事情: 这就是联接的完成方式:
SELECT * FROM TABLEA a JOIN TABLEB on a.commonfield = b.commonfield
这是你使用IN语句的方式
SELECT * FROM TABLEA WHERE commonfield in (SELECT commonfield from tableb)
答案 3 :(得分:0)
需要一些思考,但我通过从相关语句中删除所有INNER JOIN
来大大优化了这种性能。
相对于运行所花费的时间,此查询会根据正在处理的记录数量而变得越来越快。
这是我最终的结果。你会注意到一些额外的变量。这些是在每次WHILE
次迭代开始时设置的。
SELECT @CurrentTrack = Track,
@CurrentCode = Code,
@CurrentLanguage = [Language]
FROM ResourceInfo_VW riv
WHERE riv.Key = @CurrentKey
SELECT riv.Key
FROM ResourceInfo_VW riv
WHERE riv.[Type] = 'a'
AND riv.Track = @CurrentTrack
AND riv.Code = @CurrentCode
AND riv.[Language] = @CurrentLanguage
AND riv.CourseKey IN (SELECT CourseKey
FROM UserGroupCourseCatalog_VW
WHERE UserGroupKey = @UserGroupKey)