2009-03-02 15 views
1

このクエリはかなり長いですが、where句を追加するか文字列に追加すると、実行に2秒かかります。なぜ私は理解できません。varchar(50)外部キーで結合するとクエリが遅くなります

inner join [lookup] l on p.dosing = l.lookupid and l.lookupid = 'da_ncd' 

また、where節に移動することと同じ効果があります:

where p.dosing = 'da_ncd' 
をされ、それを遅く

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 

ライン:ここ

はフルでクエリの

それ以外の場合、クエリはほぼ即座に実行されます。 >.<

+0

は、1.lookupidのインデックスに登録されていますか? – sfossen

+0

その主キー – Shawn

+0

は、intベースの主キーとforiegnキーを使用できますか? – sfossen

答えて

2

ああ、申し訳ありませんがわかりました。 Patient.Dosingは、NULLを許可するように設定されました。私はそれが別の種類の索引になったと思います。

0

このテーブルにインデックスを作成して、そのVARCHARフィールドがフィールドのリストに正しく含まれていることを確認してください。

+0

コメントを読んで、それはすでに索引付けされています。 – sfossen

2

質問の回答があっても、記録のため。 通常、このようなことは、実行計画が変更されたために発生します。クエリアナライザの計画を比較します。

2

もう1つの問題はデータ型です。たとえば、p.dosingとl.lookupidが異なる場合、nvarcharとvarcharは大きな影響を与えます。

関連する問題