一般而言,存储过程是否比现代RDBMS上的内联语句更有效?

时间:2008-09-12 20:32:26

标签: sql database stored-procedures

传统观点认为存储过程总是更快。因此,由于它们总是更快,所以使用它们所有时间

我很确定这是基于历史背景,曾经如此。现在,我并不是说不需要存储过程,但是我想知道在现代数据库中需要存储过程,例如MySQL,SQL Server,Oracle或< Insert_your_DB_here > ;。通过存储过程进行ALL访问是否过度?

20 个答案:

答案 0 :(得分:249)

答案 1 :(得分:21)

使用存储过程的原因:

  • 减少网络流量 - 您必须通过网络发送SQL语句。使用sprocs,您可以批量执行SQL,这也更有效。
  • 缓存查询计划 - 第一次执行sproc时,SQL Server会创建一个执行计划,该计划会被缓存以供重用。对于经常运行的小型查询,这尤其有效。
  • 能够使用输出参数 - 如果发送返回一行的内联SQL,则只能返回记录集。使用sprocs,你可以将它们作为输出参数返回,这要快得多。
  • 权限 - 当您发送内联SQL时,您必须向用户授予对表的权限,这授予的权限远远超过仅授予执行sproc的权限
  • 逻辑分离 - 删除SQL生成代码并将其隔离在数据库中。
  • 无需重新编译即可进行编辑 - 这可能会引起争议。您可以在sproc中编辑SQL,而无需重新编译应用程序。
  • 查找表的使用位置 - 使用sprocs,如果要查找引用特定表的所有SQL语句,可以导出sproc代码并进行搜索。这比尝试在代码中找到它容易得多。
  • 优化 - 在使用sprocs时,DBA更容易优化SQL并调整数据库。找到缺失的索引等更容易。
  • SQL注入攻击 - 正确编写的内联SQL可以抵御攻击,但是对于这种保护,sprocs更好。

答案 2 :(得分:17)

在许多情况下,存储过程实际上较慢,因为它们更加通用。虽然存储过程可以高度调整,但根据我的经验,它们有足够的开发和制度摩擦,一旦它们工作就会留在原地,因此存储过程往往会返回很多列“以防万一” - 因为你没有想要在每次更改应用程序时部署新的存储过程。另一方面,OR / M仅请求应用程序使用的列,这会减少网络流量,不必要的连接等。

答案 3 :(得分:9)

这是一场肆虐的辩论(例如,here)。

编写错误的存储过程和在应用程序中编写错误的数据访问逻辑一样容易。

我更喜欢Stored Procs,但那是因为我通常在企业环境中使用非常大而复杂的应用程序,在那里有专门的DBA负责保持数据库服务器的运行。

在其他情况下,我很高兴LINQ等数据访问技术可以处理优化。

然而,纯粹的表现不是唯一的考虑因素。安全性和配置管理等方面通常至少同样重要。

编辑:虽然Frans Bouma的文章确实很冗长,但它却忽略了一英里的安全问题。它5岁的事实也没有帮助它的相关性。

答案 4 :(得分:9)

对于大多数现代数据库,存储过程与参数化或准备好的查询之间没有明显的速度差异,因为数据库还将缓存这些查询的执行计划。

请注意,参数化查询与ad hoc sql不同。

今天仍然支持存储过程的主要原因更多地与安全性有关。如果您使用独占存储过程,则可以为应用程序的用户禁用INSERT,SELECT,UPDATE,DELETE,ALTER,DROP和CREATE等权限,只保留EXECUTE。

这为二阶 sql注入提供了一些额外的保护。参数化查询仅防止第一顺序注入。

答案 5 :(得分:4)

2007年,我参与了一个项目,我们通过ORM使用了MS SQL Server。我们有两个不断增长的大表,在SQL Server上占用了7-8秒的加载时间。在创建了2个大型存储的SQL过程并从查询规划器中优化它们之后,每个数据库加载时间都缩短到不到20毫秒,因此使用存储的SQL过程仍然存在效率原因。

话虽如此,我们发现存储过程最重要的好处是增加了维护 - 安全性,数据完整性,并将业务逻辑与中间件逻辑分离,使所有中间件逻辑从重用中受益。 2个程序。

我们的ORM供应商通常声称,解雇许多小型SQL查询比获取大型连接数据集更有效。我们的经历(令我们惊讶)展示了其他一些东西。

这当然可能因机器,网络,操作系统,SQL服务器,应用程序框架,ORM框架和语言实现而异,因此衡量任何好处,您可以从做其他事情中获得。

在我们进行基准测试之前,我们发现问题出现在ORM和数据库之间,并承担了所有的负担。

答案 6 :(得分:4)

显然,实际表现应该在个别情况下进行衡量,而不是假设。但即使在存储过程中性能受到妨碍的情况下,也有充分的理由使用它们:

  1. 应用程序开发人员并不总是最好的SQL编码器。存储过程会从应用程序中隐藏SQL。

  2. 存储过程自动使用绑定变量。应用程序开发人员经常避免使用绑定变量,因为它们看起来像不需要的代码,并且在小型测试系稍后,无法使用绑定变量可能会降低RDBMS性能。

  3. 存储过程会创建一个间接层,以后可能会有用。可以在不触及应用程序代码的情况下更改数据库端的实现细节(包括表结构)。

  4. 创建存储过程的练习对于记录系统的所有数据库交互非常有用。当事情发生变化时,更容易更新文档。

  5. 那就是说,我通常会在我的应用程序中粘贴原始SQL,以便我自己控制它。这取决于您的开发团队和理念。

答案 7 :(得分:4)

没有人提到的一个主题是存储过程的好处是安全性。如果通过存储过程专门构建具有数据访问权限的应用程序,则可以锁定数据库,以便通过这些存储过程进行唯一访问。因此,即使有人获得了数据库ID和密码,他们也会受限于他们可以看到或对该数据库做的事情。

答案 8 :(得分:3)

当使用SP时,我更喜欢使用SP。无论如何,在SQL Server中,SP对参数化查询没有任何性能优势。

然而,在我目前的工作中,我的老板提到我们被迫使用SP,因为我们的客户需要它们。他们觉得自己更安全。我在这里的时间不长,看看我们是否正在实施基于角色的安全性,但我有一种感觉。

因此,在这种情况下,客户的感受胜过所有其他论点。

答案 9 :(得分:2)

对我来说,存储过程的一个优点是与主机语言无关:您可以从C,Python,PHP或任何应用程序切换到另一种编程语言而无需重写代码。此外,诸如批量操作之类的某些功能可以提高实际性能,并且在主机语言中不容易获得(根本没有?)。

答案 10 :(得分:1)

使用存储过程进行CRUD操作可能有点过分,但这取决于所使用的工具和您自己的首选项(或要求)。我更喜欢内联SQL,但我确保使用参数化查询来防止SQL注入攻击。我保留了这张xkcd comic的打印件,以提醒您如果不小心会出现什么问题。

当您使用多组数据返回单组数据时,存储过程可以带来真正的性能优势。处理存储过程中的数据集通常比通过线路发送数据在客户端处理更有效。

答案 11 :(得分:1)

认识到这个问题有点偏离主题,但如果你使用了大量的存储过程,请确保有一致的方法将它们置于某种源代码控制之下(例如,subversion或git)和能够将更新从开发系统迁移到测试系统到生产系统。

如果这是手工完成的,无法轻易审核哪些代码在哪里,这很快就会成为一场噩梦。

答案 12 :(得分:1)

我能说的就是SQL服务器。在该平台中,存储过程很可爱,因为服务器存储执行计划,这在大多数情况下可以提高性能。我说“在大多数情况下”,因为如果SP具有广泛变化的执行路径,您可能会获得次优的性能。然而,即使在这些情况下,SP的一些开明的重构也可以加快速度。

答案 13 :(得分:1)

阅读Frans Bouma的excellent post(如果有点偏颇)。

答案 14 :(得分:0)

是的,他们大部分时间都比较快。 SQL组合也是一个巨大的性能调优领域。如果我正在做一个后台办公类型的应用程序,我可能会跳过它们,但我面临的任何生产都会使用它们,因为其他人说的所有原因......即安全性。

答案 15 :(得分:0)

我不知道他们更快。我喜欢使用ORM进行数据访问(不重新发明轮子),但我意识到这并不总是一个可行的选择。

Frans Bouma有一篇关于这个主题的好文章:http://weblogs.asp.net/fbouma/archive/2003/11/18/38178.aspx

答案 16 :(得分:0)

... IMHO

将“C_UD”操作限制到存储过程可以将数据完整性逻辑保存在一个位置。这也可以通过将“C_UD”操作限制为单个中间件层来完成。

可以向应用程序提供读取操作,以便它们只能连接所需的表/列。

答案 17 :(得分:0)

也可以使用存储过程代替参数化查询(或即席查询)以获得其他一些优势:

  • 如果您需要更正某些内容(排序顺序等),则无需重新编译应用
  • 您可以拒绝访问该用户帐户的所有表,仅授予对存储过程的访问权限,并通过存储过程路由所有访问。这样,您可以对所有输入进行自定义验证,比表约束更灵活。

答案 18 :(得分:0)

存储过程很适合经常运行SQL代码的情况,因为数据库将其标记为存储在内存中。如果您在存储过程之外重复运行相同的代码,您将会从数据库中反复重复使用相同的代码而产生性能损失。

我通常经常将代码称为存储过程或SqlCommand(.NET)对象,并根据需要执行多次。

答案 19 :(得分:-2)

减少网络流量 - SP通常比动态SQL差。因为人们没有为每个选择创建一个新的SP,如果你只需要一个列,你会被告知使用具有所需列的SP而忽略其余的列。获得额外的列以及您刚刚离开的网络使用情况。此外,当使用SP时,您往往会进行大量客户端过滤。

缓存 - MS-SQL没有区别对待它们,因为MS-SQL 2000可能是7但我不记得了。

权限 - 不是问题,因为我所做的几乎所有事情都是web或者有一些中间应用程序层来完成所有数据库访问。我使用的唯一具有直接客户端访问数据库的软件是第三方产品,专为用户提供直接访问权限,并以提供用户权限为基础。是的MS-SQL权限安全模型SUCKS !!! (还没有花时间在2008年)作为最后一部分,我想看看有多少人仍在进行直接客户端/服务器编程与Web和中间应用程序服务器编程的调查;如果他们正在做大型项目,为什么没有ORM。

分离 - 人们会质疑为什么要将业务逻辑放在中间层之外。此外,如果您正在寻找单独的数据处理代码,则可以在不将其放入数据库的情况下执行此操作。

编辑能力 - 你有什么不需要担心的测试和版本控制?也只是客户端/服务器的问题,在网络世界中没有问题。

查找表格 - 只有在您可以识别使用它的SP时,才会使用版本控制系统,代理搜索或Visual Studio的工具来查找。

优化 - 您的DBA应该使用数据库的工具来查找需要优化的查询。数据库可以告诉DBA哪些语句正在讨论最多的时间和资源,他们可以从那里修复。对于复杂的SQL语句,如果简单的选择不担心,程序员应该被告知与DBA交谈。

SQL注入攻击 - SP没有提供更好的保护。他们唯一得到点头的是,他们中的大多数教授使用参数与动态SQL,大多数示例忽略参数。