As per Oracle文档 http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/limits.htm,
PL/SQL 基于编程语言 Ada。
PL/SQL 使用 Ada 描述性中间属性表示法 (DIANA) 的变体,这是一种树结构中间语言。
它是使用称为接口定义语言 (IDL) 的元符号来定义的。
DIANA 由编译器和其他工具内部使用。
在编译时,PL/SQL 源代码被转换为机器可读的 m 代码。
过程或包的 DIANA 和 m 代码都存储在数据库中。
在运行时,它们被加载到共享内存池中。
DIANA用于编译依赖程序; m代码被简单地执行。
不幸的是,您无法根据解析的大小估计 DIANA 节点的数量。
具有相同解析大小的两个程序单元可能需要 1500 和 2000 个 DIANA 节点,
分别是因为,例如,第二个单元包含更复杂的 SQL 语句。
问汤姆说 http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:571023051648
有关 DIANA 节点计算的更多信息,请阅读本书“Ada-Europe '93:第 12 届 Ada-Europe 国际会议,“Ada Sans Frontieres”,法国巴黎,1993 年 6 月 14-18 日。会议记录”
以下支持说明很好地涵盖了这个主题......
Article-ID: <Note:62603.1>
Folder: PLSQL
Topic: General Information Articles
Title: 'PLS-123 Program too Large' - Size Limitations on PLSQL
Packages
Document-Type: BULLETIN
Impact: MEDIUM
Skill-Level: NOVICE
Server-Version: 07 to 08
Updated-Date: 13-JUN-2000 17:41:01
References:
Overview
本文包含有关 PL/SQL 包大小限制的信息。当限制为
达到时,您会收到以下错误:
PLS-123 Program too large
PL/SQL 包的大小限制
在 8.1.3 之前的版本中,大型程序会导致 PLS-123 错误。出现这种情况
因为编译器的真正限制;不是错误的结果。
编译 PL/SQL 单元时,编译器会构建解析树。最大尺寸为
PL/SQL 单元由解析树的大小决定。最大戴安娜节点数
存在于这棵树中。
在 7.3 之前,您可以有 2 * * 14 (16K) 个 diana 节点,从 8.0 到 8.1.3,可以有 2 * * 15 (32K) 个节点
允许戴安娜节点。在 8.1.3 中,此限制已放宽,因此您现在可以
此树中有 2 * * 26(即 64M)个 diana 节点用于包和类型体。
源代码限制
虽然没有简单的方法来转换源代码行数的限制,但我们观察到每行源代码大约有 5 到 10 个节点。在 8.1.3 之前,编译器最多可以干净地编译大约 3,000 行代码。
从 8.1.3 开始,放宽了包体和类型体的限制,现在最多可以有 6,000,000 行代码。
注意:此新限制仅适用于包体和类型体。此外,您现在可能会在达到此特定编译器限制之前开始达到一些其他编译器限制。
就源代码大小而言,假设标记(标识符、运算符、函数等)平均为四个字符长。那么,最大值将是:
Up to 7.3: 4 * (2 * * 14)=64K
From 8.0 to 8.1.3: 4 * (2 * * 15)=128K
With 8.1.3: 4 * (2 * * 25)=256M
这是一个粗略的估计。如果您的代码有很多空格、长标识符等,您可能
最终得到的源代码比这个更大。您最终可能会得到更小的源代码
如果您的来源使用非常短的标识符等,则比这更重要。
请注意,这是每个程序单元的,因此包体最有可能遇到这种情况
限制。
如何检查包裹的当前尺寸
要检查包的大小,您可以使用的最接近的相关数字是 PARSED_SIZE
数据字典视图USER_OBJECT_SIZE。该值提供了 DIANA 的大小
存储在 SYS.IDL_xxx$ 表中的字节数,而不是共享池中的大小。
PL/SQL 代码(在编译期间使用)的 DIANA 部分的大小要大得多
共享池的值比系统表中的值要大。
例如,当 PARSED_SIZE 中的 64K 限制时,您可能会开始遇到问题
USER_OBJECT_SIZE 不超过 50K。
对于一个包来说,解析后的大小或者DIANA的大小只对整个包有意义
对象,不单独用于规范和主体。
如果您为包选择 parsed_size,您将收到单独的源代码和代码大小
规范和主体,但只是整个对象的有意义的解析大小
是封装规范行的输出。 parsed_size 输出 0
就行了,为包体。
以下示例演示了此行为:
CREATE OR REPLACE PACKAGE example AS
PROCEDURE dummy1;
END example;
/
CREATE OR REPLACE PACKAGE BODY example AS
PROCEDURE dummy1 IS
BEGIN
NULL;
END;
END;
/
SQL> start t1.sql;
Package created.
Package body created.
SQL> select parsed_size from user_object_size where name='EXAMPLE';
PARSED_SIZE
-----------
185
0
SQL> select * from user_object_size where name='EXAMPLE';
.....
Oracle 将 DIANA 和 MCODE 都存储在数据库中。 MCODE 是实际运行的代码,
而特定图书馆单元 X 的 DIANA 包含以下信息:
使用库单元 X 编译程序。
以下是几点注意事项:
a) DIANA 在 IDL 中有代表。 IDL 的线性版本存储在磁盘上。这
实际的解析树被构建并存储在共享池中。这就是为什么尺寸
共享池中的 DIANA 通常大于磁盘上的。
b) 仅当您创建时,共享池中才需要调用过程的 DIANA
程序。在生产系统中,共享池中不需要 DIANA
(但仅适用于 MCODE)。
c) 从版本 7.2 开始,包体的 DIANA 被丢弃,不再使用,
并且不存储在数据库中。这就是为什么 PARSED_SIZE(即 DIANA 的大小)为
包体为 0。
因此,应该始终定义大型过程和函数
包内!
包存储在 DIANA 数据库中,就像过程一样。一个包可以用来
然而,打破依赖链,也许会让这个问题消失。我相信所有
生产(真实)代码应该位于包中,而不是位于独立的过程或函数中。