使用存储过程是否能够带来显著的性能提升?

7

使用存储过程还是以连接字符串和所有其他好东西的旧方式做更好?我们的系统最近运行缓慢,我们的经理希望我们尝试看看是否可以稍微加快一下速度,我们正在考虑将一些旧的数据库调用更改为存储过程。这值得吗?


1
“用连接字符串的老方法”无论是使用动态SQL还是存储过程,都需要使用连接字符串! - fretje
10个回答

17

首先要做的是检查数据库是否设置了所有必要的索引。分析您的代码缓慢的位置,并检查相关的SQL语句和与之相关的索引。看看是否可以重写SQL语句以使其更有效率。检查循环中是否每次迭代都重新编译SQL(准备)语句,而不是在外部仅编译一次。

如果实现非常低效,将SQL语句移动到存储过程中并不能帮助解决问题。但是,数据库会知道如何最优化SQL,它也不需要反复执行此操作。这也可以通过将复杂的SQL语句转换为简单的过程调用来使客户端代码更清晰。


9

我希望我能为这个链接加10分。它恰好描述了我在数据库层面上存储逻辑的想法。 - Brian C. Lane
然而,我必须对作者的一个观点提出异议。虽然这不会影响最终结论,但他的陈述“在SQL中你无法做到的事情,在应用程序代码中同样也做不到”表明了对集合逻辑及其效率的常见误解。 - GalacticCowboy

6
只要您的调用是一致的,数据库就会存储执行计划(至少在MS SQL中是这样)。使用存储过程最重要的原因是方便和确保安全管理。
如果我是您,我首先会查看是否需要添加索引。还可以运行性能分析工具来检查哪些操作需要更改,例如添加更多Where子句或限制结果集。
您应该考虑尽可能使用缓存。

投票支持加粗重要关键词,不错的点子。 :) - Jon Tackabury

5
存储过程并不能提高速度。然而,重新排列逻辑将会有巨大的影响。当您考虑存储过程时设计整洁、专注的事务非常有益。
此外,存储过程倾向于使用绑定变量,而其他编程语言有时会依赖于即时构建SQL语句。一个小的、固定的SQL语句集和绑定变量是快速的。动态SQL语句很慢。
一个“最近运行缓慢”的应用程序不需要编码更改。
  1. 测量。测量。测量。“慢”在性能调优方面没有多少意义。什么是慢的?哪个确切的事务是慢的?哪个表是慢的?聚焦。

  2. 控制所有变化。所有的。有什么变化吗?操作系统补丁?RDBMS更改?应用程序更改?某些事情发生了变化以减慢事情的进展。

  3. 检查规模上的约束。一张表是否因为80%的数据是历史数据,你每年只用于报告而放缓了速度?

除非您可以绝对指出一个特定的代码块作为存储过程证明更快,否则存储过程永远不是性能问题的解决方案。

我们运行缓慢的主要原因是因为我们正处于繁忙的季节,但它比以往任何时候都要慢(即使是在以前的繁忙季节)。因此,我们正在尽力稍微加速一下。谢谢。 - Josh Mein
“比以前慢”是一个开始,但这还是太笼统了。下一步是专注于特定的表格、事务、例程、程序、作业或任务。如果没有重点,你无法证明对存储过程的更改具有积极影响。 - S.Lott
我们认为我们的工作表及其相关表格是最受欢迎的,因为这是一年中调用最多的,所以我们将重点关注它们。 - Josh Mein
比以前慢了 - 请参阅下面关于排队系统性能行为的帖子。 - ConcernedOfTunbridgeWells

4

如果存储过程能避免发送大量数据或避免与服务器进行往返通信,它们就可以真正地提供帮助,因此如果您的应用程序存在这些问题,则它们可能非常有价值。


2
如果您的服务器在繁忙的季节明显变慢,可能是由于饱和而不是数据库中的任何低效因素。基本的排队理论告诉我们,当服务器接近饱和时,它会呈双曲线形地变慢。
基本关系式为1/(1-X),其中X是负载比例。这描述了平均排队长度或等待时间。因此,当负载激增时,正在饱和的服务器将非常迅速地变慢。
负载为25%的服务器将具有1.333K的平均服务时间,其中K是机器执行一次事务的时间(松散地说)。负载为50%的服务器将具有2K的平均服务时间,而负载为90%的服务器将具有10K的平均服务时间。鉴于减速是双曲线性质的,通常不需要大幅度改变总体负载即可产生响应时间的显着降级。
显然,这有些简化,因为服务器将同时处理多个请求(针对这种情况有更复杂的排队模型),但基本原则仍然适用。
因此,如果您的服务器正在经历暂时性负载使其饱和,您将会遇到明显的减速区间。请注意,这些减速只需要在系统的一个瓶颈区域出现就能减缓整个处理过程。如果您只在繁忙季节才遇到这种情况,那么您的服务器可能只是受到某些资源限制而不是特别缓慢或低效。
请注意,这种可能性并不排斥代码中存在低效率的情况。您可能会发现缓解瓶颈的方法是调整一些查询。
为了确定系统是否受到瓶颈影响,请开始收集分析信息。如果您能找到有大量等待的资源,这应该是一个好的起点。
最后一种可能性是您需要升级服务器。如果代码中没有主要的低效率(如果分析不显示任何不成比例的瓶颈,这很可能是情况),您可能只需要更大的硬件。我不知道您的容量是多少,但不要排除您可能已经超出了服务器的承受能力的可能性。

2
完成研究后,您会意识到两种极端观点在谱系的两端。历史上由于一些框架(如hibernate)的可用性,Java社区一直反对存储过程;相反,.NET社区使用的存储过程比较多,这种遗留传统甚至可以追溯到vb5/6时代。将所有信息放在背景下,并避免持有任何一个极端观点。
选择是否使用存储过程时,速度不应是主要因素。您可以使用hibernate和其他框架中的内联SQL来实现存储过程的性能。考虑维护以及其他程序(例如报告、脚本)能否使用与您的应用程序相同的存储过程。如果您的情况需要多个使用相同SQL代码的消费者,则存储过程是一个很好的选择,维护也会更容易。如果不是这种情况,并且您决定使用内联SQL,请考虑在配置文件中将其外部化以便于维护。
最终,重要的是什么能使您特定情况下的利益相关者成功。

0

是的,存储过程是实现良好性能的一大步。主要原因是存储过程可以预编译并缓存其执行计划。

但是,您需要首先分析真正的性能瓶颈所在,以便有条不紊地进行此练习。

正如其中一个回复中建议的那样,尝试使用分析器工具分析问题所在 - 例如,您是否需要创建索引...

干杯


现代大多数关系型数据库系统都会预编译和缓存准备语句的执行计划。 - Jon Skeet

0

就像以上所有帖子所建议的那样,您首先要清理SQL语句,拥有适当的索引。缓存可能会很棘手,除非我了解您想要实现什么,否则我不能发表评论。

但是关于sprocs的一件事,请确保不要让它生成动态SQL语句

因为首先,这将是无意义的,并且可能会受到SQL注入攻击...这在我调查过的项目中曾经发生过。

我建议主要使用sprocs进行更新,然后是选择语句。祝你好运 :)


-1

你永远无法提前预测。你必须去做并且测量差异,因为在十次中有九次,瓶颈不在你想象的地方。

如果你使用存储过程,你就不需要传输数据。数据库通常执行[编辑]复杂[/编辑]存储过程[编辑]带有循环、高级数学等[/编辑]会比较慢。所以这真的取决于你需要做多少工作,你的网络有多慢,数据库执行这个特定代码有多快等等。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接