慢/重查询,可以提高效率吗?

时间:2014-03-03 22:16:53

标签: sql sql-server tsql

我有下面的查询 - 这有效,但在MSSMS中运行大约需要80秒。我想知道它是否可以提高效率吗?

下面将进行解释。

SELECT A.courseid, A.studentid, attendanceStatus, lessonDate,
 (SELECT top 1 SnoozeFrom FROM [tblConsecutiveSnooze] C 
     WHERE A.courseID = C.courseID AND A.StudentID = C.StudentID 
     ORDER BY SnoozeFrom DESC ) AS latestSnooze , 
 (SELECT top 1 SnoozeTimes FROM [tblConsecutiveSnooze] D 
     WHERE A.courseID = D.courseID AND A.StudentID = D.StudentID 
     ORDER BY SnoozeFrom DESC ) AS snoozeTimes  
FROM [tblStudentAttendance] A INNER JOIN tblcourses 
     ON A.courseID = tblcourses.courseID

WHERE [lessonDate] > getdate()-21 
AND EXISTS (SELECT * FROM tblstudentCourses B WHERE A.courseID = B.courseID 
   AND B.[DateLeft] IS NULL AND A.StudentID  = B.StudentID)  

ORDER BY courseid , studentID, [lessonDate]

所以我正在做的是尝试访问所有学生出勤记录(来自tblStudentAttendance),在过去的21天内,我已经确认(通过EXISTS)该学生确实仍然注册了该课程。

这两个子SELECT查询可以合并为一个,但这对查询的运行时间没有影响。

似乎对运行时间有很大影响的是EXISTS条件。所以任何建议都值得赞赏。

更新

Sql Plan: http://199.127.217.23/mm.sqlplan

索引:

  • tblStudentAttendance(id,PK)
  • tblCourses(courseID,PK)
  • tblConsecutiveSnooze(id,PK)
  • tblstudentCourses(id,PK)

3 个答案:

答案 0 :(得分:1)

如果查看发布的执行计划,您会发现添加缺失的索引可以将查询性能提高多达33%。您可以尝试将以下非聚集索引添加到tblStudentCourses表。您可以将索引名称更改为适合您的名称。

USE [hvps453_datab2]
GO
CREATE NONCLUSTERED INDEX [NC_tblStuddentCourses_DL_SI_CI]
ON [dbo].[tblStudentCourses] ([DateLeft])
INCLUDE ([studentID],[courseId])
GO

答案 1 :(得分:0)

带有行号的派生表如何找到最新的SnoozeFrom记录?或者,也可以使用CTE。

SELECT A.courseid
, A.studentid
, attendanceStatus
, lessonDate
, ConsecSnooze.SnoozeFrom AS latestSnooze
, ConsecSnooze.SnoozeTimes AS snoozeTimes
FROM [tblStudentAttendance] A
    INNER JOIN tblcourses
    ON A.courseID = tblcourses.courseID
    LEFT JOIN (
            SELECT SnoozeFrom
                                , SnoozeTimes
                                , C.courseID
                                , C.StudentID
                                , ROW_NUMBER() OVER (PARTITION BY C.CourseID, C.StudentID ORDER BY SnoozeFrom DESC) AS RowNum
            FROM [tblConsecutiveSnooze] C
    ) as ConsecSnooze ON ConsecSnooze.courseID = A.courseID
        AND ConsecSnooze.StudentID = A.studentID
            AND ConsecSnooze.RowNum = 1
WHERE [lessonDate] > getdate() - 21
AND EXISTS (
    SELECT *
    FROM tblstudentCourses B
    WHERE A.courseID = B.courseID
        AND B.[DateLeft] IS NULL
        AND A.StudentID = B.StudentID
    )
ORDER BY courseid
, studentID
, [lessonDate]

答案 2 :(得分:0)

如果您访问tblConsecutiveSnooze的主要方式是CourseIDStudentID,那么我高度建议您将PK更改为非群集并添加CourseID, StudentID上的聚集索引。这远远优于仅添加非聚簇索引并将聚簇PK保留在id上。此外,如果没有FK,那么您甚至可能不需要id列(切换到CourseID, StudentID没有意义)。虽然我是代理键的支持者,但不是每个表都需要它们!

我还建议您停止命名列id。列名在其中存在的每个表中应该相同,包括其基表。