跟踪 ORM 性能
Posted
技术标签:
【中文标题】跟踪 ORM 性能【英文标题】:Tracing ORM performance 【发布时间】:2011-01-26 17:21:18 【问题描述】:这不是“哪个是最快的 ORM”的问题,也不是“如何用 ORM 编写好的代码”的问题。这是另一面:代码已经编写完成,已经上线,数千名用户正在访问应用程序,但存在明显的整体性能问题。 SQL Profiler 跟踪只能运行很短的时间:5 分钟会产生几十万个结果。
问题很简单:在使用 SQL Profiler 缩小了一些慢查询(持续时间大于给定时间)之后,有哪些技术和解决方案可以将这些 SQL 查询追溯到有问题的组件?一个相关的问题是,如果特定区域运行缓慢,我们如何识别该区域正在执行的 SQL,以便在 SQL Profiler 中对其进行适当过滤?
背景是我们有一个相当大的应用程序,它具有相当复杂的表结构,并且当前基于通过存储过程进行的数据访问。如果出现 SQL 性能问题,通常是拔出 SQL Profiler,找出是否有慢的地方(按持续时间过滤)或被投诉的区域是否慢(按存储过程过滤),然后调整存储过程(或架构 - 通过索引)。
现在有推动将我们的代码从主要是存储过程的解决方案转移到主要是 ORM 解决方案的推动力,但是反对这一举措的最大推动力是如何将性能问题(如果出现)追溯到有问题的代码。我已经阅读过,似乎通常它可能涉及我们需要在服务器上安装的第三方工具(ORM 跟踪实用程序,如 NHProf 或 .NET 跟踪实用程序,如 dottrace)。现在是否可以在实时环境中安装额外的工具是另一个问题,所以如果这样的事情可以在没有额外工具的情况下执行,那么这可能是一个奖励。
我最感兴趣的是使用 SQL Server 2008 的解决方案,但它可能对于任何 RDBMS 来说都足够通用。至于 ORM 技术,我对此没有特别关注,因为目前没有任何东西在使用,所以有兴趣了解技术在 nHibernate、fluent-nhibernate 和实体框架之间有何不同(或常见)。如果他们提供其他东西,其他 ORM 也是受欢迎的 :-)
我已通读How to find and fix performance problems (...),我认为问题只是那里的“隔离”部分。 仅在实时系统上很容易重现的问题将难以隔离。我在第 2 段中引用的数字是我们可以从配置文件中获得的卷类型的数字......
如果你有实时 ORM 跟踪的实际经验,那就更好了 :-)
2016 年 10 月 21 日更新:为了完整起见,我们最终通过编写代码和覆盖 NHibernate 方法为 NHibernate 解决了这个问题。我问的另一个 SO 问题的详细信息:NHibernate and Interceptors - measuring SQL round trip times。我希望这对于许多不同的 ORM 来说都是一种类似的方法。
【问题讨论】:
您是否已经熟悉各种 DMV 和报告,这些 DMV 和报告根据执行计划统计而不是分析显示按持续时间、CPU、IO 等显示的***查询?还有什么版本的SQL Server?如果 2008 年有管理数据仓库可能会有所帮助(尽管我猜想通过 ORM 发出的非参数化查询,您最终可能会遇到许多类似的查询和计划,从而使汇总结果变得困难) 有趣的问题,我期待着学习一些关于这个主题的东西,因为我没有答案给你。 @Martin -- 抱歉,2008 年(问题已编辑)。现在您提到会敲响警钟的 DMV 将进行调查。该应用程序目前基于 SQL 2000,但下一个版本将升级到 2008。不太太打扰了大约 2000 个解决方案。虽然一旦我们有了查询,我们如何通过 ORM 层追溯到导致问题的模块? @Chris - RE:回溯我认为它们不会有帮助。它们只会帮助确定要关注的查询,而无需涉及探查器。 @Martin ... 这就是问题所在——如果更改查询的唯一方法是更改 ORM 代码,我就被卡住了 :-) 感谢您的提醒;它肯定会省去一些麻烦。 【参考方案1】:存在用于 ORM 工具的分析器,例如 UberProf。它找出由 ORM 生成的哪些 SQL 语句可能有问题。
例如,选择 n+1 问题。这些工具可能会告诉您哪些 ORM 查询语句会导致 SQL 代码不佳,甚至可能会告诉您如何改进它们。
【讨论】:
这样的工具在负载非常重的实时环境中有多好(请参阅问题中所述的卷)?我假设有了这些,您可以找到以这种方式使用 ORM 的代码?此外,如果我们将应用程序部署在(例如)六台应用程序服务器上,则可能我们必须跟踪超过六台应用程序服务器(尽管我们可以跟踪一个并希望问题出现在那里,然后不能全面了解数据库上发生的情况——所以要与 SQL Profiler 等工具结合使用?)【参考方案2】:我们有一个存在问题的 Java/Hibernate 应用程序,因此我们使用了具有不同值的 SET CONTEXT_INFO。如果我们在 WTF 查询之前看到同一 SPID 上的 0x14,我们可以将其缩小到模块 x。
不是 Java 人,我不知道他们做了什么,当然它可能不适用于 .net。 IIRC 你必须小心何时打开/关闭连接
此时我们还可以控制客户端负载,因此我们没有太多多余的流量。
当然是 YMMV,但它可能有用
我刚刚发现这些也很有用
Temporary tables, sessions and logging in SQL Server? Why is my CONTEXT_INFO() empty?【讨论】:
有趣的方法;我想知道是否有一种“水印”SQL 语句的方法......可能需要进一步研究。以上是关于跟踪 ORM 性能的主要内容,如果未能解决你的问题,请参考以下文章