完全用 PL/SQL 编写大型批处理程序是否很愚蠢?
Posted
技术标签:
【中文标题】完全用 PL/SQL 编写大型批处理程序是否很愚蠢?【英文标题】:Is it stupid to write a large batch processing program entirely in PL/SQL?完全用 PL/SQL 编写大型批处理程序是不是很愚蠢? 【发布时间】:2008-09-17 00:21:09 【问题描述】:我正在着手开发一个程序,该程序可能最自然地被描述为对数据库表的一批计算,并将每月执行一次。所有输入都在 Oracle 数据库表中,所有输出都将在 Oracle 数据库表中。该程序应在未来多年内保持可维护性。
将其实现为一系列存储过程似乎很简单,每个存储过程都执行合理的转换,例如根据某些业务规则在部门之间分配成本。然后我可以编写单元测试来检查每个转换的输出是否符合我的预期。
在 PL/SQL 中完成这一切是不是一个坏主意?您是否愿意使用典型的面向对象编程语言(例如 C#)进行大量的批量计算?使用 PL/SQL 等以数据库为中心的编程语言不是更有表现力吗?
【问题讨论】:
【参考方案1】:您描述了以下要求
a) 必须能够实现批处理 b) 结果必须是可维护的
我的回应:
-
PL/SQL 旨在实现您所描述的。同样重要的是要注意,PL/SQL 中的效率在其他工具中是不可用的。存储过程语言将处理放在数据旁边——这就是批处理应该放在的位置。
用任何语言编写维护性差的代码都很容易。
如上所述,您的实施将取决于可用的技能、适当的设计和对优质流程的遵守。
为了提高效率,您的实施必须分批处理数据(分批选择和分批插入/更新)。 OO 方法的危险在于它很容易被引导到逐行处理数据的设计。这种类型的方法包含不必要的开销,并且效率明显低于按行处理数据的设计。
这两种方法都可以成功使用。
马修·巴特勒
【讨论】:
关于 #2 - 原则上同意,但是有些语言使编写草率、讨厌、不可维护的代码变得容易得多……pl-sql 就是其中之一……尽管该奖项可能授予javascript。 @user13276:你能举一些具体的例子来说明 PL/SQL 如何让编写草率的代码变得更容易吗?为什么“更好”的语言更难写出草率的代码?【参考方案2】:其他评论者需要注意的一点 - 问题是关于 PL/SQL,而不是关于 SQL。一些答案显然是关于 SQL,而不是 PL/SQL。 PL/SQL 是一种功能齐全的数据库语言,而且它也很成熟。有一些不足,但是对于发帖人想做的事情类型来说,还是很不错的。
【讨论】:
【参考方案3】:不,这不一定是个坏主意。如果该解决方案对您来说似乎很简单,并且允许您测试和验证每个流程,那么它听起来可能是一个好主意。 OO 平台可能(尽管它们不一定是)不适合大型数据集,因为对象创建和开销会降低性能。
Oracle 设计 PL/SQL 时考虑到了您的类似问题,如果企业对数据库和 PL/SQL 有足够的了解,这似乎是一个合理的解决方案。请记住大批量集,因为从 PL/SQL 到实际 SQL 引擎的每次调用都是上下文切换,因此应尽可能将单个记录进程批处理在一起以提高性能。
【讨论】:
【参考方案4】:只要确保你以某种方式记录它工作时发生的事情。否则你会有一个黑匣子,如果它卡在某个地方几个小时,你会想知道是停止它还是让它“多工作一点”。
【讨论】:
Oracle 为此提供了一个“longops”API。我认为它在 dbms_utility 中。 用于更新进度的Oracle api称为DBMS_application_info。进度发布到视图 v$session_longops。没有理由不使用其他方法。 我相信你想要的是 dbms_application_info.set_module 和 .set_action。数据库使用 longops 来指示诸如查询计划中的特定步骤需要读取多少块【参考方案5】:PL/SQL 是一门成熟的语言,可以很好地与 SQL 集成。随着 Oracle 的每个版本,它变得越来越强大。 同样从 Oracle 11 开始,PL/SQL 默认编译为机器码。
【讨论】:
【参考方案6】:通常我会说尽可能少地使用 PL/SQL - 它通常不太易于维护 - 在我最近的一份工作中,我真的看到了使用它会变得多么混乱和困难。
但是,由于它是批处理 - 并且由于输入和输出都是 DB - 将逻辑放入 PL/SQL 中是很有意义的 - 以最大限度地减少“移动部件”。但是,如果它是业务逻辑 - 或系统其他部分使用的组件 - 我会说不要这样做..
【讨论】:
“它的可维护性通常要低得多——在我最近的一份工作中,我真的看到了多么混乱”——我相信一个糟糕的程序员可以在任何语言中弄得一团糟。 PL/SQL 的具体问题是什么?【参考方案7】:我为一个项目用 PL/SQL 和 ProC 编写了大量的批处理和报告生成程序。他们通常更喜欢我用 PL/SQL 编写,因为他们自己的开发人员会在未来维护他们发现比 ProC 代码更容易理解。
它最终只是用 Pro*C 编写的真正时髦的处理或报告。
没有必要像其他人提到的那样将这些编写为存储过程,它们可以只是根据需要运行的脚本文件,有点像 shell 脚本。使测试和生产系统之间的源代码修订控制和迁移变得更加容易。
【讨论】:
“[脚本文件] 使测试和生产系统之间的源代码修订控制和迁移变得更加容易。” -- 很多人声称存储过程的版本控制有些困难。看在上帝的份上,只需将存储过程代码放在一个文本文件中并签入...与任何其他编程语言没有什么不同。【参考方案8】:只要您需要执行的计算可以在 PL/SQL 中充分且可读地捕获,那么仅使用 PL/SQL 将是最有意义的。
真正的问题是可维护性——编写不可维护的 SQL 非常容易,因为一旦您跳出简单的 SQL DML,每个 RDBMS 都有不同的语法和不同的函数集,而且没有真正的格式化标准。评论等。
【讨论】:
"编写不可维护的 SQL 非常容易,因为每个 RDBMS 都有不同的语法和不同的函数集" -- 但是如果您使用的是 PL/SQL,那么您已经提交给特定的数据库,并且您应该尽可能使用任何特定于 Oracle 的功能,如果它能让您的生活更轻松的话。【参考方案9】:我使用 C# 和 SQL 创建了批处理程序。
C# 的优点:
您拥有完整的 .NET 库和 OO 的所有功能 语言。C# 的缺点:
批处理程序和数据库分开 - 这意味着,您必须将批处理程序与数据库分开管理。 您需要转义所有该死的 sql 代码SQL 的优点:
与 DBMS 完美集成。如果这项工作只操作数据库,那么将它包含在数据库中是有意义的。您最终会在一个包中获得一个数据库及其所有组件。 无需转义sql代码 保持真实 - 您是在自己的问题域中编程SQL 的缺点:
它的 SQL 和我个人对它的了解不如 C#。一般来说,由于上述优点,我会坚持使用 SQL。
【讨论】:
【参考方案10】:这是一个加载的问题:) 您应该了解一些数据库编程架构设计,以及它们的成本/收益。 2 层通常意味着您有一个连接到数据库的客户端,发出直接 SQL 调用。 3 层通常意味着您有一个“应用程序服务器”,它向数据库发出直接 SQL 调用,但客户端正在与应用程序服务器通信。通常,这提供了“横向扩展”。 最后,您有 2 1/2 层应用程序,它们采用类似 2 层的格式,只有工作在存储过程中被划分。
您的流程听起来像是“后台”之类的东西,客户/流程只需要每月汇总和缓存一次的结果。 也就是说,没有代理连接,并且经常连接,并说“做这些计算”。相反,你暗示了一个偶尔发生的过程,你可以摆脱非实时。
因此,考虑到这些要求,我会说一般来说,更接近数据会更快,并让 SQL Server 完成所有计算。 我想你会发现接近数据对你很有帮助。
但是,在执行这些计算时,您可能会发现某些计算不适用于 SQL Server。以计算债券或任何固定收益工具的应计利息为例。在 SQL 中不是很漂亮,更适合更丰富的编程语言。但是,如果您只有简单的平均值和其他相对健全的聚合,我会坚持使用 SQL 方面的存储过程。
再说一次,没有足够的信息来说明您的计算性质,或者您的房子在开发人员的 SQL 功能方面要求什么支持,或者您的老板说什么……但既然我知道我的 SQL 方法,并且喜欢靠近数据,我会为这样的任务保留纯 SQL/存储过程。
YMMV :)
【讨论】:
【参考方案11】:它通常不会更有表现力,因为大多数存储过程语言在设计上都很糟糕。但它可能会比在外部应用中运行得更快。
我想这归结为您对 PL/SQL 的熟悉程度、编写此代码的时间、性能的重要性以及您是否可以合理地期望维护人员对 PL/SQL 足够熟悉以维护里面写的程序。
如果速度无关紧要,并且维护人员可能不精通 PL/SQL,那么使用“传统”语言可能会更好。
您还可以使用混合方法,使用 PL/SQL 生成中间数据(例如,表连接和求和等),并使用单独的应用程序来控制流并检查值和错误。
【讨论】:
以上是关于完全用 PL/SQL 编写大型批处理程序是否很愚蠢?的主要内容,如果未能解决你的问题,请参考以下文章