У меня есть SQL код, который выполняется на SQL Server 2017 менее чем за 200 мс, но тот же код на SQL Server 2012 занимает более 3 секунд - может кто-нибудь сказать мне:
- почему это происходит
- как мне это решить
select count(*) from dbo.mConsultationQuestionsReplies = 1,300,000
Это мой код:
DECLARE @maxCount int;
DECLARE @ddlIds nvarchar(max);
SET @maxCount = 6;
SET @ddlIds = '4,8,840,779,10,813,3,18,7,918';
IF OBJECT_ID('tempdb..#rList') IS NOT NULL
DROP TABLE #rList
IF OBJECT_ID('tempdb..#docList') IS NOT NULL
DROP TABLE #docList
SELECT
rd.UserID,
(CASE
WHEN ids1.value IS NULL
THEN CAST(ids2.value AS int)
ELSE CAST(ids1.value AS int)
END) [cid]
INTO
#docList
FROM
mDJDoctors [rd]
LEFT JOIN
dbo.[mDJDoctorsSpeciality] [rs] ON rd.DoctorID = rs.doctorId
LEFT JOIN
dbo.mDJSpecialtyCategory [rca] ON rca.SpecialtyId = rs.specialId
LEFT JOIN
STRING_SPLIT(@ddlIds, ',') [ids1] ON rca.CategoryId = ids1.value
LEFT JOIN
dbo.mDJDoctorsSpecialtyAbove [ars] ON ars.doctorId = rd.DoctorID
LEFT JOIN
dbo.mDJSpecialtyAboveCategory [arca] ON arca.AboveSpecialtyId = ars.SpecialtyAboveId
LEFT JOIN
STRING_SPLIT(@ddlIds, ',') [ids2] ON [arca].CategoryId = ids2.value
WHERE
[ids1].value IS NOT NULL
OR [ids2].value IS NOT NULL
SELECT *
INTO #rList
FROM
(SELECT
*,
ROW_NUMBER() OVER (PARTITION BY t.cid ORDER BY t.ReplyDateInsert DESC) AS rowNumber
FROM
(SELECT DISTINCT r.ReplyUserID, r.ReplyDateInsert, d.cid
FROM dbo.mConsultationQuestionsReplies[r]
JOIN #docList [d] ON r.ReplyUserID = d.UserID
WHERE r.ReplyId IN (SELECT MAX(r.ReplyId)[id]
FROM dbo.mConsultationQuestionsReplies[r]
JOIN #docList [d] on r.ReplyUserID = d.UserID
GROUP BY d.cid, d.UserID)) [t]) [t]
WHERE
t.rowNumber <= @maxCount
SELECT
u.FirstName AS DoctorName,
u.UserID AS DoctorUserId,
sp.specialFaName AS DoctorSpecialty,
ab.SpecialtyAboveFaName AS DoctorAboveSpecialty,
md.DoctorGUID,
md.DoctorID,
cp.ProfileISOnline,
p.ProfilePicture AS DoctorProfilePicture,
p.ProfileDateInserted,
r.ReplyDateInsert AS LastReplyDateInsert,
r.cid
FROM
dbo.mDJDoctors AS md
INNER JOIN
dbo.Core_Users AS u ON md.UserID = u.UserID
INNER JOIN
dbo.Core_Profiles AS p ON u.UserID = p.UserID
INNER JOIN
(SELECT * FROM #rList) [r] ON r.ReplyUserID = u.UserID
INNER JOIN
dbo.mConsultationDocterProfile AS cp ON cp.UserID = u.UserID
LEFT OUTER JOIN
dbo.mDJDoctorsSpeciality AS mdad ON md.DoctorID = mdad.doctorId
LEFT OUTER JOIN
dbo.mDJSpecialty AS sp ON mdad.specialId = sp.specialId
LEFT OUTER JOIN
dbo.mDJDoctorsSpecialtyAbove AS mdad2 ON md.DoctorID = mdad2.doctorId
LEFT OUTER JOIN
dbo.mDJSpecialtyAbove AS ab ON mdad2.SpecialtyAboveId = ab.SpecialtyAboveId
WHERE
cp.ProfileISOnline = 1
обновление: основано на guid с марта c -s я удалил STRING_SPLIT, и новый результат
declare @maxCount int;
set @maxCount = 6;
IF OBJECT_ID('tempdb..#rList') IS NOT NULL DROP TABLE #rList
IF OBJECT_ID('tempdb..#docList') IS NOT NULL DROP TABLE #docList
select rd.UserID, (case when arca.CategoryId is null then cast(rca.CategoryId as int) else cast(arca.CategoryId as int) end)[cid] into #docList
from mDJDoctors [rd] WITH (NOLOCK)
left join dbo.[mDJDoctorsSpeciality] [rs] WITH (NOLOCK) on rd.DoctorID = rs.doctorId
left join dbo.mDJSpecialtyCategory [rca] WITH (NOLOCK) on rca.SpecialtyId = rs.specialId
left join dbo.mDJDoctorsSpecialtyAbove [ars] WITH (NOLOCK) on ars.doctorId = rd.DoctorID
left join dbo.mDJSpecialtyAboveCategory [arca] WITH (NOLOCK) on arca.AboveSpecialtyId = ars.SpecialtyAboveId
where arca.CategoryId in (4,8,840,779,10,813,3,18,7,918) or rca.CategoryId in (4,8,840,779,10,813,3,18,7,918)
select * into #rList from (
select * , ROW_NUMBER() OVER (PARTITION BY t.cid ORDER BY t.ReplyDateInsert DESC) AS rowNumber from (
select distinct r.ReplyUserID, r.ReplyDateInsert, d.cid
from dbo.mConsultationQuestionsReplies[r] WITH (NOLOCK)
join #docList [d] on r.ReplyUserID = d.UserID
where r.ReplyId in(
select max(r.ReplyId)[id]
from dbo.mConsultationQuestionsReplies[r] WITH (NOLOCK)
join #docList [d] on r.ReplyUserID = d.UserID
group by d.cid,d.UserID
))[t])[t] where t.rowNumber <= @maxCount
SELECT distinct
u.FirstName AS DoctorName,
u.UserID AS DoctorUserId,
sp.specialFaName AS DoctorSpecialty,
ab.SpecialtyAboveFaName AS DoctorAboveSpecialty,
md.DoctorGUID,
md.DoctorID,
cp.ProfileISOnline,
p.ProfilePicture AS DoctorProfilePicture,
p.ProfileDateInserted,
r.ReplyDateInsert AS LastReplyDateInsert,
r.cid
FROM dbo.mDJDoctors AS md WITH (NOLOCK)
INNER JOIN dbo.Core_Users AS u WITH (NOLOCK)
ON md.UserID = u.UserID
INNER JOIN dbo.Core_Profiles AS p WITH (NOLOCK)
ON u.UserID = p.UserID
INNER JOIN
(
select * from #rList
) [r]
ON r.ReplyUserID = u.UserID
INNER JOIN dbo.mConsultationDocterProfile AS cp WITH (NOLOCK)
ON cp.UserID = u.UserID
LEFT OUTER JOIN dbo.mDJDoctorsSpeciality AS mdad WITH (NOLOCK)
ON md.DoctorID = mdad.doctorId
LEFT OUTER JOIN dbo.mDJSpecialty AS sp WITH (NOLOCK)
ON mdad.specialId = sp.specialId
LEFT OUTER JOIN dbo.mDJDoctorsSpecialtyAbove AS mdad2 WITH (NOLOCK)
ON md.DoctorID = mdad2.doctorId
LEFT OUTER JOIN dbo.mDJSpecialtyAbove AS ab WITH (NOLOCK)
ON mdad2.SpecialtyAboveId = ab.SpecialtyAboveId
WHERE cp.ProfileISOnline = 1
order by cid, LastReplyDateInsert
занимает 200 мс в sql 2017 и 1038 мс в sql 2012
обновление 3: это мои планы выполнения xml на 2012 и 2017 годы
планы выполнения на 2012 и 2017 годы
обновление 4: конфигурация сервера