如何根据执行后报告的读取次数来衡量查询与可接受的阈值(关于性能)的距离?
示例:为了让自己清楚,如果我们谈论的是汽油里程为 40 mpg 的汽车的每加仑英里数,并且我们必须行驶 40 英里的距离,那么最佳性能的阈值是 1 加仑行驶那个距离。因为不是每个人都像Max Verstappen 或 Lewis Hamilton那样开车,如果你是一个糟糕的车手,你可以花 1.3 甚至 2 加仑的油来跑那个距离。但是如果你花 30 加仑去一个 40 英里外的地方,我可以说你肯定走错了路。
背景:有时我运行sp_whoisactive只是为了找到一个报告类似 1,248,909 次读取的查询(因为每页是 8 KB,这意味着从4.4 GB的数据库中处理了大约 9.7 GB 的数据)。这意味着一个查询读取整个数据库两次。当我看到类似的东西时,我的直觉告诉我有些地方出了问题,但开发人员有时会争辩说“这是一个复杂的查询,它应该表现得像那样”。然后我必须改进查询,以证明即使复杂的查询会消耗更多资源,但有一个阈值表明您偏离了轨道。
是否有一个公式可以根据所涉及的表数量、连接类型、函数的使用等来计算它?如果没有,是否有经验法则可用于进行合乎逻辑的论证?
不幸的是,不,我认为您不会找到公式甚至经验法则。它只是过于多样化和抽象,没有一个标准可以通过,因为它会因具体情况而异。对于查询 A,在 4.4 GB 大的数据库中读取 9.7 GB 数据的 1,248,909 次读取可能是完全正确的,而具有相同精确指标的查询 B 可能会引起关注和优化案例。只有您作为 DBA/数据库开发人员/准数据库老兄才能真正利用您对数据库和使用应用程序的深入了解以及直觉来确定单个查询是否正在使用有效数量的资源。
话虽如此,我通常会怀疑大量数据处理查询,尤其是在如此小的数据库中,例如上面提到的查询 A。因此,我会考虑研究诸如此类的示例,但您还必须考虑这样的查询对服务器其余部分的性能影响。即它是否在繁忙的服务器上消耗来自其他查询的资源?是否过度阻塞其他查询/锁定所涉及的基础表?它的运行时间是否很慢,或者它会在一个非常可接受的时间范围内返回?如果它通过了这类问题的测试,虽然它可能值得记录以供将来参考,但现在可能不值得你花时间尝试优化,因为通常有更大的鱼要炸与服务器上的其他实际性能问题(实际上导致问题的其他查询或可以完成的数据库或服务器调整)。
另外,我将补充一点,您可以通过查看请求的内存和授予的内存与查询的已用内存来确定某些查询是否消耗了不必要的资源。它应该是实际执行计划的一部分,SentryOne 的 Plan Explorer 工具允许您突出显示单个操作员(尽管 SSMS 也可能在突出显示时显示?)并查看该操作员的这些指标。通常我会发现我的执行计划中是否存在基数估计问题,它认为返回的行数将比实际多得多,请求的内存量和授予的内存量显着超过已用内存. 这意味着不仅将不必要的资源从服务器分配给该查询,而且该查询本身必须等待额外的时间才能分配这些资源。您还可能遇到查询运行速度较慢的相反问题,因为它低估了所需的内存量,因此从服务器请求的内存太少。Brent Ozar 有一篇很好的文章An Introduction to Query Memory详细介绍了这些内存指标。