3

我们正在讨论将通用函数/过程放在单独的包中或在每个包中使用本地副本对性能的影响。

我的想法是在一个包中包含公共代码会更干净,但其他人担心性能开销。

想法/经验?

4

3 回答 3

7

将它放在一个地方并从多个地方调用它——这是基本的代码重用。从另一个包调用一个包的任何开销都是微不足道的。如果他们仍然怀疑,让他们展示性能差异。

于 2009-11-09T15:05:14.223 回答
5

担心者完全可以通过展示性能开销来证明他们所关心的问题的有效性。这应该是微不足道的。

同时他们应该考虑在多个地方重复代码时的内存使用和维护开销。

通用代码放在一个包中。

于 2009-11-09T15:18:40.773 回答
1

除非您通过 DB 链接调用位于不同数据库中的包中的过程,否则调用另一个包中的过程的开销可以忽略不计。

存在一些性能问题以及内存问题,但它们很少见。此外,它们属于“甲骨文黑魔法”类别。例如,检查此链接。如果您能清楚地理解那是什么,请认为您自己是一位成功的 Oracle 专业人士。如果没有 - 不要担心,因为它真的是铁杆的东西。

但是,您应该考虑的是依赖性问题。Oracle 包由 2 部分组成:规范正文规范是一个标头,其中声明了公共过程和函数(即,在包外可见)。 正文是它们的实现。虽然紧密相连,但它们是 2 个独立的数据库对象。

Oracle 使用包状态来指示包是 VALID 还是 INVALID。如果一个包变得无效,那么依赖它的所有其他包也将变得无效。例如,如果你的程序调用包 A 中的一个过程,它调用包 B 中的一个过程,这意味着你的程序依赖于包 A,而包 A 依赖于包 B。在 Oracle 中,这种关系是可传递的,这意味着你的程序依赖于包 B。因此,如果包 B 损坏,您的程序也会停止(因错误而终止)。

这应该是显而易见的。但不太明显的是,Oracle 还在编译期间通过包规范跟踪依赖关系。

假设您的包 A 和包 B 的规范和主体均已成功编译且有效。然后你去更改包 B 的包体。因为你只改变了包体,而不是规范,Oracle 假设调用包 B 的方式没有改变,也没有做任何事情。

但是,如果随着主体一起更改包 B 的规范,那么 Oracle 会怀疑您可能更改了某些过程的参数或类似的东西,并将整个链标记为无效(即包 B 和 A 以及您的程序)。请注意,Oracle 不检查规范是否真的改变了,它只是检查时间。因此,只需重新编译规范以使所有内容无效就足够了。

如果发生失效,下次运行程序时它将失败。但是如果之后再运行一次,Oracle 会自动重新编译所有内容并成功执行。

我知道这很混乱。那是甲骨文。不要试图用你的大脑过多地围绕它。你只需要记住几件事:

  • 尽可能避免复杂的包间依赖关系。如果一件事依赖于另一件事,而另一件事又依赖于另一件事,以此类推,那么仅通过重新编译一个数据库对象而使所有内容无效的可能性非常高。最坏的情况之一是“循环”依赖关系,当包 A 调用包 B 中的过程,包 B 调用包 A 中的过程。在这种情况下,几乎不可能在不制动另一个的情况下编译一个。

  • 将包规范和包主体保存在单独的源文件中。如果你只需要改变身体,不要碰规格!

于 2009-11-10T02:24:48.470 回答