通过JDBC部署庞大的PLSQL包是非常缓慢的

时间:2011-02-24 10:37:54

标签: jdbc plsql

我必须通过JDBC部署非常大的PLSQL包,并且经历了非常长的部署持续时间。我知道使用包含高达25.000行代码的软件包并不是一个好主意,但我现在别无选择。通过JDBC部署这样的程序包大约需要2.5小时。

我从文件系统中读取了包,并将文件读取器包装在BufferedReader中。我逐行解析并检查分隔符并将每行附加到StringBuilder,直到语句完成。然后我使用StringBuilders toString()并将生成的String交给我的语句execute()。

感谢您的建议!

2 个答案:

答案 0 :(得分:1)

Oracle PL / SQL包由以下内容组成:

  • 包头 - 类似于C .h文件的规范
  • 包体 - 相当于.c文件

上传程序包标头将使使用该程序包中的函数/过程/记录/常量/对象/类型的所有PL / SQL程序包无效 - 通常是引用或使用程序包中某些内容的任何内容。

  

指定PACKAGE以重新编译包规范和包体(如果存在),无论它们是否无效。这是默认值。 重新编译包规范和正文会导致依赖对象的失效和重新编译,如规范和身体所述。

     

数据库还会使依赖于emp_mgmt的所有对象无效。如果您随后引用其中一个对象而未先显式重新编译它,则数据库会在运行时隐式重新编译它。

来源:http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/alter_package.htm

上传包体对数据库状态的影响较小。依赖于上传单位的套餐不会失效。

  

重新编译包体不会使依赖于包规范的对象无效。

     

当您重新编译包体时,如果任何这些对象无效,数据库将首先重新编译主体所依赖的对象。如果数据库成功重新编译主体,则主体变为有效。

来源:http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/alter_package.htm

编译时间极长的原因可能是由数据库执行的一系列重新编译引起的。这通常是将包头和包体保持在一个文件中,然后按顺序上传每个包的头部和主体的结果,如下例所示:

  • @ pkg_a.sql - 依赖项无效并重新编译尝试
  • @ pkg_b.sql - 与上面相同
  • @ pkg_c.sql - 与上述相同

在这种情况下,数据库可能会尝试多次重新编译某些软件包,因为尚未上载其他依赖项。这是浪费依赖性解决和编译的时间。

通过将包拆分为.pks(仅包含标题)和.pkb(仅包含正文),可以大大提高此方案。首先上传头文件,然后上传主体。

  • @ pkg_a.pks - 依赖项无效但未重新编译
  • @ pkg_b.pks - 与上述相同
  • @ pkg_c.pks - 与上述相同
  • @ pkg_a.pkb - pkg_a已成功重新编译,因为所有标头都是最新的
  • @ pkg_b.pkb - 与上述相同
  • @ pkg_c.pkb - 与上述相同

这是可能的,因为它只需要来自依赖项的包头有效来编译依赖包。 在这种情况下,每个包体的重新编译只发生一次

将包拆分为头文件和正文文件也可以避免上传未更改的头文件。这通常是因为大多数更改都是对库的正文(实际代码)进行的。跳过不必要的包头上传将导致更少的包被无效,因此 - 更少的工作来验证整个数据库。

这种方法可以帮助您大大减少将更改上传到数据库所需的时间。

答案 1 :(得分:0)

我不认为您的长包部署时间与Java,JDBC加载过程有关,而是与Oracle数据库包管理有关。

当您执行CREATE PACKAGE BODY FOO...时,RDBMS软件首先检查以确保系统中没有其他用户正在使用该程序包(通过数据库锁)。如果是,则您的进程会挂起,直到所有其他用户完成使用该程序包。然后它将您的包提交到数据库中。测试此方法的一种方法是重命名包(在原始源文件中)并尝试加载它。如果不花2.5小时,这可能是一个促成因素。

运行语句时RDMBS执行的另一件事是编译包,该包涉及验证代码中的所有引用(例如表,视图,其他包)并生成编码版本。对于大型包,编译时间可能很长。测试它的方法是运行语句ALTER PACKAGE FOO COMPILE;和时间。