加速这个SQL查询?

时间:2012-11-12 21:38:49

标签: sql sql-server-2008

此查询目前大约需要30秒才能运行。

我想帮助加快速度,但不知道如何去做。任何帮助都会很棒。请注意:我目前无法对数据库或其设计进行任何实际更改。

SELECT top 1 v.[address], v.[address2], v.[city], v.[state_prov_id],v.[postcode],
        v.[first_name], v.[last_name], v.[client_specific_id], v.[name], v.phone,
        v.Location_id, v.Contact_id, v.Event_ID, v.client_id, v.program_id,
        v.source_code_id, v.file_source_code_id, v.URL, v.ScriptFrame,
        v.calldatemark, v.NumCallMark + 1 as Numcallmark,
        v.NumCallMarkDay + 1 as NumCallMarkDay,
        v.NumCallMarkWeek + 1 as NumCallMarkWeek, v.autoaudio,
        v.autohumantext, v.automachinetext 
   FROM vw_locationcontactdialer v 
  WHERE v.program_id = 10001565
    and v.numcallmark < 3 
    and (dateadd(hh,72,v.calldatemark) < getdate()
        or v.calldatemark = '01/01/1900' or v.calldatemark is null) 
    and  source_code_id = 10015311 
    and v.contact_id not in ( select contact_ID from CALL_HISTORY with (NOLOCK) 
                               where program_ID = 10001565 
                                 and result_id not in ('8','U','N')
                               group by contact_ID)
  order by calldatemark

我得到了一个提示尝试加入,但我不确定如何实现这一目标。我不确定如何进行JOIN并确保所有不在子查询中的contact_id都已完成。

我想出了这个:

SELECT TOP 1 v.[address], v.[address2], v.[city], v.[state_prov_id],v.[postcode],
            v.[first_name], v.[last_name], v.[client_specific_id], v.[name],
            v.phone, v.Location_id, v.Contact_id, v.Event_ID, v.client_id,
            v.program_id, v.source_code_id, v.file_source_code_id, v.URL,
            v.ScriptFrame, v.calldatemark,
            v.NumCallMark + 1 as Numcallmark,
            v.NumCallMarkDay + 1 as NumCallMarkDay,
            v.NumCallMarkWeek + 1 as NumCallMarkWeek, v.autoaudio,
            v.autohumantext, v.automachinetext 
  from vw_locationcontactdialer v 
  JOIN CALL_HISTORY ch on v.Contact_ID = ch.contact_ID
 where v.Program_ID = 10001565
   and v.NumCallMark < 3
   and (DATEADD(hh,72,v.calldatemark) < GETDATE() 
        or v.CallDateMark = '01/01/1900' or v.CallDateMark is null)
   and v.Source_Code_ID = 10015311
   and ch.result_ID not in ('8','U','N')
 group by ch.contact_id
 order by v.CallDateMark

但由于此错误而无法正常工作,我不完全理解:Msg 8120,Level 16,State 1,Line 1 列'vw_locationcontactdialer.address'在选择列表中无效,因为它不包含在聚合函数或GROUP BY子句中。

任何帮助都会很棒。

3 个答案:

答案 0 :(得分:1)

我可以给你一个小提示:“(DATEADD(hh,72,v.calldatemark)&lt; GETDATE()”条款可以防止calldatemark字段上的索引被使用。 用“v.calldatemark&lt; DATEADD(hh,-72,GETDATE())”替换它可能会有所帮助。

另外,忽略“分组依据”。您只对某些contact_Ids感兴趣。如果subselect的结果只包含几个条目,则在将其转换为JOIN时将无法获得任何性能。

正如评论已经说过的那样,您应该检查并最终发布底层视图的模式,因为它可能是性能不佳的根本原因。

答案 1 :(得分:1)

您可以按如下方式将其转换为联接:

from vw_locationcontactdialer v left outer join
     (select contact_ID
      from CALL_HISTORY with (NOLOCK) 
      where program_ID = 10001565 and 
            result_id not in ('8','U','N')
      group by contact_ID
     ) ch
     on v.contact_id = vh.contact_id
where . . .
      ch.contact_id is null
order by calldatemark

(道歉,如果我尝试发布整个查询,我会收到错误。)

为了使这项工作更好,您可能希望返回原始查询并使用相关子查询:

where
      not exists (select 1
                  from CALL_HISTORY ch with (NOLOCK) 
                  where program_ID = 10001565 and 
                        result_id not in ('8','U','N') and
                        ch.contact_id = v.contact_id
                 )

如果您在CALL_HISTORY.Contact_Id上有索引,那么它会帮助您。更好的是,Call_History上的多部分索引包含contact_id,result_id和program_id。

答案 2 :(得分:0)

我确实想办法让这项工作正常,这是我的代码:

Select top 1 v.[address], v.[address2], v.[city], v.[state_prov_id], v.[postcode], 
v.[first_name], v.[last_name], v.[client_specific_id], v.[name], 
v.phone, v.Location_id, v.Contact_id, v.Event_ID, v.client_id, v.program_id,
v.source_code_id, v.file_source_code_id, v.URL, v.ScriptFrame, v.calldatemark,
v.NumCallMark + 1 as Numcallmark, 
v.NumCallMarkDay + 1 as NumCallMarkDay, 
v.NumCallMarkWeek + 1 as NumCallMarkWeek, v.autoaudio, 
v.autohumantext, v.automachinetext 
from vw_locationcontactdialer v 
left join (select contact_id from CALL_HISTORY 
where program_ID = 10001565 and result_ID not in ('8','U','N') 
group by contact_ID) h on v.Contact_ID = h.contact_ID 
where v.program_id = 10001565 
and v.numcallmark < 3 and (dateadd(hh,72,v.calldatemark) < getdate() 
or v.calldatemark = '01/01/1900' or v.calldatemark is null) 
and  source_code_id = 10015311  
and h.contact_ID is null order by calldatemark