如何优化这个永远需要的SQL查询?

时间:2015-03-12 15:41:07

标签: sql sql-server-2008 query-optimization

我正在尝试优化此查询,因为它需要30秒才能执行:

SELECT
   TOP 100 table1.* 
FROM
   table1 (NOLOCK)     
INNER JOIN
   DB1..table2 (NOLOCK) 
      ON DB1..table2.id = DB1..table1.id    
INNER JOIN
   DB1..table2_batch (NOLOCK) 
      ON DB1..table2_batch.table2_batch_id = DB1..table2.table2_batch_id    
INNER JOIN
   DB2..table4 (NOLOCK) 
      ON CASE 
         WHEN CHARINDEX(':',
      table2_batch.reference_number,
      3) > 3 THEN SUBSTRING(table2_batch.reference_number,
      3,
      CHARINDEX(':',
      table2_batch.reference_number,
      3) -3 ) 
      ELSE 
   RIGHT(table2_batch.reference_number,
   LEN(table2_batch.reference_number) -2) 
end = Cast(table4.PurchaseOrderID as int)    INNER JOIN
   DB2..table3 (NOLOCK) 
      ON  DB2..table3.key =  DB2..table4.key 
WHERE
   table1.id IS NOT NULL  
   AND (
      table1.id!='' 
      OR table1.id IS NULL
   ) 
   AND   DB2..table3.AccountTypeID != 30000 
   AND CHARINDEX('O', DB1..table2_batch.reference_number) = 1 
   AND  table1_id NOT IN (
      select
         lim.table1_id 
      from
         link_table1_message as lim (nolock) 
      inner join
         table1 as i (nolock)  
            on i.table1_id = lim.table1_id 
      where
         lim.message_id >= 90
   ) 
ORDER BY
   last_hit DESC

1 个答案:

答案 0 :(得分:0)

基于this comment

  

瓶颈在于DB2..table4连接。当我把那部分拿出来时,查询真的很快......但我真的需要加入那里来确保这种情况符合适当的条件。

它有点猜测,因为我们不知道涉及多少行,也不知道你的架构是什么样的,但做了一些假设,这个可能求助:

INNER JOIN
   DB2..table4 (NOLOCK) 
      ON CASE 
         WHEN CHARINDEX(':',
      table2_batch.reference_number,
      3) > 3 THEN SUBSTRING(table2_batch.reference_number,
      3,
      CHARINDEX(':',
      table2_batch.reference_number,
      3) -3 ) 
      ELSE 
   RIGHT(table2_batch.reference_number,
   LEN(table2_batch.reference_number) -2) 
end = Cast(table4.PurchaseOrderID as int)

在我发现的join中有很多逻辑。

您的table2_batch reference_number编码了一个您最终需要提取并用于加入table4.PurchaseOrderID的值的with cteTable2 as ( select table2_batch_id ,reference_number ,case when charindex(':',reference_number,3) > 3 then substring(reference_number,3,charindex(':',reference_number,3) - 3) else right(reference_number,len(reference_number) - 2) end PurchaseOrderID from table2_batch ) ;我首先选择第一个:

cteTable2

然后,您可以将select视为后续table2_batch语句中的完整表格,因此您不必加入cteTable2,而是加入inner join DB2..table4 (NOLOCK) on cteTable2.PurchaseOrderID = cast(table4.PurchaseOrderID as int)

cast

......真的需要{{1}}吗?