我有一个包含作业状态的日志表。其中一列是工作名称。有时工作根本不会运行,因此没有条目。我的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理解和实现。
答案 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;