我的一位同事声称,即使执行路径被缓存,从 ORM 生成的参数化 SQL 也不可能像存储过程一样快。对这个顽固的开发人员有任何帮助吗?
13 回答
我将从阅读这篇文章开始:
这是两者之间的速度测试:
第 1 轮 - 您可以启动探查器跟踪并比较执行时间。
对于大多数人来说,说服他们的最好方法是“向他们展示证据”。在这种情况下,我将创建几个基本的测试用例来检索相同的数据集,然后计算使用存储过程与 NHibernate 相比需要多长时间。一旦你有了结果,就把它交给他们,大多数持怀疑态度的人应该屈服于证据。
我只会在 Rob 的回答中添加几件事:
首先,确保测试用例涉及的数据量与生产值相近。换句话说,如果您的查询通常针对具有数十万行或行的表,则创建这样的测试环境。
其次,除了使用 nHibernate 生成的查询和 s'proc 调用外,其他一切都相同。希望您可以通过简单地更换提供者来执行测试。
最后,要意识到通常比存储过程与 ORM 有更多的利害关系。考虑到这一点,测试应该考虑所有因素:执行时间、内存消耗、可伸缩性、调试能力等。
这里的问题是你已经接受了举证责任。你不太可能像那样改变别人的想法。不管你喜不喜欢,人们——甚至是程序员——都太情绪化了,不会轻易被逻辑所左右。你需要把举证责任重新推给他——让他说服你——这将迫使他进行研究并为自己找到答案。
使用存储过程的一个更好的论点是安全性。如果只使用存储过程,没有动态 sql,则可以禁用应用程序数据库用户的 SELECT、INSERT、UPDATE、DELETE、ALTER 和 CREATE 权限。这将保护您免受大多数二阶 SQL 注入的影响,而参数化查询仅对一阶注入有效。
测量它,但在非微基准中,即代表系统中实际操作的东西。即使存储过程对性能有微小的好处,但与代码所产生的其他成本相比,它是微不足道的:实际检索数据、转换数据、显示数据等。更不用说使用存储过程相当于传播你的逻辑在您的应用程序和数据库中,没有重要的版本控制、单元测试或重构支持。
自己对它进行基准测试。编写一个测试平台类,执行数百次采样存储过程,并运行相同次数的 NHibernate 代码。比较每种方法的平均和中值执行时间。
如果每次查询都相同,则同样快。Sql Server 2005 在批处理中的每条语句级别缓存查询计划,而不管 SQL 来自何处。
长期的不同可能是存储过程对于 DBA 来说管理和调整要容易很多很多倍,而必须从分析器跟踪中收集的数百个不同的查询是一场噩梦。
我已经多次争论过这个问题。
几乎总是我最终得到一个非常好的 dba,并在运行分析器的情况下运行一个 proc 和一段代码,并让 dba 显示结果非常接近,可以忽略不计。
测量它。
真的,在你衡量之前,任何关于这个话题的讨论都可能是徒劳的。
对于他正在考虑的特定用例,他可能是正确的。对于一些可以任意调整的复杂 SQL 集,存储过程可能会执行得更快。但是,您从诸如休眠之类的东西中获得的东西是缓存。对于您的实际应用程序的生命周期,这可能会更快。
额外的抽象层将导致它比对 sproc 的纯调用要慢。仅仅因为您在托管堆上有额外的分配,以及额外的推送和弹出调用堆栈,事实是调用存储过程比让 ORM 构建查询更有效,不管有多好ORM 是。
有多慢,如果它甚至可以测量,是有争议的。大多数 ORM 都有一个缓存机制来避免执行查询,这也有助于实现这一点。
即使存储过程快了 10%(可能不是),您可能想问问自己它到底有多重要。最终真正重要的是为您的系统编写和维护代码是多么容易。如果您正在编写一个 Web 应用程序,并且您的页面都在 0.25 秒内返回,那么使用存储过程节省的额外时间可以忽略不计。但是,使用像 NHibernate 这样的 ORM 可以有许多额外的优势,仅使用存储过程很难复制。