如何调查为什么每天运行2分钟的sql脚本需要2个小时?

时间:2012-12-12 17:38:26

标签: sql sql-server performance sqlprofiler

我的同事今天问我一个问题

  

“我有一个包含4个选择查询的SQL脚本。我一直在使用它   每天超过一个月,但昨天相同的查询花了2个小时   我不得不中止执行。“

他的问题是

  • Q1。那天这个剧本怎么了?
  • Q2。我怎样才能检查那4个查询中哪些被执行以及哪一个是中止的罪魁祸首?

我对Q2的回答是使用SQL分析器并检查Sql语句事件的跟踪。

第一季度: 我问他几个问题

  1. 那天的数据量是多少? 他的回答:没有改变
  2. 索引是否有任何变化,即某人可能已删除索引? 他的回答:没有改变
  3. 通过检查数据管理视图来跟踪它是否陷入僵局? 他的回答:没有陷入僵局
  4. 你认为我还应该考虑什么?可以有任何其他原因吗?

    由于我没有看到查询,所以我无法将其粘贴到此处。

3 个答案:

答案 0 :(得分:1)

要注意的事项(SQL Server):

  1. 统计数据已过期?有人运行大型批量插入操作吗?运行update statistics

  2. 索引的变化?如果是,如果是存储过程,请检查执行计划和/或重新编译...然后再次检查执行计划并纠正任何问题。

  3. SQL Server缓存执行计划。如果查询是参数化的或使用if-then-else逻辑,则第一次运行时,如果参数是边缘情况,则缓存的执行计划对于普通执行可能效果不佳。你可以在这里阅读更多关于这个......啊...的功能:

答案 1 :(得分:0)

在这种情况下,我的方法是:

  1. 在这种情况下,他不得不中止执行,因为查询所花的时间超过了预期的时间,最终没有完成。据我了解,您正在查询的表可能存在任何阻塞会话/未提交的事务(当天有任何其他用户执行)。由于您正在执行“ select”语句,并且据我所知,“ select”语句用于等待任何其他事务完成(如果该事务在“ select”之前执行)。您的查询可能正在等待任何其他事务完成(该事务可能具有更新/插入或删除)。检查是否有阻止会话。

  2. 对于单个会话,sql服务器在线程之间切换。您需要检查包含查询的线程是否处于“已暂停” /“正在运行”或“可运行”模式。在您的情况下,您的查询可能处于暂停模式。调查查询的模式以及原因。

  3. 接下来是碎片。最佳实践是在您的环境中配置索引重建/重组作业,这有助于消除不必要的碎片。这样您的查询在返回数据时将需要扫描更少的页面。否则,您的查询将花费越来越多的时间返回数据。配置作业并每周至少执行一次该作业。它将不断刷新您的索引和页面。

答案 2 :(得分:-1)

  • Use EXPLAIN分析四个查询。这将告诉您优化器将如何使用索引(或不使用索引)。

  • 在语句之间向脚本添加查询SELECT NOW(),以便您可以测量每个查询所花费的时间。您也可以让MySQL为您做算术,将NOW()存储到会话变量中,然后使用TIMEDIFF()来计算语句的开始和结束之间的差异。

    SELECT NOW() INTO @start;
    SELECT SLEEP(5); -- or whatever query you need to measure
    SELECT TIMEDIFF(@start, NOW());
    
  • @Scott在评论中建议使用slow query log来衡量长时间运行查询的时间。

  • 确定长时间运行的查询后,请在执行查询时使用查询PROFILER,以确切了解其花费时间的位置。