即席查询与存储过程对比动态SQL

时间:2010-05-29 10:19:32

标签: sql stored-procedures dynamic-sql adhoc-queries

即席查询与存储过程与动态SQL。任何人都可以说利弊吗?

6 个答案:

答案 0 :(得分:30)

存储过程

  • Pro:适用于简短的简单查询(也称为OLTP - 即添加,更新,删除,查看记录)
  • Pro:将数据库逻辑与业务逻辑分开
  • Pro:易于排除故障
  • Pro:易于维护
  • Pro:通过网络传输的位数较少(即只有proc名称和params)
  • Pro:在数据库中编译
  • Pro:更好的安全性(用户不需要直接访问表)
  • Pro:优秀的查询计划缓存(适用于OLTP 查询 - 从计划重用中获益)
  • Con:优秀的查询计划缓存(对OLAP 查询不利 - 来自独特计划的好处)
  • Con:使您与该SQL供应商绑定

动态SQL (即在存储过程中使用exec命令)

  • Pro:适用于简短的简单查询(又称OLTP)
  • Pro:将数据库逻辑与业务逻辑分开
  • Pro:通过网络传输的位数较少(即只有proc名称和params)
  • Pro:允许引用任何表,数据库或列
  • Pro:允许根据参数
  • 添加/删除谓词(在WHERE子句中)
  • Pro:良好的查询计划缓存(对于OLTP和OLAP查询都是中等到良好的)
  • Con:只能编译proc的静态元素
  • Con:使您与该SQL供应商绑定
  • Con:更难以排除故障
  • Con:更容易受到SQL注入攻击

Ad Hoc SQL (即在您的商家代码中创建)

  • Pro:适用于长期,复杂的quieres(又名OLAP - 即报告或分析)
  • Pro:灵活的数据访问
  • Pro:可以使用ORM;可以在代码中编译/测试(即Linq-to-Sql或SqlAlchemy)
  • Pro:查询计划缓存不佳(适用于OLAP 查询 - 受益于独特的计划)
  • Con:查询计划缓存不佳(对OLTP 查询不利 - 从计划重用中获益)
  • Con:通过网络传输更多比特(即整个查询和参数)
  • Con:如果您不使用ORM,则更难维护
  • Con:如果您不使用ORM,则更难以排除故障
  • Con:更容易受到SQL注入攻击

注意:始终参数化您的临时SQL。

对于OLAP ad hoc SQL:仅参数化字符串数据。这满足两个条件。它可以防止SQL注入攻击。它使查询看起来更加独特。是的,您将获得较差的查询计划缓存命中率。但这对于OLAP查询来说是理想的。他们受益于独特的计划生成,因为他们的数据集和最有效的计划在给定参数之间差异很大。

答案 1 :(得分:2)

存储过程PROs:

  • 汇编。这意味着它运行得更快,并且由于绕过优化/编译阶段而对数据库服务器的CPU产生了积极的影响,但是首次执行除外。
  • 允许对复杂的读写查询进行干净的权限控制。
  • 提供可重用的API,允许一个GOOD高效实现,而不是来自各种应用程序的各种平台上的一堆Yahoos重新实现samke查询并冒着实现低效的实现的风险
  • 与任何API一样,提供抽象层。您可以更改底层实现(架构),而无需更改任何调用SP的代码。当所有使用该查询的平台上有100多个应用程序时,这是一个非常大的优势。

存储过程CONs:

  • 与动态SQL相比,难以编写灵活的逻辑
  • 预编译版本可能会导致执行效率降低,因为数据漂移和优化程序选择会发生变化。通过偶尔重新编译很容易改善。

答案 2 :(得分:0)

存储过程

  • Pro:在不需要在表级授予更多基本权利的情况下执行操作。
  • Pro:Discrete and versionable
  • Pro:允许您将架构与数据访问代码隔离开来。
  • Con:编写CRUD程序可能很繁琐
  • Con:需要与基础架构保持一致

临时和动态 - 请参阅Bill Paetzke的回答和评论。

另外,不要忘记SQL的批量插入等模式,这些模式不在您的列表中,但仍应予以考虑。

答案 3 :(得分:0)

RDBMS?这个答案特定于旧的oracle

旧版oracle版本< 11,动态sql不重用现有的SGA sqltext计划,它为解析器需要的每个执行计划创建一个新条目。有很多动态sql调用,sqltext区域的刷新速度足够快,以至于查询重用率会下降,并且性能会随之下降。

答案 4 :(得分:0)

另一个优势是更容易“无停机升级”(对于主要升级,您仍可能会导致停机)。

如果通过存储过程完成所有数据访问,则可以轻松地将存储过程的v1和v2并排放置。

现在你可以从v1和v2并排运行二进制文件/应用程序逻辑,每个都调用它们自己的存储过程版本。

通过1没有实现停机时间,将v1应用程序锁定为只读模式(如果适用),2,部署数据库更改。 3,重新启用对v1 app的正常访问,4,并排部署v2 app,告诉新用户使用新的二进制文件。 6.当没有更多用户使用旧二进制文件时关闭旧二进制文件。

答案 5 :(得分:0)

瘟疫可以避免恕我直言的存储过程。这里有十个很好的理由,为什么你永远不应该使用它们(适用于所有数据库):

  1. PL / SQL语言适用于处理表,行和列中的数据。表达业务逻辑是一个糟糕的选择。你可以用任何语言编写任何代码 - 这并不意味着你应该
  2. 大多数数据库缺少一个像样的IDE来帮助语法和链接到其他现有程序(例如Eclipse对java的帮助)
  3. 人力资源很难找到编写和维护存储过程 - 它们更加罕见,因此更加昂贵
  4. 存储过程在数据库之间不可移植,因为a)PL / SQL没有行业标准b)即使有标准,您通常最终会在存储过程中使用特定于数据库的功能/ sql。如果您必须移动dbs,那么您正在寻找完整的业务逻辑重写
  5. 大多数数据库不提供对存储过程调试的任何支持 - 您只需将行插入日志表或类似内容以实现日志记录以进行调试 - 非常难看
  6. 要测试存储过程,您需要一个真正的数据库实例。这使得单元测试存储过程很困难(你必须将它们部署到dev db来运行它们)
  7. 要部署存储过程,您必须更新数据库(删除然后创建存储过程)。如果发现错误,您不能像使用应用程序代码那样简单地回滚到以前的二进制版本。相反,您必须找到旧代码,删除新存储的proc并(重新)创建旧代码。这是更改更改回滚
  8. 您正在增加数据库服务器的处理需求,而不是将业务逻辑分发给其他(app)服务器。由于数据库通常是单例,这非常糟糕,因为增加容量的唯一方法是购买更好的硬件(而不是购买更多硬件或使用云)。
  9. 它们 比使用预准备语句的编写良好的查询快得多,因为在数据库服务器上增加处理需求和使用它们的效率之间存在折衷。除了速度并不是一切(只要它是可以接受的):可维护性,可调试性,PL / SQL的适用性等同样重要,如果不是更重要的话
  10. 存储过程语言有限(如果有)库可供使用,因此您最终会编写大量低价值代码。这与应用程序语言不同,应用程序语言具有大量可用于业务逻辑所需的库的库
  11. 我只有一个地方可以批准他们的使用:对于非常具体的数据库功能 - 可能是一个关键检查或数据类型转换或类似的东西,可能在触发器内,这是非常重要的,它证明了它的存在并且可能赢了一旦写完就不会改变。

    通常,您应该从存储过程中进行尖叫!