1000年前に作成された古いレポートクエリのパフォーマンスを向上させるために、いくつかの変更を加えています。UNION ALLを実行するように変更する過程で、列選択値の1つをNULLに置き換えました。これを行うとすぐに、クエリは実行に1〜2秒かかるものから実行するのに30秒かかるものに変わります。2つのバージョンの実際の実行プランを確認しましたが、同じように見えます。リテラルNULLを選択すると、行の値を読み取るよりも遅くなる可能性があることは私には意味がありません。また、以前のタイプ(nvarchar)に明示的にNULLをキャストし、NULLの代わりに''を選択して違いはありませんでした。
クエリとスキーマは非常に複雑であるため、Q&Aのトラブルシューティングが必要になる可能性があります。NULLを選択したときに速度が低下する列は、下部にある「OtherComments」です。その上にコメントされた、高速で実行される元のバージョンを見ることができます。私たちを軌道に乗せるために、私はその列を変更すると実行が遅くなる理由を理解することだけを目的としており、クエリを改善する他の方法は理解していません(たくさんあることを知っています)。省略形は次のとおりです。
SELECT @Date Parameter,
fml.FirstName + ' ' + fml.LastName ParentName,
(
SELECT TOP 1 p.PhoneNum
FROM tbl_Phone p, tbl_PhoneTypes pt, tbl_FamilyPhone fp
WHERE p.fk_PhoneTypeID = pt.pk_PhoneTypeID
AND p.pk_PhoneID = fp.fk_PhoneID
AND fp.fk_FamilyID = fml.pk_familyID
AND pt.Type = 'home'
AND fp.IsDeleted = 0
ORDER BY fp.CreatedDate DESC
) PhoneNo,
fml.Comments FamilyComments,
std.FirstName + ' ' + std.LastName StudentName,
(
SELECT
...
) ClassDescription,
(
SELECT
...
) TestClassDescription,
CASE
WHEN (sce.pk_StudentEnrollmentID IS NOT NULL) THEN
(
SELECT emp.FirstName + ' ' + emp.LastName
...
)
WHEN (st.pk_StudentTestID IS NOT NULL) THEN
(
SELECT emp.FirstName + ' ' + emp.LastName
...
)
ELSE
NULL
END InstructorName,
CASE
WHEN (st.pk_StudentTestID IS NOT NULL) THEN
(
SELECT emp.FirstName + ' ' + emp.LastName
...
)
ELSE
NULL
END TestInstructorName,
st.TestDate TestDate,
tr.Description TestResult,
CASE
WHEN (
SELECT COUNT(ClassDate) --Select absent attendances from yesterday
...
) >= 1
THEN
CAST(1 AS BIT)
ELSE
CAST(0 AS BIT)
END
MissedYesterdaysClass,
CASE
WHEN (datediff(day, CONVERT(varchar(11),fml.InquiryDate,102), @Date) =3 and
(fml.CurrentMembershipDate IS NULL) AND ((fml.WebCreated = 0) OR (fml.WebCreated = NULL)) AND
((
SELECT count(*)
...
) <= 0) AND
((
SELECT count(*)
...
) <= 0) AND
((
SELECT count(*)
...
) <= 0) AND
((
SELECT count(*)
...
) <= 0) AND
((
SELECT count(*)
...
) <= 0)) THEN
CAST(1 AS BIT)
WHEN (((fml.InquiryDate + 3) = @Date) AND (std.pk_StudentID IS NULL)) THEN
CAST(1 AS BIT)
ELSE
CAST(0 AS BIT)
END InquiredButDidnotSchedule,
CASE
WHEN --(((st.TestDate + 2) = @Date) AND
(datediff(day, CONVERT(varchar(11),st.testdate,102), @Date) =2 and
(tr.Description = 'Not Enrolled') AND
(st.IsDeleted = 0) AND
(st.IsCancelled = 0)) THEN
CAST(1 AS BIT)
ELSE
CAST(0 AS BIT)
END AttendedButHavenotEnrolled,
CASE
WHEN --(((st.TestDate + 1) = @Date) AND
(datediff(day, CONVERT(varchar(11),st.testdate,102), @Date) =1 and
(tr.Description = 'No Show') AND
(st.IsDeleted = 0) AND
(st.IsCancelled = 0)) THEN
CAST(1 AS BIT)
ELSE
CAST(0 AS BIT)
END PeopleNoShowed,
CASE
WHEN ---(((st.TestDate - 1) = @Date) AND
(datediff(day, CONVERT(varchar(11),st.testdate,102), @Date) =-1 and
(tr.Description = 'Scheduled') AND
(st.IsDeleted = 0) AND
(st.IsCancelled = 0)) THEN
CAST(1 AS BIT)
ELSE
CAST(0 AS BIT)
END PeopleHaveTest,
CAST(0 AS BIT) ShowOtherComments,
CASE
WHEN
((
SELECT count(*)
...
) > 0) AND
((
SELECT EventDate
...
)
BETWEEN
(
DateAdd(day, DateDiff(day, 0, @Date), 0)
)
AND
(
(DateAdd(day, DateDiff(day, 0, @Date), 0) + 6)
)
)
AND
datename(weekday, @Date) = 'Wednesday'
AND
bb.IsDeleted = 0
AND
bb.IsCancelled = 0 THEN
CAST(1 AS BIT)
ELSE
CAST(0 AS BIT)
END ShowUpcomingBookingss,
(
SELECT EventDate
...
) BookingDate,
bb.ChildTurningAge Age,
std.pk_StudentID StudentID,
fml.pk_familyID FamilyID,
CASE
WHEN (datediff(day, CONVERT(varchar(11),fml.InquiryDate,102), @Date) =1 and
(fml.MembershipDate IS NULL) AND (fml.WebCreated = 1) AND
((
SELECT count(*)
...
) <= 0) AND
((
SELECT count(*)
...
) <= 0) AND
((
SELECT count(*)
...
) <= 0) AND
((
SELECT count(*)
...
) <= 0) AND
((
SELECT count(*)
...
) <= 0)) THEN
CAST(1 AS BIT)
WHEN (((fml.InquiryDate + 1) = @Date) AND (std.pk_StudentID IS NULL)) THEN
CAST(1 AS BIT)
ELSE
CAST(0 AS BIT)
END InquiredButDidnotScheduleOnline,
-- Commenting this out and replacing with NULL slows it down from 2 sec to 30 sec
-- fml.OtherComment OtherComments,
NULL OtherComments,
FROM tbl_Family fml
LEFT OUTER JOIN tbl_Student std on fml.pk_FamilyID = std.fk_FamilyID
LEFT OUTER JOIN tbl_StudentEnrollment sce on std.pk_StudentID = sce.fk_StudentID
LEFT OUTER JOIN tbl_StudentTest st on std.pk_StudentID = st.fk_StudentID
LEFT OUTER JOIN tbl_Booking bb on std.pk_StudentID = bb.fk_StudentID
LEFT JOIN tbl_TestResult tr on st.fk_TestResultID = tr.pk_TestResultID
WHERE fml.fk_FacilityID = @FacilityID
AND (fml.IsDeleted = 0 OR fml.IsDeleted IS NULL)
AND (std.IsDeleted = 0 OR std.IsDeleted IS NULL)