首页 > 解决方案 > 优化带数据时间过长的SQL查询

问题描述

我正在尝试查询一个医疗保健系统,该系统在没有任何评估的情况下计算患者人数(患者在访问诊所时进行的活动)。我想过滤掉特定网络、用户和诊所的结果。

这是我的查询:

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 秒。

有人可以建议一个更好的方法来编写这个查询吗?

编辑

这是查询的执行计划

在此处输入图像描述

在此处输入图像描述

标签: sqlsql-server

解决方案


几个小贴士:

  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 )


推荐阅读