我在很多采访中都被问过这个问题:
如果有人抱怨查询运行缓慢,首先要做的是什么?
我说我运行sp_who2 <active>
并检查运行的查询,以查看哪个资源占用的资源最多,以及是否存在锁定,阻塞或死锁。
有人可以就此给我提供反馈吗?这是最好的答案还是有更好的方法?
谢谢!
答案 0 :(得分:8)
这是我多年来一直提出的面试问题之一。请记住,我不使用它作为是/否,我用它来衡量他们的SQL Server知识有多深,以及它们是服务器还是代码集中。
你的答案是如何找到哪个查询运行缓慢,并可能检查服务器资源的原因,以确定它突然运行缓慢的原因。根据您的回答,我会开始将您标记为可操作的DBA类型。这些正是操作DBA在接到服务器突然运行缓慢的调用时执行的步骤。如果这就是我正在面试的那就好了,这就是你要找的东西。一旦你发现死锁,我可能会进一步深入研究解决问题的步骤,但我不希望人们能够走得更远。如果它不是死锁或阻塞,那么更好的答案是捕获执行计划并查看是否有陈旧的统计数据。参数嗅探也可能正在进行,因此存储过程可能需要“重新编译”。这些是我看到DBA遇到的典型问题。我不经常采访DBA,所以也许其他人在这里有更深层次的问题。
如果面试是针对开发人员的工作,那么我希望答案更多的是假设我们已经找到了哪个查询运行缓慢,并且它是可重现的。如果需要,我甚至可以继续说明。开发人员可以控制的东西与操作DBA可以控制的东西不同,所以我希望开发人员开始查看代码。
人们通常建议此时查看执行计划,因此建议将其作为一个好答案。我稍后会解释为什么我不一定同意这是最好的第一步。如果受访者确实碰巧在此时提到了执行计划,那么我的后续问题就是询问他们在执行计划中寻找什么。最常见的答案是寻找表扫描而不是寻找,可能显示缺失索引的迹象。这些答案向我展示了使用执行计划的更多经验,这与寻找具有最高百分比和/或寻找粗线的步骤有关。
我发现很多查询调优工作在开始执行计划和解决方案时变得误入歧途,因为调整查询的人不知道他们想要执行计划的样子,只是他们不喜欢他们拥有的那个。然后他们将尝试关注看似表现最差的步骤,添加索引,查询提示等,当它可能由于某些其他步骤而导致整个执行计划被颠倒翻转,并且他们正在调整错误片。例如,如果在外键上有三个表连接在一起,而第三个表缺少索引,则SQL Server可能会决定下一个最佳计划是以相反的方向遍历表,因为主键索引存在那里。副作用可能是看起来第一个表是有问题的表,而实际上它是第三个表。
我调整查询的方式,以及我更喜欢听到的答案,就是查看代码并了解代码尝试做什么以及我希望连接如何流动。我开始将查询分解为从第一个表开始的碎片。请记住,我在松散地使用术语“第一”来表示我希望SQL Server启动的表。这不一定是列出的第一个表。然而,它通常是最小的桌子,特别是应用了“where”。然后我将逐一添加其他表格以查看是否可以找到查询向南的位置。它通常是一个缺失的索引,没有sargability,基数太低或陈旧的统计数据。如果你作为受访者在上下文中使用这些确切的术语,无论是谁在面试你,你都会提出这个问题。
此外,一旦您期望联接如何发展,现在是将您的期望与实际执行计划进行比较的好时机。这就是你如何判断一个计划是否已经发生在你身上的原因。
如果我回答这个问题,或者调整一个实际的查询,我还要补充一点,我喜欢在表上获取行计数,并查看连接中所有列的选择性和“where”子句。我也想看看数据。有时问题在代码中并不明显,但当你看到一些数据时就会变得很明显。
答案 1 :(得分:1)
我真的不能说哪个是最好的答案,但我会回答:分析Actual Execution Plan。这应该是检查性能问题的基础。
互联网上有很多关于分析执行计划的信息。我建议你看一下。
答案 2 :(得分:1)
使用SQL事件探查器。执行所需的设置并运行存储过程并检查哪个语句的持续时间更长。单独执行这些语句,获取执行计划。检查错过的索引,加入订单(首先加入小表)。尝试使用临时表joininig表。
答案 3 :(得分:1)
我猜我是基于布鲁斯的访谈模型的编码器,但是我目前正在处理一个缓慢的查询问题,这使我陷入了困境。我们正在使用nHibernate作为我们的ORM,并且在与nHibernate进行通信时,我从未见过的一些差劲的技术没有考虑到“延迟加载”。因此,缓慢的查询之所以缓慢,是因为它实际上是一个可怕的查询,它可以连接每个表(生成的查询占据了屏幕的两页)。当我们使用Linq重新编写该查询时,将删除所有联接。
无论您担任什么角色,我都想问一个问题:这是正确的查询吗,无论是什么角色,都需要成为第一要务。即使作为DBA,如果查询不好,您可能仍建议您更改查询。关注于查询计划和索引以及其他优化微调应该是次要的,以确保您正在优化实际所需的内容。我喜欢布鲁斯对此重点的回答。