查询执行速度慢:执行时间长=>非常奇怪为什么?

时间:2019-03-06 21:15:56

标签: sql sql-server performance tsql

我正在使用Microsoft的SQL Server 2012 Express。数据库/数据大小从小到中等,仅包含50个表,尽管某些表确实具有100k-200k记录。给我带来麻烦的查询确实在较大的表之一(time_list)上运行。

涉及的表:

  • time_list(约20万条记录)
  • Code_Department_Types(20条记录)
  • Code_Billing_Types(50条记录)
  • Job_Info(约65k条记录)
  • 工作地址(〜83k记录)
  • Job_Plans(约75,000条记录)
  • 公司(约5k条记录)

坏消息:当前表除了PK / FK之外没有其他索引

问题:

我有一个查询(见下文),运行速度非常慢,执行速度取决于应用于查询的日期过滤器,但是运行缓慢的原因却很直观。

基于以下我的测试案例的观察:

  1. 看来,一旦我尝试在2019年内查询任何内容,就会破坏性能。

  2. 有趣的是,我可以查询巨大的日期范围,并且一切运行良好,但是2019年的一个非常具体的范围导致查询停顿。 我什至通过完全删除日期过滤器来运行查询,它在681毫秒内执行。

  3. 此问题在LIVE服务器和测试服务器上可见,并且可以通过在查询中使用日期过滤器来重现。尽管硬件有所不同,但两台服务器的时延都非常相似。

    让我介绍一下测试用例(日期过滤器应用在查询的底部):

    • 情况1)执行时间:681 ms <=闪电快

    没有日期过滤器,查询返回结果集中最多的记录。

    • 情况2)执行时间:1.1秒<=快!

    日期过滤范围:t.date在“ 1900-01-01”和“ 2019-03-31”之间

    时间范围:〜119年

    • 情况3)执行时间:1:40分钟(秒)==慢

    日期过滤范围:t.date在“ 2019-01-01”和“ 2019-03-06”之间

    时间范围:〜3个月

    • 情况4)执行时间:必须在6分钟后停止查询,但它一直继续运行<= SUPER SLOW

    日期过滤范围:t.date在“ 2018-03-01”和“ 2019-03-31”之间

    时间范围:〜1年

实际查询:

select 
    result.JobId as ProjectId, job.file_number as FileNumber, 
    job.street_name1 as ProjectAddress, addr.StreetMetadata as AddressMetadata, 
    client.client_number as ClientNumber, 
    pln.Lot as PlanLot, pln.plan_number as PlanNumber,
    result.TimeDate as TimeDate
from
    (select distinct
         job.entity_id as JobId, job.client_entity_id as ClientId, 
         (select top 1 t2.date 
          from time_list t2
          inner join Code_Department_Types dept2 on dept2.entity_id = t2.department_id
          inner join Code_Billing_Types bill2 on bill2.entity_id = t2.billing_id
          where (t2.job_id = job.entity_id and ((bill2.name='L/O on GRADE' and dept2.name='F')))
          order by t2.date desc) as TimeDate
    from 
        time_list t
    inner join 
        Code_Department_Types dept on dept.entity_id = t.department_id
    inner join 
        Code_Billing_Types bill on bill.entity_id = t.billing_id
    inner join 
        Job_Info job on t.job_id = job.entity_id
    where 
         EXISTS (select t.entity_id FROM time_list t1
                inner join Code_Department_Types dept on dept.entity_id = t1.department_id
                inner join Code_Billing_Types bill on bill.entity_id = t1.billing_id
                where 
                    t1.job_id = job.entity_id and (bill.name='L/O on GRADE' and dept.name='F')
        ) and not 
         EXISTS (select t.entity_id FROM time_list t1
                inner join Code_Department_Types dept on dept.entity_id = t1.department_id
                inner join Code_Billing_Types bill on bill.entity_id = t1.billing_id
                where 
                    t1.job_id = job.entity_id and (bill.name='SRPR' and dept.name='F')
        )
            and t.date between '1900-01-01' AND '2019-03-31' -- FAST! (1.1 sec)
            --and t.date between '2019-01-01' and '2019-03-06'  -- SLOW (1:40)
                --and t.date between '2018-03-01' AND '2019-03-31'  -- SLOW (> 6 mins, and still going, had to stop it)
        ) as result

        inner join Companies client on client.entity_id = result.ClientId
        inner join Job_Info job on job.entity_id = result.JobId
        inner join Job_Address addr on addr.JobId = job.entity_id
        inner join Job_Plans pln on pln.job_id = result.JobId
        order by FileNumber asc;

2 个答案:

答案 0 :(得分:1)

正如帖子所指出的,在日期字段上添加索引可立即解决问题。我将对此进行监视,但现在将此帖子标记为“已回答”。

答案 1 :(得分:0)

您的注释中指定了有关更新日期参数的运行时间增量,这表明存在一些数据完整性问题。这有帮助吗?

CAST(t.[Date] AS DATE) BETWEEN '1900-01-01' AND '2019-03-31'