性能不佳的 SQL 查询

Posted

技术标签:

【中文标题】性能不佳的 SQL 查询【英文标题】:Poorly performing SQL query 【发布时间】:2016-01-05 11:36:45 【问题描述】:

我有如下查询,在 SQL Server 2008 中执行

SELECT
    ipm.HEORG_REFNO,    
    ipm.HOTYP_REFNO,     
    ipm.CASLT_REFNO,     
    ipm.HOLVL_REFNO,    
    IPM.MAIN_IDENT,  
     ...  
FROM  
    dbo.HEALTH_ORGANISATIONS ipm  (NOLOCK)             
LEFT JOIN
    (SELECT
         s.heorg_refno, min(s.start_dttm) as start_dttm_SPONT, max(isnull(convert(datetime,s.end_dttm,120),convert(datetime,'9999-01-01', 120))) as end_dttm_SPONT    
     FROM
         dbo.service_points s (NOLOCK)    
     INNER JOIN
         dbo.reference_values rfval (NOLOCK) ON s.SPTYP_REFNO = rfval.RFVAL_REFNO    
                                             AND RFVAL.MAIN_CODE != 'PDT'         
     GROUP BY 
         s.heorg_refno) SPONT ON ipm.HEORG_REFNO = SPONT.HEORG_REFNO    

 -- Bring only Health Organisation records and also certain records,whose HOTYP_REFNO does not exist in REF_VALS
WHERE
    NOT EXISTS ((SELECT 'x' 
                 FROM REFERENCE_VALUES RVAL (NOLOCK) 
                 WHERE RVAL.RFVAL_REFNO = ipm.HOTYP_REFNO 
                   AND main_code IN ('011','012','015','016',  '017','019','2','AANDE','AEB','AEC','CLINIC','DAYCC','DEPRT','GPSIT','HC','HOSPL','HOST','LOCTN','LOSYN','MIU','MISC','MRL', 'SITE','THEAT','WARD','PDT','NURHM','DAYCR') 
    or ipm.HEORG_REFNO IN(select distinct HEORG_REFNO from SERVICE_POINT_SESSIONS (NOLOCK) where OWNER_HEORG_REFNO = 2001934 and HEORG_REFNO != 2001934) 
    or ipm.HEORG_REFNO IN (select REFNO from LOR_IPM_SYNTH_STG_DEV..  STAGING_Activity_LOCATION_DCS (NOLOCK) where Sources='HEORG_REFNO' and REFNO != 2001934)  
    )
  )

执行查询需要花费大量时间。

当我评论以下 2 行时,它运行得更快:

or ipm.HEORG_REFNO IN(select distinct HEORG_REFNO from SERVICE_POINT_SESSIONS (NOLOCK) where OWNER_HEORG_REFNO = 2001934 and HEORG_REFNO != 2001934) 
    or ipm.HEORG_REFNO IN (select REFNO from LOR_IPM_SYNTH_STG_DEV..  STAGING_Activity_LOCATION_DCS (NOLOCK) where Sources='HEORG_REFNO' and REFNO != 2001934)  

感谢您在调整查询时提供的任何指导

【问题讨论】:

不存在的选择部分是否需要永远自行运行? 要改掉的坏习惯:putting NOLOCK everywhere。可能的影响:脏读、缺失行、两次读取行、读取同一行的多个版本、索引损坏、读取错误…… 不..它运行得非常快.. 【参考方案1】:

我的第一个想法是您的查询非常复杂 - 我会寻找简化它的方法...

In 子句并不总是表现良好 - 我很想将这些信息吸进一个禁止的“main_Codes”表变量中,然后加入它并测试是否为空......

是时候运行执行计划,看看你的瓶颈实际在哪里,这取决于你自己的环境(索引、统计等)......

【讨论】:

【参考方案2】:

尝试将这些 IN 子查询转换为如下所示的 JOIN 查询,并确保在连接条件和 where 过滤条件涉及的所有列上创建了正确的索引。

LEFT JOIN SERVICE_POINT_SESSIONS sps ON ipm.HEORG_REFNO = sps.HEORG_REFNO
AND sps.OWNER_HEORG_REFNO = 2001934 
AND sps.HEORG_REFNO != 2001934

我会将您的查询修改为如下所示。尽管到目前为止我对您的大 inlist 无能为力,但您应该将该 inlist 拉入表变量中,并考虑用它来做 JOIN

SELECT
    ipm.HEORG_REFNO,    
    ipm.HOTYP_REFNO,     
    ipm.CASLT_REFNO,     
    ipm.HOLVL_REFNO,    
    IPM.MAIN_IDENT,  
     ...  
FROM  
    dbo.HEALTH_ORGANISATIONS ipm            
LEFT JOIN
    (SELECT
         s.heorg_refno, min(s.start_dttm) as start_dttm_SPONT, 
         max(isnull(convert(datetime,s.end_dttm,120),convert(datetime,'9999-01-01', 120))) as end_dttm_SPONT    
     FROM
         dbo.service_points s     
     INNER JOIN dbo.reference_values rfval 
     ON s.SPTYP_REFNO = rfval.RFVAL_REFNO  
     AND RFVAL.MAIN_CODE != 'PDT'         
     GROUP BY 
         s.heorg_refno) SPONT ON ipm.HEORG_REFNO = SPONT.HEORG_REFNO

LEFT JOIN SERVICE_POINT_SESSIONS sps 
ON ipm.HEORG_REFNO = sps.HEORG_REFNO 
AND sps.OWNER_HEORG_REFNO = 2001934 
AND sps.HEORG_REFNO != 2001934

LEFT JOIN LOR_IPM_SYNTH_STG_DEV .. STAGING_Activity_LOCATION_DCS sald 
ON ipm.HEORG_REFNO = sald.HEORG_REFNO
AND sald.Sources='HEORG_REFNO' 
AND sald.REFNO != 2001934

WHERE NOT EXISTS (SELECT 1 
                 FROM REFERENCE_VALUES RVAL 
                 WHERE RVAL.RFVAL_REFNO = ipm.HOTYP_REFNO 
                 AND RVAL.main_code IN ('011','012','015','016',  '017','019','2','AANDE','AEB','AEC','CLINIC','DAYCC','DEPRT','GPSIT','HC','HOSPL','HOST','LOCTN','LOSYN','MIU','MISC','MRL', 'SITE','THEAT','WARD','PDT','NURHM','DAYCR')); 

【讨论】:

抱歉.. 将其设为左连接无济于事.. 而且我们对 DB 没有任何权限.. 它的“只读”用于所有实际用途... 对不起..它没有..我基本上是在检查服务点会话表中不存在来自 ipm 的记录..我什至添加了一个“WHERE SPSSN.HEORG_REFNO IS NULL”子句..但它仍然没有提供所需的输出..

以上是关于性能不佳的 SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章

性能不佳的 ML Kit 条码扫描

Windows 上 localtime_s() 多线程性能不佳的解决方法

谷歌创造ImageNet1K新纪录:性能不佳的微调模型不要扔,求一下平均权重就能提升性能...

Oracle 中最耗时的 5 个 SQL 查询

SQL Server 查询性能不佳

CTE 中的 SQL Server 视图导致性能不佳