优化SQL查询,查找表中不存在的条目

时间:2012-01-17 17:54:44

标签: sql query-optimization

我有一个包含作业状态的日志表。其中一列是工作名称。有时工作根本不会运行,因此没有条目。我的SQL确定日志中哪些作业“丢失”。

此查询大约需要17分钟,这很长。我有很多其他更复杂的(至少看起来更复杂),不需要这么长时间。

如何优化?

-- Display missing jobs. Thats jobs that are not in job log but should be
declare @startDate datetime, @endDate datetime
declare @rangeInHours int
set @rangeInHours = -24
set @endDate = '2012-01-17 12:00:01'
set @startDate = dateadd(hour, @rangeInHours, @endDate)

declare @myTable table( name nvarchar(50))
insert into @myTable values('Activity work')
-- There are another 100 entries like this one above to add all the expected jobs

-- this is my sql to find missing jobs
select distinct i.name from @myTable i
where not exists
 ( select 1 from job_log j
     where j.name = i.name 
       and j.start_date > @startDate and j.start_date < @endDate
  )
order by i.name asc

通过了许多线程,但找不到合适的答案,至少有一个我能用我有限的SQL理解和实现。

3 个答案:

答案 0 :(得分:1)

您可以尝试以下方法,它可能会比嵌套选择提供更好的性能。

select distinct m.name
from @myTable m
left outer join job_log j on j.name = m.name and j.start_date > @startDate and j.start_date < @endDate
where j.name is null

答案 1 :(得分:1)

与大多数SQL问题一样,答案取决于您的架构,而不是您的查询。要检查@start和@end之间的名称@name和start_date是否存在,那么必须在(name,start_date)上有索引:

create index job_log_name_start on (name, start_date);

作为一般规则,在询问SQL问题时,请始终发布所涉及的表的确切定义,包括所有索引。 job_log的聚集索引键是什么?时间序列通常按时间键聚类,因为大多数查询都会询问时间范围,这会使您的job_log表可能由start_date聚集。

对于更多花哨的东西,回答'此条目的一般解决方案肯定不存在?'用Bloom filters回答,我见过基于SQL的实现(例如哈希name和工时)。

答案 2 :(得分:0)

请确保您在job_log.name上有索引。

DECLARE @rangeInHours int = -24; 
DECLARE @endDate datetime = '2012-01-17 12:00:01';
DECLARE @startDate datetime = DATEADD(hour, @rangeInHours, @endDate);    
DECLARE @ExpectedJobs table(name nvarchar(50));

INSERT INTO @ExpectedJobs values('Activity work'), ('foo'), ('bar');

SELECT      e.name AS MissingJob
FROM        @ExpectedJobs AS e
LEFT JOIN   job_log AS j ON j.name = e.name 
WHERE
    j.[name] IS NULL
AND j.start_date > @startDate 
AND j.start_date < @endDate
GROUP BY e.name
ORDER BY e.name;