MySQL存储过程使用它们或不使用它们

时间:2011-06-16 08:20:47

标签: mysql database performance database-design stored-procedures

我们正处于一个新项目的开始阶段,我们真的想知道是否应该在MySQL中使用存储过程。

我们仅使用存储过程来插入和更新业务模型实体。有几个表代表模型实体,我们将在那些存储过程insert / update中抽象它。

另一方面,我们可以从Model层调用insert和update,但不能在MySQL中调用,而是在PHP中调用。

根据您的经验,哪个是最佳选择?两种方法的优点和缺点。哪个是高性能最快的?

PS:这是一个大多数读取和高性能的Web项目是最重要的必备条件。

12 个答案:

答案 0 :(得分:60)

与实际的编程语言代码不同,它们是:

  • 不可移植(每个数据库都有自己的PL / SQL版本。有时不同版本的相同的数据库是不兼容的 - 我已经看过了!)
  • 不易测试 - 你需要一个真正的(dev)数据库实例来测试它们,因此单元测试它们的代码作为构建的一部分几乎是不可能的
  • 不易更新/可释放 - 您必须删除/创建它们,即修改生产数据库以释放它们
  • 没有库支持(为什么在其他人拥有时编写代码)
  • 不易与其他技术整合(尝试从中调用Web服务)
  • 他们使用与Fortran一样原始的语言,因此完成有用的编码是不够优雅和费力的,因此很难表达业务逻辑,即使通常这是他们的主要目的
  • 不提供调试/跟踪/消息记录等(有些dbs可能支持这个 - 我还没有看到它)
  • 缺少一个体面的IDE来帮助语法和链接到其他现有的程序(例如Eclipse对java的帮助)
  • 熟悉编码的人比应用程序编码人员更为罕见且更昂贵
  • 他们的“高性能”是一个神话,因为他们在数据库服务器上执行他们通常增加数据库服务器负载,所以使用它们通常会减少你的最大事务可以通过
  • 无法有效地共享常量(通常通过创建表并从您的过程中查询它来解决 - 非常低效)

如果您有一个特定于数据库的操作(例如,用于维护数据库完整性的事务内操作),或者保持您的过程非常原子和简单,那么您可能会考虑它们。

建议在预先指定“高性能”时注意。它往往导致糟糕的选择而牺牲良好的设计,它会比你想象的更快地咬你。

使用存储过程自担风险(来自曾经去过那里且永远不想回去的人)。我的建议是像瘟疫一样避免它们。

答案 1 :(得分:27)

与编程代码不同,它们是:

  • 几乎渲染SQL注入攻击 不可能的(除非你是 构建和执行动态 从你的程序中的SQL)
  • 要求发送的数据要少得多 IPC作为标注的一部分
  • 使数据库更好 缓存计划和结果集(这是 诚然不太有效 MySQL由于其内部缓存 结构)
  • 易于单独测试 (即不作为JUnit测试的一部分)
  • 在他们的意义上是便携式的 允许您使用特定于db的 功能,抽象背后 程序名称(在代码中你被卡住了 使用通用SQL类型的东西)
  • 几乎从不比SQL慢 从代码中调用
但是,正如波西米亚人所说的那样,也有很多缺点(这只是提供另一种观点)。在决定什么对你最有利之前,你可能需要进行基准测试。

答案 2 :(得分:13)

至于表演,他们在未来的MySQL版本中具有真正具有高性能的潜力(在SQL Server或Oracle下,它们是真正的享受!)。然而,对于所有其他......他们完全爆发了竞争。我将总结一下:

  • 安全性:您可以只为您的应用提供EXECUTE权限,一切都很好。您的SP将插入更新选择...,没有任何可能的泄漏。它意味着对您的模型的全局控制,以及强制数据安全性。

  • 安全性2:我知道这种情况很少见,但有时PHP代码会从服务器泄漏出来(即公开可见)。如果它包含您的查询,可能的攻击者会知道您的模型。这很奇怪,但无论如何我想发信号

  • 任务组:是的,创建高效的SQL SP需要一些特定的资源,有时候会更昂贵。但是如果你认为你不需要这些资源只是因为你在你的客户端集成了你的查询......你就会遇到严重的问题。我提到了Web开发的类比:将视图与其他视图分开是很好的,因为您的设计人员可以使用他们自己的技术,而程序员可以专注于编写业务层。

  • 封装业务层:使用存储过程完全隔离它所属的业务:该死的数据库。

  • 快速测试:shell下有一个命令行,您的代码已经过测试。

  • 独立于客户端技术:如果明天你想从php切换到其他东西,没问题。好吧,只是将这些SQL存储在一个单独的文件中也可以解决问题,这是正确的。另外,关于如果你决定切换sql引擎的评论中的好点,你还有很多工作要做。无论如何,你必须有充分的理由这样做,因为对于大型项目和大公司来说,这很少发生(主要是由于成本和人力资源管理)

  • 实施敏捷3 +层开发:如果您的数据库与客户端代码不在同一台服务器上,则可能有不同的服务器,但只有一台服务器用于数据库。在这种情况下,当您需要更改SQL相关代码时,您不必升级任何php服务器。

好的,我认为这是我在这个问题上最重要的事情。我在两种灵魂(SP vs client)中都有所发展,我真的非常喜欢SP风格。我只是希望Mysql有一个真正的IDE为他们,因为现在它是一种痛苦的屁股有限。

答案 3 :(得分:7)

存储过程很好用,因为它们可以使您的查询井井有条,并允许您一次执行批处理。存储过程通常可以快速执行,因为它们是预编译的,与每次运行时编译的查询不同。这对数据库位于远程服务器上的情况有很大影响;如果查询在PHP脚本中,则应用程序和数据库服务器之间存在多个通信 - 查询将被发送,执行并返回结果。但是,如果使用存储过程,则只需要发送一个小的CALL语句而不是大而复杂的查询。

可能需要一段时间才能适应编程存储过程,因为它们有自己的语言和语法。但是,一旦你习惯了它,你会发现你的代码非常干净。

就性能而言,如果您使用存储过程,则可能无法获得任何重大收益。

答案 4 :(得分:5)

我会让我知道我的意见,尽管我的强硬可能与这个问题没有直接关系。:

与许多问题一样,关于使用存储过程或应用程序层驱动的解决方案的回复依赖于将推动整体工作的问题:

  • 你想得到什么。

您是尝试进行批量操作还是在线操作?他们是完全交易的吗?这些行动有多复发?等待数据库的工作量有多重?

  • 你有什么才能得到它。

您拥有什么样的数据库技术?什么样的基础设施?您的团队是否接受过数据库技术的全面培训?您的团队是否能够更好地构建数据库诊断解决方案?

  • 获得它的时间。

没有秘密。

  • 架构。

您的解决方案是否需要分发到多个位置?是您使用远程通信所需的解决方案吗?您的解决方案是在多个数据库服务器上工作,还是可能使用基于群集的架构?

  • Mainteinance。

需要更改多少申请?你有经过专门培训的个人维护解决方案吗?

  • 变更管理。

您是否看到您的数据库技术会在短时间,中期,长时间内发生变化?您是否会看到需要经常迁移解决方案?

  • 费用

使用一种或另一种策略实施该解决方案需要多少费用?

这些要点的总体结果将成为答案。因此,在决定是否使用任何策略时,您必须关注每一点。有些情况下,存储过程的使用优于应用程序层管理的查询,而其他情况下,执行查询和使用基于应用程序层的解决方案时最好。

在以下情况下使用存储过程往往更加充分:

  1. 您的数据库技术不会在短时间内发生变化。
  2. 您的数据库技术可以处理并行操作,表分区或其他任何策略,以将工作负载划分为多个处理器,内存和资源(群集,网格)。
  3. 您的数据库技术与存储的过程定义语言完全集成,即支持在数据库引擎内。
  4. 您有一个开发团队,他们并不担心使用过程语言(第三代语言)来获得结果。
  5. 您希望实现的操作是在数据库内置或支持的(导出到XML数据,与触发器,预定操作等相关地管理数据完整性和一致性)。
  6. 可移植性不是一个重要问题,您不会在短时间内对您的组织进行技术变革,即使是不可取的。通常,可移植性被应用程序驱动和面向分层的开发人员视为里程碑。从我的角度来看,当您的应用程序不需要部署到多个平台时,可移植性不是问题,当没有理由进行技术更改时,或者迁移所有组织的工作量减少数据高于进行更改的好处。通过使用应用程序层驱动的方法(可移植性)可以获得什么,你可以从数据库中获得性能和价值(为什么要花费数千美元来获得一辆你驾驶不超过60 mil的法拉利) /小时?)。
  7. 表现是一个问题。第一:在某些情况下,使用单个存储过程调用可以获得比来自其他应用程序的多个数据请求更好的结果。此外,您需要执行的某些特性可能内置在您的数据库中,并且在工作负载方面的使用成本更低。当您使用应用程序层驱动的解决方案时,您必须考虑与进行数据库连接,调用数据库,网络流量,数据包装相关的成本(即,使用Java或.NET时,存在隐式成本时使用JDBC / ADO.NET调用时必须将数据包装到表示数据库数据的对象中,因此当数据来自外部时,实例化在处理,内存和网络方面会产生相关成本。
  8. 在以下情况下使用应用层驱动的解决方案往往更加充分:

    1. 便携性是一个重要问题。
    2. 应用程序将部署到只有一个或几个数据库存储库的多个位置。
    3. 您的应用程序将使用繁重的面向业务的规则,这些规则需要与底层数据库技术无关。
    4. 您需要根据市场趋势和预算来改变技术提供商。
    5. 您的数据库未与调用数据库的存储过程语言完全集成。
    6. 您的数据库功能有限,您的要求超出了数据库技术的要求。
    7. 您的应用程序可以支持外部调用固有的惩罚,更基于事务,具有特定于业务的规则,并且必须将数据库模型抽象为用户的业务模型。
    8. 并行化数据库操作并不重要,而且,您的数据库没有并行化功能。
    9. 您的开发团队没有经过良好的数据库技术培训,使用基于应用程序驱动的技术可以提高工作效率。
    10. 希望这可能有助于任何人问自己什么是更好用。

答案 5 :(得分:3)

我建议你不要使用存储过程:

  • 他们在MySQL中的语言非常糟糕
  • 无法将数组,列表或其他类型的数据结构发送到存储过程
  • 存储过程不能永远更改其界面; MySQL不允许使用命名参数或可选参数
  • 这使得部署应用程序的新版本变得更加复杂 - 比如你有10个应用程序服务器和2个数据库,你会先更新吗?
  • 您的开发人员都需要学习和理解存储过程语言 - 这是非常废话(正如我之前提到的)

相反,我建议创建一个图层/库并将所有查询放在那里

你可以

  • 更新此库并使用您的应用
  • 将其发布到您的应用服务器上
  • 拥有丰富的数据类型,例如传递的数组,结构等
  • 对此库进行单元测试,而不是存储过程。

关于表现:

  • 使用存储过程会降低应用程序开发人员的性能,这是您关心的主要内容。
  • 在复杂的存储过程中识别性能问题非常困难(对于简单查询来说容易得多)
  • 您可以通过网络在一个块中提交查询批处理(如果启用了CLIENT_MULTI_STATEMENTS标记),这意味着没有存储过程就不会再有延迟。
  • 应用程序端代码通常比数据库端代码更好地扩展

答案 6 :(得分:2)

如果您的数据库很复杂而不是具有响应的论坛类型,但真正的仓储SP肯定会受益。你可以在那里解决所有的业务逻辑,而不是一个开发人员会关心它,他们只是打电话给你的SP。我一直这样做加入超过15个表并不好玩,你无法向新开发者解释这个。

开发人员也无法访问数据库,太棒了!把它留给数据库设计者和维护者。如果您还决定要更改表结构,则可以将其隐藏在界面后面。 n-tier,记得??

高性能和关系数据库不是一起出现的,即使MySQL InnoDB很慢,MyISAM也应该被抛到窗外。如果您需要使用Web应用程序进行性能,则需要适当的缓存,内存缓存或其他。

在你的情况下,因为你提到'Web'我不会使用存储过程,如果它是数据仓库我肯定会考虑它(我们使用SP作为我们的仓库)。

提示: 既然你提到了Web项目,那么有关nosql的解决方案吗?另外,你需要一个快速的DB,为什么不使用PostgreSQL呢? (试图在这里提倡...)

答案 7 :(得分:2)

我以前使用MySql并且我对sql的理解充其量很差,我花了相当多的时间使用Sql Server,我清楚地分离了数据层和应用层,我目前正在寻找一个服务器0.5太字节。

有时我没有使用ORM感到沮丧,因为存储过程的开发速度非常快,速度要慢得多。我认为通过使用ORM可以加快我们的大部分工作。

当您的应用程序达到临界质量时,ORM性能将受到影响,编写良好的存储过程将更快地为您提供结果。

作为性能的一个例子,我在应用程序中收集10种不同类型的数据,然后将其转换为XML,我在存储过程中处理,我只有一次调用数据库而不是10次。

Sql非常擅长处理数据集,让我感到沮丧的一件事是当我看到有人从原始形式的sql获取数据并使用应用程序代码循环结果和格式并将它们分组时,这真的是不好的做法。

我的建议是学习和理解sql,你的应用程序才会真正受益。

答案 8 :(得分:1)

我建议您远离数据库特定的存储过程。

我经历了很多项目,他们突然想要切换数据库平台,而SP内部的代码通常不是很便携=额外的工作和可能的错误。

存储过程开发还要求开发人员直接访问SQL引擎,因为项目中的任何人都可以通过代码访问来更改正常连接。

关于你的模型/图层/层次的想法:是的,坚持下去。

  • 网站调用业务层(BL)
  • BL呼叫数据层(DL)
  • DL调用任何存储(SQL,XML,Web服务,套接字,文本文件等)

这样您就可以维持层之间的逻辑级别。如果只是DL调用看起来非常慢,你可以开始使用存储过程,但是如果你突然需要将数据库转移到一个全新的平台,那么可以在某处维护原始的非SP代码。通过业务中的所有云托管,您永远不会知道什么是下一个数据库平台......

出于同样的原因,我密切关注亚马逊AWS。

答案 9 :(得分:1)

这里有很多信息让人迷惑,软件开发是一种进化。我们20年前所做的事情现在不是最好的做法。回到使用经典客户端服务器的那一天,除了SP之外,你不会想到任何东西。

对于课程来说,这绝对是马匹,如果你是一个大型组织,你将使用多层,可能是SP,但你会关心它们,因为一个专门的团队将把它们整理出来。

相反,我发现自己试图快速敲定一个Web应用程序解决方案,这可以满足业务需求,离开开发人员(远程对我)来敲除页面和SQL查询是非常快的定义数据库结构。

然而,复杂性正在增长,并且没有简单的方法来提供API,我盯着使用SP来包含业务逻辑。我认为它运作良好且合情合理,我控制它是因为我可以构建逻辑并为我的离岸开发人员提供一个简单的结果集来构建前端。

如果我发现我的软件取得了非凡的成功,那么就会出现更多关注点的分离,并且会出现不同的n teir实现,但是现在SP是完美的。

您应该知道所有可用的工具集,并且与之匹配是明智的。除非你建立一个企业系统,然后快速而简单是最好的。

答案 10 :(得分:0)

我认为关于数据库存储的查询有很多错误信息。

如果您要对数据进行许多静态查询,我建议您使用MySQL存储过程。特别是如果您要将事物从一个表移动到另一个表(即出于某种原因从活动表移动到历史表)。当然,这样做有个缺点,那就是必须单独记录更改的日志(理论上,您可以创建一个表,该表仅保存DBA更新的存储过程的更改)。如果您有许多不同的应用程序与数据库连接,特别是如果您说有一个用C#编写的桌面程序和一个用PHP编写的Web程序,那么将某些过程存储在数据库中可能是更有利的,因为它们是与平台无关的。

该网站上有一些有趣的信息,您可能会觉得有用。

https://www.sitepoint.com/stored-procedures-mysql-php/

与往常一样,首先构建沙箱,然后进行测试。

答案 11 :(得分:-2)

尝试从框架更新实时系统上的100,000,000条记录,然后让我知道它的运行方式。对于小型应用程序来说,SP不是必须的,但对于大型的严肃系统来说,它们是不二之选。