1

我有一个存储过程,它在一个WHILE循环中运行几个查询,特别是这些查询比 SP 的其余部分花费的时间呈指数增长,大大降低了我的性能。

我在一些地方读到,如果您只从第一个表中提取列,则使用 an INvs. anINNER JOIN可以提高性能,这正是我正在做的。

然而,问题是我对如何INNER JOININ子句替换 my 没有第一个线索。我认为 an 的语法与 anIN非常不同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 
4

4 回答 4

2

是的,格式非常不同,它们在技术上做了不同的事情:这就是连接的完成方式:

SELECT * FROM TABLEA a JOIN TABLEB on a.commonfield = b.commonfield

这就是您使用 IN 语句的方式

SELECT * FROM TABLEA WHERE commonfield in (SELECT commonfield from tableb)
于 2013-10-04T18:32:04.130 回答
2

一种选择是创建一个表变量来存储您的中间结果。

首先将@UserGroupKeys插入while循环中。update ... select然后对你的真实数据表运行一个。这将是手术中最昂贵的部分。

table 变量现在将查找UserGroupKeytoKey并且应该比搜索原始表快得多。

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
于 2013-10-04T18:34:20.547 回答
2

嗯,我注意到的第一件事是有一个“相关子查询”,这实际上不是必需的。您已选择变量,这意味着即使存在多个 KEY,最后也只会选择一个值。在这种情况下,将在变量中选择什么键取决于 SQL Server,因为没有 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

只是为了说明,如果您尝试了解为什么以当前方式编写此查询的逻辑,那么只有您可以进入下一步,在您的情况下,使用不同的运算符重写查询。

于 2013-10-04T19:07:15.860 回答
0

花了点心思,但我通过INNER JOIN从相关语句中删除所有 s 极大地优化了这个性能。

相对于运行所需的时间,此查询会根据正在处理的记录数变得越来越快。

这就是我最终的结果。您会注意到一些额外的变量。这些是在每次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)
于 2013-10-04T21:41:28.520 回答