我有两张表,99% 的操作都是简单的选择。我们很少有插入/删除和更新。
这些表上有一个内部连接,查询的执行计划是index seek。99% 的查询运行速度非常快(大约 1 秒)。但有时查询需要 30 秒才能运行。
这件事发生的时间没有任何规律。有一次发生在“12 月 1 日凌晨 3:17:20”。一次在“12 月 8 日晚上 10:13:43”。有一次发生在“12 月 11 日下午 16:50:43”。
我怎样才能找到这个问题来自哪里的线索?
SQL Server 是否有记录所有事件的工具?
我的查询只有简单的 where 子句:where id = @id
。
SQL Server 2014 没有为您提供很多选项来调查过去运行的查询的性能不佳。您可以尝试检查错误日志以查看在您的慢查询执行附近是否发生了任何灾难性事件。例如,可能有一个耗时超过 15 秒的长 I/O。您还可以检查系统健康扩展事件。例如,可能在您的慢查询执行附近发生了长时间的锁定等待(>30 秒)。
听起来您真正需要的是增加应用程序日志记录(您已经知道错误发生的精确秒数,因此请考虑在查询运行时间超过预期时记录性能信息),购买 SentryOne 等 SQL Server 监控工具,或升级到 SQL Server 2017 并查看查询存储等待统计信息。您应该知道,即使使用其中许多工具,调查一年前发生的性能问题也会很困难。
如果它真的只是一个简单的
SELECT ... FROM tbl where tbl.id = @id
(没有连接等)我会假设,这是一个阻塞问题。这通常是由于应用程序编写不当造成的:begin transaction
COMMIT
或他拒绝并且应用程序执行ROLLBACK
通常用户快速点击按钮,一切都很好。但有时他去吃午饭或接电话或其他什么,有时甚至应用程序前端/浏览器崩溃,所以你现在对这一行有很长的锁定。当用户自己或其他人现在想要选择相同的ID时,他必须等待......
Erik Darling 的上述答案可能就是您正在寻找的。所以在这里我不会过多的介绍。
你知道查询每次都使用相同的执行计划吗?我已经多次看到应用程序使用动态 SQL 污染计划缓存。95% 的时间使用的参数返回少数行。典型的计划通常是索引查找。然后在另外 5% 的时间里,参数匹配更多的行并且 SQL 进行索引扫描。