优化SQL查询花费的时间太长

时间:2018-10-05 06:27:52

标签: sql sql-server

我正在尝试查询一个医疗系统,该系统计算没有任何评估的患者人数(患者去诊所就诊的活动)。我想过滤出特定网络,用户和诊所的结果。

这是我的查询

select count(*) as Qualify from 
UserClinic uc
INNER JOIN Patient p on p.DefaultClinicId = uc.ClinicId and uc.UsersId = 47 and p.NetworkId = 2
where 
p.ActivePatient = 1
and p.deleted = 0
and not exists(select * from PatientToxicologyTesting ptt where ptt.PatientID = p.PatientID)
and not exists(select * from PatientPrescriptionRegistry ppr where ppr.PatientID = p.PatientID)
and not exists(select * from PatientPillCount pc where pc.PatientID = p.PatientID)
and not exists(select * from PatientControlledSubstanceAgreement csa where csa.PatientID = p.PatientID)
and not exists(select * from PatientHealthAssessment mha where mha.PatientID = p.PatientID)

UserClinic是User与Clinic之间的多对多关系表。 患者链接到网络和诊所。

上面的查询需要3分钟的时间来执行,如果我从查询中删除了UserId或NetworkId加入条件,那么这个时间将大大减少到1秒。

有人可以建议一种更好的方式编写此查询吗?

编辑

这是查询的执行计划

enter image description here

enter image description here

1 个答案:

答案 0 :(得分:2)

一些提示:

  1. 如果您对尝试选择的特定值不感兴趣,请不要使用“ COUNT(*)”或“ SELECT *”。我建议使用“ COUNT(1)”或“ SELECT 1”
  2. 再次检查在PatientID部分中使用的表的NOT EXISTS列上是否具有索引。这些表应检查:PatientToxicologyTesting, PatientPrescriptionRegistry, PatientPillCount, PatientControlledSubstanceAgreement and PatientHealthAssessment。您有CLUSTER INDEX SCAN,这意味着索引丢失或碎片化。如果索引高度分散,则对其进行重建/重新组织。
  3. 您可以在Patient表上创建过滤索引以支持此查询

    Create Index IX_Patient_Filter_1 ON Patient(NetworkId,DefaultClinicId) WHERE ActivePatient = 1 AND deleted = 0

  4. 您可以在UserClinic表上创建支持索引

    Create Index IX_UserClinic_1 ON UserClinic(UsersId,ClinicId )