优化我的存储过程 - 这是正确的方法吗?

时间:2016-06-15 08:29:25

标签: sql sql-server-2008 database-performance sqlperformance

SELECT  TOP 1 @CurrentStudentID = StudentID
FROM    Courses WITH (NOLOCK)
WHERE   Courses.CourseID = @CourseID 
ORDER BY StudentID

-- Loop through all the students and find if he/she is registered for more than one course.
WHILE (@@ROWCOUNT > 0 AND @CurrentStudentID IS NOT NULL)
BEGIN

    -- Select all other courses student is currently registered in.

    IF @@ROWCOUNT > 0
    BEGIN
        -- return required information
    END
    ELSE
    BEGIN
        -- Perform some operations
    END

    -- Select the next registered student
    SELECT  TOP 1 @CurrentStudentID = StudentID
    FROM    Courses WITH (NOLOCK)
    WHERE   Courses.CourseID = @CourseID AND
            Courses.StudentID > @CurrentStudentID 
    ORDER BY StudentID
END

有人可以在这里帮助我的逻辑吗?我写了一个存储过程,以确定一门课程的学生目前是否正在从同一所学校学习其他课程。

如果学生人数众多,我特别担心两个SELECT查询和while循环的表现。我觉得我这样做的感觉非常人为。我确信有更好的方法可以做到这一点。

我已对此存储过程进行了SQL分析,对于单个调用,其持续时间范围为0 - 60 ms。我不明白为什么相同的存储过程的执行时间是如此随机和不一致。

感谢任何帮助。我只有1年以上的SQL Server 2008经验。

提前致谢。

1 个答案:

答案 0 :(得分:1)

正如我所提到的,SQL是一种基于集合的理论语言。换句话说,它与数据集是半关系的,允许在数据组之间进行有效的比较。诸如C ++或Java之类的“较低”语言不能维护如此大的数据集,因为它们是基于光标(逐行)的语言。

此定义的高级别,重点是将您的数据视为EXCEL张。您有预定义的列,例如CourseIDStudentID,其他列中的信息依赖于这些值(CourseID 1:1 Course_Name)和一些重复的信息(CourseID)可以有多个学生)。

真正的规范化包括删除相互依赖的列,但现在不用担心。主要关注的是对业务有意义的事情。您的表格已为其课程和学生识别列。因此,如果这些值没有冲突的相互依赖的值,则不需要使用游标。

SELECT StudentID, COUNT(COURSEID) AS CLASS_NUM
FROM   COURSES
GROUP BY StudentID
HAVING COUNT(COURSEID) > 1

GROUP BY从列出的列中返回不同的值集,展平其他行并允许聚合函数,如COUNT()。 (注意:NULLS不计入COUNT()。使用ISNULL功能) 您还没有限制列表,但是您获得了相同的结果。在SQL展平行之后,如果需要,可以使用HAVING子句进一步限制GROUP BY的结果集。

绝对比光标快。 :)

现在,如果您的表格包含不同学期和年份的学生,您可以考虑将其添加到GROUP BY,以便在GROUP BYStudentID和{{ 1}})

另外,请回想一下Year语句在SELECTGROUP BY子句之后进行LOGICALLY读取,因此HAVING语句中列出的任何列都必须出现在{{1}中或者具有聚合函数。