【发布时间】:2009-03-07 05:04:53
【问题描述】:
我有一个很长的查询,但是向它添加一个 where 子句,或者加入一个字符串会导致它需要额外的 2 秒才能运行。我不知道为什么。
这是完整的查询:
ALTER PROCEDURE [dbo].[RespondersByPracticeID]
@practiceID int = null,
@activeOnly bit = 1
AS
BEGIN
SET NOCOUNT ON;
select
isnull(sum(isResponder),0) as [Responders]
,isnull(count(*) - sum(isResponder),0) as [NonResponders]
,isnull((select
count(p.patientID)
from patient p
inner join practice on practice.practiceid = p.practiceid
inner join [lookup] l on p.dosing = l.lookupid and l.lookupid = 'da_ncd'
where
p.practiceID = isnull(@practiceID, p.practiceID)
and p.active = case @activeOnly when 1 then 1 else p.active end
) - (isnull(sum(isResponder),0) + isnull(count(*) - sum(isResponder),0)),0)
as [Undetermined]
from (
select
v.patientID
,firstVisit.hbLevel as startHb
,maxHbVisit.hblevel as maxHb
, case when (maxHbVisit.hblevel - firstVisit.hbLevel >= 1) then 1 else 0 end as isResponder
,count(v.patientID) as patientCount
from patient p
inner join visit v on v.patientid = v.patientid
inner join practice on practice.practiceid = p.practiceid
inner join [lookup] l on p.dosing = l.lookupid and l.lookupid = 'da_ncd'
inner join (
SELECT
p.PatientID
,v.VisitID
,v.hblevel
,v.VisitDate
FROM Patient p
INNER JOIN Visit v ON p.PatientID = v.PatientID
WHERE
v.VisitDate = (
SELECT MIN(VisitDate)
FROM Visit
WHERE PatientId = p.PatientId
)
) firstVisit on firstVisit.patientID = v.patientID
inner join (
select
p.patientID
,max(v.hbLevel) as hblevel
from Patient p
INNER JOIN Visit v ON p.PatientID = v.PatientID
group by
p.patientID
) MaxHbVisit on maxHbVisit.patientid = v.patientId
where
p.practiceID = isnull(@practiceID, p.practiceID)
and p.active = case @activeOnly when 1 then 1 else p.active end
group by
v.patientID
,firstVisit.hbLevel
,maxHbVisit.hblevel
having
datediff(
d,
dateadd(
day
,-DatePart(
dw
,min(v.visitDate)
) + 1
,min(v.visitDate)
)
, max(v.visitDate)
) >= (7 * 8) -- Eight weeks.
) responders
END
减慢速度的行是:
inner join [lookup] l on p.dosing = l.lookupid and l.lookupid = 'da_ncd'
此外,将其移至where 子句具有相同的效果:
where p.dosing = 'da_ncd'
否则,查询几乎会立即运行。 >.<
【问题讨论】:
-
是否可以使用int基主键和外键?
-
在做join时,需要把key加载到内存中,内存是50bytes,int/numeric key只有8..
-
是的,这就是我在自己编写的应用程序中如何做到这一点,但这种结构是强加给我的。只是想弄清楚发生了什么:
-
l.lookupid 并不重要 - p.dosing 是否已编入索引?
-
正如一般提示——varchar 连接会比 int 连接更昂贵。如果性能是一个问题,请避免!
标签: database tsql optimization