JOIN语句中的OR问题

时间:2009-08-30 02:17:21

标签: sql performance join

我的SQL语句有问题,详见下文。查询返回我需要的结果,但需要花费大量的时间来执行。我现在在db中有这么多记录,通常不会加载页面。

SELECT dscan.guid, dscan.drive, dscan.folder, dscan.filename, source.guid  
FROM source 
RIGHT JOIN dscan ON (
  (source.guid & '_dtr' = dscan.guid OR source.guid & '_dto' = dscan.guid OR source.guid = dscan.guid)  
  AND dscan.guid LIKE '%" & Replace(strSearch_guid, "'", "''") & "%'  
  AND dscan.filename NOT LIKE '.[_]%'  
  AND dscan.drive = 'Z:')  
WHERE source.guid Is Null  
ORDER BY dscan.drive, dscan.guid

从我在网上找到的,JOIN语句中的OR是一个问题,但我无法弄清楚如何解决这个问题。

我正在将数据库记录与文件名进行比较以识别错误 - 但文件名有时会包含“_dtr”或“_dto”附件,我必须将其考虑在内。

7 个答案:

答案 0 :(得分:1)

使用构造的谓词比较值,以及在开头使用wildcrads的“Like”将需要完整的表扫描。在您重新设计架构以消除此问题之前,这将是大型表的主要性能影响。但是,您可以通过合并三个单独的sql语句来消除OR中的性能损失。试试这个:

    SELECT D.guid, D.drive, D.folder, D.filename, S.guid  
    FROM dscan D Left Join source S
        ON S.guid & '_dtr' = D.guid 
          AND D.guid LIKE '%" & Replace(strSearch_guid, "'", "''") & "%'   
          AND D.filename NOT LIKE '.[_]%'    
          AND D.drive = 'Z:')  
    WHERE S.guid Is Null  
  Union
    SELECT D.guid, D.drive, D.folder, D.filename, S.guid  
    FROM dscan D Left Join source S
        ON S.guid & '_dto' = D.guid  
          AND D.guid LIKE '%" & Replace(strSearch_guid, "'", "''") & "%'   
          AND D.filename NOT LIKE '.[_]%'    
          AND D.drive = 'Z:')  
    WHERE S.guid Is Null  
  Union
    SELECT D.guid, D.drive, D.folder, D.filename, S.guid  
    FROM dscan D Left Join source S
        ON S.guid = D.guid    
          AND D.guid LIKE '%" & Replace(strSearch_guid, "'", "''") & "%'   
          AND D.filename NOT LIKE '.[_]%'    
          AND D.drive = 'Z:')  
    WHERE S.guid Is Null  
    ORDER BY D.drive, D.guid

答案 1 :(得分:0)

我认为你应该尝试用一些括号来解剖它。

((source.guid&'_dtr'= dscan.guid)OR(source.guid&'_dto'= dscan.guid)OR(source.guid = dscan.guid))

答案 2 :(得分:0)

or是臭名昭着的表演吸盘。请尝试使用in子句。:

SELECT dscan.guid, dscan.drive, dscan.folder, dscan.filename, source.guid  
FROM source 
RIGHT JOIN dscan ON (
  dscan.guid in (source.guid & '_dtr', source.guid & '_dto', source.guid)
  AND dscan.guid LIKE '%" & Replace(strSearch_guid, "'", "''") & "%'  
  AND dscan.filename NOT LIKE '.[_]%'  
  AND dscan.drive = 'Z:')  
WHERE source.guid Is Null  
ORDER BY dscan.drive, dscan.guid

但是,最好的是,使用您的查询执行计划来真正了解数据库引擎正在做什么。然后,您可以看到真正的瓶颈所在,以及可以添加哪些索引以加快查询速度。

答案 3 :(得分:0)

也许你可以重新订购东西。你可以尝试:

  • 首先从dscan中选择(我假设dscan上的正确连接意味着你想要它的所有行)。在那之后你可能甚至不需要正确的加入。
  • 重新订购您的ON条款,例如。将比较最有可能首先失败 - 利用短路。把所有的AND放在第一个和OR的最后一个
  • 将一些比较从ON子句移到WHERE子句

答案 4 :(得分:0)

实际上,我认为您的性能问题不是来自“OR”,而主要是因为您使用串联字符串来进行连接。

同时加入字符串数据并不能提供最佳性能。另一方面,如果列被索引(在它们上添加索引),它会有所帮助(如果你没有再次连接字符串)

作为一个解决方案,我不知道是否有可能或想要在该表中添加列并包含已添加“extensions”的字符串版本,因此查询不需要连接它们?

这些是一些解决方法,而不是真正的解决方案

答案 5 :(得分:0)

我重写了你的查询:

 SELECT d.guid, 
        d.drive, 
        d.folder, 
        d.filename,
        src.guid
   FROM DSCAN d
   JOIN (SELECT s.quid,
                s.quid & '_dtr' AS DTR,
                s.quid & '_dto' AS DTO,
           FROM SOURCE s
          WHERE s.guid IS NOT NULL) src ON d.guid IN (s.quid, s.dtr, s.dto)
   WHERE d.guid LIKE '%' & REPLACE(strSearch_guid, "'", "''") & '%'
     AND d.filename NOT LIKE '.[_]%'  
     AND d.drive = 'Z:'
ORDER BY d.drive, d.guid

我假设您在OP中有一个关于source.guid IS NULL的类型 - 没有意义,您只需要NULL source.guid记录,然后连接到它们。

此:

RIGHT JOIN dscan ON (source.guid & '_dtr' = dscan.guid OR 
                     source.guid & '_dto' = dscan.guid OR 
                     source.guid = dscan.guid)

...只会在guid列上使用索引(假设存在一个)来创建值 not 进行比较。如果您需要这样做,最好在内联视图或CTE /子查询保理中构建它们。

答案 6 :(得分:0)

现在让我们通过以下内容查看您的select语句:

SELECT dscan.guid,dscan.drive,dscan.folder,dscan.filename,source.guid
来源 RIGHT JOIN dscan ON

并以此结束:

WHERE source.guid是否为空 ORDER BY dscan.drive,dscan.guid

因此,如果我正确读取您尝试读取dscan表中的所有内容以及与源表匹配的anthing。

??如果您查找source.guid为null,究竟如何链接这两个表?因为如果source.guid为null,为什么你会这样做:

<强>源 RIGHT JOIN dscan ON(   (source.guid&amp;'_dtr'= dscan.guid OR source.guid&amp;'_dto'= dscan.guid OR source.guid = dscan.guid)
  AND dscan.guid LIKE'%'&amp; Replace(strSearch_guid,“'”,“''”)&amp;“%'
  AND dscan.filename NOT LIKE'。[_]%'
  AND dscan.drive ='Z:')

您的查询需要很长时间,因为它会在联接中丢失。你的尝试 让它过滤太多东西并过滤像'%blah blah%'那样 帮助加快速度。检查源表和dscan表上是否有正确的索引。

为什么 WHERE source.guid是NUll 您需要source.guid与dscan表中的dscan.guide匹配。