当前位置:首页 >> 计算机软件及应用 >>

8


Oracle Database 11g: 面向 DBA 和开发人员的重要新特性

PL/SQL 性能
通过研究代码内联、真正的原生编译以及简单整数的用例来了解如何提高代码 性能。

Oracle Database 11g 引入了许多极有用的新特性用以提高 PL/SQL 代码的性能, 但其中最引人注目的特性是原生编译和内部单元内联。 原 生编译本身不是新特性,但无需任何前提条件(如安装 C 编译器)即可使用 此特性却是一项新技术。 Oracle 将这个改进的性能称为“真正的原生编译”。 ( ) 此外,新的数据类型 simple_integer 使得代码在原生编译下可以更好地执行。 内部单元内联是一种优化技术,利用此技术,PL/SQL 代码在编译期间可以生成 有效代码。 在本文中, 您将看到这些新特性的相应用例。您还会了解这些用例在不同方案中 的性能: 执行原生编译时、 使用简单整数时、 内联程序时以及在各种组合方案中。

真正的原生编译
您可能会想起 Oracle9i 数据库第 2 版中引入的原生编译;与解释形式相比, 使用原生编译时 PL/SQL 程序的执行速度要快得多。尽管有上述优点,但采用率 却很低, 这是因为许多系统管理员都不愿意在生产数据库服务器上安装所需的 C 编译器。另外,此类编译器还要求定义用于创建 O/S 中间文件的参数 plsql_native_library_dir。 在 Oracle Database 11g 中,无需在服务器上安装 C 编译器或设置参数即可执 行原生编译。只需在创建或重新编译存储的代码之前设置一个会话参数即可: alter session set plsql_code_type = native; ...

compile the code here ...

原生编译所需时间比解释编译长,但由于目前在 Oracle Database 11g 中执行 进程的速度非常快, 因此影响不是很明显。您可能希望在常规开发周期中使用解 释编译模式,而在开发结束时使用原生编译模式,这通常是一个很好的做法。 作为 11g 移植的一部分,我用关键任务应用程序中的实际代码(一个相当大的 程序包,共 5,827 行代码)做了一个试验。我在现有的 10g 数据库和新的 11g 数据库上对该代码执行了原生编译,然后使用解释编译重复了相同的操作。执行 这两编译时都将 plsql_optimize_level 设置为 2。 我测量了每种方案的编译时 间,如下所示(以秒为单位)。 10g 解释 原生 1.66 4.66 11g 1.64 2.81

结果显而易见。执行解释编译时,完成时间非常接近。但是执行原生编译时,在 11g 下的编译时间大大缩短,约为 10g 下的 60%。因此,尽管在 11g 下执行原 生编译时延长了编译时间,但仍然比 10g 下的原生编译快的多。 要了解哪些对象已使用 NATIVE 进行了编译,可以查看 USER_PLSQL_OBJECT_SETTINGS 视图: SQL> select name, PLSQL_code_type 2> from user_plsql_object_settings; NAME -------------------DO_CALC PERFECT_TRIANGLES PRIME_NUMBERS PRIME_NUMBERS SOME_MATH TR_BOOKINGS_TRACK TR_SALGRADE_COMP UPD_INT PLSQL_CODE_TYPE --------------NATIVE NATIVE NATIVE NATIVE INTERPRETED INTERPRETED INTERPRETED NATIVE

还有一个适用于所有对象的类似视图 DBA_PLSQL_OBJECT_SETTINGS。

新数据类型:简单整数

如 果使用新的数据类型 simple_integer,则原生编译的优势更为明显。从技术 上讲,它不是真正的数据类型,而是数据类型 pls_integer 的子类型。简单整 数被定义为利用硬件运算而不是软件运算。 将简单整数与真正的原生编译结合使 用时,性能将显著提高。看了后面的试验,您就会明白其中的原 委。 由于 simple_integer 是 pls_integer 的子类型,因此继承了如下属性:它是 32 位带符号整数,可以具有介于负 2,147,483,648 和 2,147,483,647 之间的 整数值。但是,它与 pls_integer 之间存在以下不同点:simple_integer 不能 为空,但允许溢出 — 当所分配的值超过最大值时,它将回绕而不返回错误。 从语法上讲,在可以使用 pls_integer 的任何位置均可使用此数据类型,但要 仔细注意它们之间的差别;simple_integer 的其他属性可能导致它在某些情况 下不适用。 在用 pls_integer 替代 simple_integer 之前,我们来看一些您应当了解的潜 在问题:
? ?

此变量不能为空,因此,如果未将变量声明写成: num1 simple_integer:= 1;

? ? ? ? ? ? ? ? ? ? ? ?

而写成: num1 simple_integer; 则会收到编译错误: PLS-00218: a variable declared NOT NULL must have an initialization assignment 如果在程序内将变量设置为 NULL,如: num1 := NULL; 则会收到编译错误: PLS-00382: expression is of wrong type 请注意这些错误消息, 它们看上去可能未表达出错误的确切本质。如果您 的程序要求将某个变量设置为空,则不能将该变量定义为 simple_integer。 有关 simple_integer 的另一个要点涉及在超出最大值和最小值时回绕 值。请记住,pls_integer 的最大正值为 2147483647。如果尝试存储一 个较大值时将会发生什么?我们来看一个代码示例: declare v1 pls_integer := 2147483647; begin v1 := v1 + 1; dbms_output.put_line('v1='||v1);

?

? ? ? ? ? ?

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

end; / 它将抛出一个错误: declare * ERROR at line 1: ORA-01426: numeric overflow ORA-06512: at line 4 该错误很明显,并且非常适当;您尝试超出数据类型允许的最大值。如果 使用 simple_integer 而不是 pls_integer: declare v1 simple_integer := 2147483647; begin v1 := v1 + 1; dbms_output.put_line('v1='||v1); end; / 输出应如下所示: v1=-2147483648 请注意该值 (-2147483648),它是 simple_integer 的最小值。当您增加 到最大值 (2147483647) 时,该值只是回绕到初始值,这是 simple_integer 的一个特性。请注意此行为。

将真正的原生编译和简单整数结合使用
如 您所见, 不能随便在任意位置使用 simple_integer;使用之前必须仔细确定 边界条件(尤其是值的潜在回绕)。此外,simple_integer 是针对原生编译设 计的。在解释编译中,它们可能不会提供很大的性能改进(但也不会降低性能, 您将在后面看到这一点)。在真正的原生模式 下,simple_integer 的性能优势 尤为突出。 实际上,大多数 PL/SQL 业务应用程序都主要是使用 SQL 开发的,因此这些应 用程序不会通过原生编译获得显著的性能改进。在“前一个周期”中,我使用 PL/SQL 开发了一个数据库容量规划工具,其中包含许多数值计算和统计计算, 代码超过几千行。执行原生编译时,此工具的性能得到了极大改进。简单整数当 时不可用,否 则会带来更大的性能优势。

内部单元内联

内部单元内联是指使用子例程代码的副本替换对该子例程的调用。通常,修改后 的代码运行速度更快。在 Oracle Database 11g 中,PL/SQL 编译器能够确定应 该复制(或内联)对哪个子例程的哪些调用并做出更改,从而提高性能。 通过示例可以对此进行很好地说明。 下面的代码使用对帐户余额计算得到的利息 更新名为 BALANCES 的表。代码遍历表的所有记录,计算利息,然后更新表的余 额列。 create or replace procedure upd_int is /* original version */ l_rate_type balances.rate_type%type; l_bal balances.balance%type; l_accno balances.accno%type; l_int_rate number; procedure calc_int ( p_bal in out balances.balance%type, p_rate in number ) is begin if (p_rate >= 0) then p_bal := p_bal * (1+(p_rate/12/100)); end if; end; begin for ctr in 1..10000 loop l_accno := ctr; select balance, rate_type into l_bal, l_rate_type from balances where accno = l_accno; select decode(l_rate_type, 'C', 1, 'S', 3, 'M', 5, 0) into l_int_rate from dual; for mth in 1..12 loop calc_int (l_bal, l_int_rate); update balances set balance = l_bal where accno = l_accno; end loop; end loop; end; /

由于所有记录类型的实际利息计算方法相同, 因此我将该逻辑放在主过程内的一 个单独过程 calc_int() 中。 这样可以提高代码的可读性和可维护性,但效率很 低。

然而,如果我编写 calc_int() 中所示的代码而不调用 calc_int(),则会创建 一个速度较快的程序,如下所示: create or replace procedure upd_int is /* revised version */ l_rate_type balances.rate_type%type; l_bal balances.balance%type; l_accno balances.accno%type; l_int_rate number; begin for ctr in 1..10000 loop l_accno := ctr; select balance, rate_type into l_bal, l_rate_type from balances where accno = l_accno; select decode(l_rate_type, 'C', 1, 'S', 3, 'M', 5, 0) into l_int_rate from dual; for mth in 1..12 loop -- this is the int calc routine if (l_int_rate >= 0) then l_bal := l_bal * (1+(l_int_rate/12/100)); end if; update balances set balance = l_bal where accno = l_accno; end loop; end loop; end; / 修改后的代码与原始代码唯一的不同之处在于, 用于计算利息的代码现在处于循 环中,而不在过程 calc_int() 内。

请注意,新版本可能更快,但这不是很好的编码方法。用于计算利息的代码部分 在月份循环的每次迭代时执行一次,然后针对每个帐号执行一次。由于重复执行

该部 分代码,因此将这部分代码单独放在一个过程 (calc_int) 中更合理,如 上一版本的 upd_int 代码中所示。该方法可以使代码模块化,易于维护,且可 读性极强,但效率较低。 那么, 如何同时实现代码模块化和提高执行速度这两个互相冲突的目标呢?以模 块化方式编写代码(像 upd_int 的第一个版本那样),然后让 PL/SQL 编译器 对代码进行“优化”,使其看上去像代码的第二个版本,这种方法如何呢? 在 Oracle Database 11g 中可以执行此操作。只需使用较高的 PL/SQL 优化级 别重新编译过程即可。完成此操作有两种方法:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

设置会话级别参数并重新编译过程: SQL> alter session set plsql_optimize_level = 3; Session altered. 上述设置指示 PL/SQL 编译器重写代码以内联该代码。 使用 plsql 设置直接编译过程。 SQL> 2 3 4 alter procedure upd_int compile plsql_optimize_level = 3 reuse settings;

Procedure altered. 同一会话中编译的任何其他过程都不会受影响。 当您要在同一会话中编译 很多过程时,这是处理内联的一种较好的方法。还可以使用编译器指令 pragma。

create or replace procedure upd_int is l_rate_type varchar2(1); ... ... begin

pragma inline (calc_int, 'YES'); for ctr in 1..10000 loop ... ... end;

我添加了 pragma inline (calc_int, 'YES'); 行以便让编译器内联该过程。同 样,您也可以在此处使用“NO”,以通知编译器不内联此过程,即使将 plsql_optimizer_level 设置为 3 时也是如此。

此内联过程可以使代码执行速度更快。 性能改进的程度自然根据编译器可能执行 内联的程度而有所不同。在本文结尾,您将看到一个使用内联的示例代码,并会 看到代码内联带来的性能改进。

编译时间
当然,此优化过程使得编译器的工作效率更高。但工作效率提高多少呢? 为了回答这个问题, 我采用了前面提供的实际生活应用程序代码,并在不同的组 合方案(内联/非内联和解释/原生)中对其进行了编译。下面是编译时间: 内联 解释 原生 1.70 3.15 未内联 1.64 2.81

结果是显而易见的。 使用内联选项执行编译时,在解释编译模式下编译时间略有 增加 (大约 4%) 执行原生编译时, 。 编译时间也有所增加, 但增幅较大, 约为 12%。 因此,您可能希望在开发周期中使用内联/解释选项编译应用程序,然后在最后 阶段使用原生编译。使用内联特性似乎没有显著增加编译时间,因此开发周 期 时间不会受到很大影响。

现在有一个重要问题: 既然您没有更改代码,如何确认代码被内联呢?可以通过 设置会话变量完成该操作: alter session set plsql_warnings = 'enable:all'; 现在,当您重新创建过程之后: SQL> @upd_int SP2-0804: Procedure created with compilation warnings 请注意此时发出的警告消息。要查看警告消息,请使用以下命令: SQL> show error Errors for PROCEDURE UPD_INT:

LINE/COL ERROR -----------------------------------------------------------------------7/5 PLW-06006: uncalled procedure "CALC_INT" is removed. 28/13 PLW-06005: inlining of call of procedure 'CALC_INT' was done 请注意最后一行,它确认了过程 calc_int 确实已被内联。

如果您要了解哪些对象是以什么级别进行编译的,可以查询视图 USER_PLSQL_OBJECT_SETTINGS: sql> select name, plsql_optimize_level 2> from user_plsql_object_settings; NAME PLSQL_OPTIMIZE_LEVEL --------------------------------------DO_CALC 2 PERFECT_TRIANGLES 2 TR_BOOKINGS_TRACK 2 TR_SALGRADE_COMP 2 UPD_INT 3 ... and so on ... 还有一个适用于所有对象的类似视图:DBA_PLSQL_OBJECT_SETTINGS。

请记住,这是内部单元内联,只有单元内部的过程才被内联。单元外部的子例程 不会被内联。

运行试验
现在通过一个可重复的试验来检验这些优点。 您需要创建一个程序包的基础性版 本,然后根据前面学过的概念修改变量数据类型和编译指令。 首先,创建欧几里德算法的一个实现,以算出两个数字的最大公约数。下面是 Wiki 页中的函数逻辑: function gcd(a, b) if a = 0 return b while b ≠ 0 if a > b a := a - b else

b := b - a return a 我们将查看在这些修饰符的不同组合下执行此程序包所占用的 CPU 时间,并记 录所用时间。因此,接下来创建一个用于存储 CPU 时间的表: create table times( native char(1) check (native in ('Y', 'N')) enable, simple char(1) check (simple in ('Y', 'N')) enable, inlining char(1) check (inlining in ('Y', 'N')) enable, centiseconds number not null, constraint times_pk primary key (simple, inlining, native)) / 共有三个列: 原生、 简单和内联, 分别用于指定原生编译、 简单整数和内联代码。 列中的“Y”表示编译代码时使用了该特性。因此,下面的记录: NATIVE SIMPLE INLINING CENTISECONDS -----------------Y N N 100

------------

表示对程序执行了原生编译但未使用简单整数,未发生代码内联,并且此组合占 用了 100 厘秒的 CPU 时间。

如果只使用一份程序包, 请使用条件编译(在 Oracle 数据库 10g 第 2 版中引 入)修改该程序包。下面是创建程序包的方法: -- suppress these expected warnings: -- inlining of call of procedure 'gcd' was done -- uncalled procedure "gcd" is removed. -- unreachable code -- keyword "native" used as a defined name alter session set plsql_warnings = 'enable:all, disable:06002, disable:06005, disable:06006, disable:06010' / alter session set plsql_ccflags = 'simple:false' / create package gcd_test is procedure time_it; end gcd_test; / create package body gcd_test is $if $$simple $then

subtype my_integer is simple_integer; simple constant times.simple%type := 'y'; $else subtype my_integer is pls_integer not null; simple constant times.simple%type := 'n'; $end function gcd(p1 in my_integer, p2 in my_integer) return my_integer is v1 my_integer := p1; v2 my_integer := p2; begin while v2 > 0 loop if v1 > v2 then v1 := v1 - v2; else v2 := v2 - v1; end if; end loop; return v1; end gcd; function exercise_gcd return number is -- expected value depends on no_of_iterations. expected_checksum my_integer := 74069926; -- 2475190; no_of_iterations constant my_integer := 5000; -- 1000; checksum my_integer := 0; v my_integer := 0; t0 number; t1 number; begin for warmup in 1..2 loop checksum := 0; t0 := dbms_utility.get_cpu_time(); for j in 1..no_of_iterations loop v := gcd(j, j); if v <> j then raise_application_error(-20000, 'logic error: gcd(j, j) <> j'); end if; checksum := checksum + v; for k in (j + 1)..no_of_iterations loop v := gcd(j, k); if gcd(k, j) <> v then

raise_application_error(-20000, 'logic error: gcd(j, k) <> gcd(k, j)'); end if; checksum := checksum + v; end loop; end loop; if checksum <> expected_checksum then raise_application_error(-20000, 'checksum <> expected_checksum: '||checksum); end if; t1 := dbms_utility.get_cpu_time(); end loop; return t1 - t0; end exercise_gcd; procedure time_it is inlining times.inlining%type; native times.native%type; centiseconds constant times.centiseconds%type := exercise_gcd(); begin if lower($$plsql_code_type) = 'native' then native := 'y'; else native := 'n'; end if; if $$plsql_optimize_level = 3 then inlining := 'y'; else inlining := 'n'; end if; insert into times(native, simple, inlining, centiseconds) values(time_it.native, gcd_test.simple, time_it.inlining, time_it.centiseconds); commit; end time_it; end gcd_test; / show errors

程序包有足够的行内注释,使代码具有自描述性,所以此处不作详细解释。概括 来说,函数 GCD() 接受两个值,并返回这两个值的最大公约数。函数 exercise_gcd() 调用 GCD() 函数,并返回执行所占用的 CPU 时间,以厘秒表 示。最后,公共过程 TIME_IT() 以相应的自由度调用 EXERCISE_GCD() 函数, 并向 TIMES 表中插入一条记录。

现在, 您需要使用不同的修饰符调用打包过程几次, 并记录每种情况下的 CPU 时 间。可以通过在编译程序包之前更改条件编译变量来执行此操作: truncate table times / -- Interpreted ---------------------------------------------- Simple:false -- No Inlining alter package GCD_Test compile body PLSQL_Code_Type = interpreted PLSQL_CCFlags = 'Simple:false' PLSQL_Optimize_Level = 2 /* no inlining */ reuse settings / begin GCD_Test.Time_It(); end; / -- inlining alter package GCD_Test compile body PLSQL_Code_Type = interpreted PLSQL_CCFlags = 'Simple:false' PLSQL_Optimize_Level = 3 /* inlined */ reuse settings / begin GCD_Test.Time_It(); end; / -- Simple:true -- no inlining alter package GCD_Test compile body PLSQL_Code_Type = interpreted PLSQL_CCFlags = 'Simple:true' PLSQL_Optimize_Level = 2 reuse settings / begin GCD_Test.Time_It(); end;

/ -- inlined alter package GCD_Test compile body PLSQL_Code_Type = interpreted PLSQL_CCFlags = 'Simple:true' PLSQL_Optimize_Level = 3 reuse settings / begin GCD_Test.Time_It(); end; / -- Native -------------------------------------------------- Simple:false -- no inlining alter package GCD_Test compile body PLSQL_Code_Type = native PLSQL_CCFlags = 'Simple:false' PLSQL_Optimize_Level = 2 reuse settings / begin GCD_Test.Time_It(); end; / -- inlined alter package GCD_Test compile body PLSQL_Code_Type = native PLSQL_CCFlags = 'Simple:false' PLSQL_Optimize_Level = 3 reuse settings / begin GCD_Test.Time_It(); end; / -- Simple:true -- no linlining alter package GCD_Test compile body PLSQL_Code_Type = native PLSQL_CCFlags = 'Simple:true' PLSQL_Optimize_Level = 2 reuse settings / begin GCD_Test.Time_It(); end; /

-- inlined alter package GCD_Test compile body PLSQL_Code_Type = native PLSQL_CCFlags = 'Simple:true' PLSQL_Optimize_Level = 3 reuse settings / begin GCD_Test.Time_It(); end; / 要查明上述每种方案中的性能改进程度,请使用以下代码: spool timings.txt <<b>>declare Interp_Pls_Integer_Noinline Interp_Pls_Integer_Inline Interp_Simple_Integer_Noinline Interp_Simple_Integer_Inline Native_Pls_Integer_Noinline Native_Pls_Integer_Inline Native_Simple_Integer_Noinline Native_Simple_Integer_Inline

Times.Centiseconds%type; Times.Centiseconds%type; Times.Centiseconds%type; Times.Centiseconds%type; Times.Centiseconds%type; Times.Centiseconds%type; Times.Centiseconds%type; Times.Centiseconds%type;

procedure Show_Caption(Caption in varchar2) is begin DBMS_Output.Put_Line(Chr(10)||Rpad('-', 60, '-')||Chr(10)||Chr(10)||Caption||Chr(10)); end Show_Caption; procedure Show_Ratio(Var1 in varchar2, Var2 in varchar2, Ratio in number) is begin DBMS_Output.Put_Line(Rpad(Var1, 15)||'and '||Rpad(Var2, 14)||To_Char(Ratio, '99.99')); end Show_Ratio; begin select a.Centiseconds into b.Interp_Pls_Integer_Noinline from Times a where a.Native = 'N' and a.Simple = 'N' and a.Inlining = 'N'; select a.Centiseconds

into from where select into from where select into from where select into from where select into from where select into from where select into from where

b.Interp_Pls_Integer_Inline Times a a.Native = 'N' and a.Simple = 'N' and a.Inlining = 'Y'; a.Centiseconds b.Interp_Simple_Integer_Noinline Times a a.Native = 'N' and a.Simple = 'Y' and a.Inlining = 'N'; a.Centiseconds b.Interp_Simple_Integer_Inline Times a a.Native = 'N' and a.Simple = 'Y' and a.Inlining = 'Y'; a.Centiseconds b.Native_Pls_Integer_Noinline Times a a.Native = 'Y' and a.Simple = 'N' and a.Inlining = 'N'; a.Centiseconds b.Native_Pls_Integer_Inline Times a a.Native = 'Y' and a.Simple = 'N' and a.Inlining = 'Y'; a.Centiseconds b.Native_Simple_Integer_Noinline Times a a.Native = 'Y' and a.Simple = 'Y' and a.Inlining = 'N'; a.Centiseconds b.Native_Simple_Integer_Inline Times a a.Native = 'Y' and a.Simple = 'Y' and a.Inlining = 'Y';

Show_Caption('Benefit of simple_integer'); Show_Ratio('Interpreted', 'no inlining', Interp_Pls_Integer_Noinline / Interp_Simple_Integer_Noinline); Show_Ratio('Interpreted', 'inlining', Interp_Pls_Integer_Inline / Interp_Simple_Integer_Inline); Show_Ratio('Native', 'no inlining', Native_Pls_Integer_Noinline / Native_Simple_Integer_Noinline); Show_Ratio('Native', 'inlining', Native_Pls_Integer_Inline / Native_Simple_Integer_Inline);

Show_Caption('Benefit of inlining'); Show_Ratio('Interpreted', 'pls_integer', Interp_Pls_Integer_Noinline / Interp_Pls_Integer_Inline); Show_Ratio('Interpreted', 'simple_integer', Interp_Simple_Integer_Noinline / Interp_Simple_Integer_Inline); Show_Ratio('Native', 'pls_integer', Native_Pls_Integer_Noinline / Native_Pls_Integer_Inline); Show_Ratio('Native', 'simple_integer', Native_Simple_Integer_NoInline / Native_Simple_Integer_Inline); Show_Caption('Benefit of native'); Show_Ratio('pls_integer', 'no inlining', Interp_Pls_Integer_Noinline / Native_Pls_Integer_Noinline); Show_Ratio('pls_integer', 'inlining', Interp_Pls_Integer_Inline / Native_Pls_Integer_Inline); Show_Ratio('simple_integer', 'no inlining', Interp_Simple_Integer_Noinline / Native_Simple_Integer_Noinline); Show_Ratio('simple_integer', 'inlining', Interp_Simple_Integer_Inline / Native_Simple_Integer_Inline); end b; / spool off 以下为输出内容。它显示了 CPU 时间与默认值之比:非内联、解释编译且使用 pls_integer。 -----------------------------------------------------------Benefit of simple_integer Interpreted Interpreted Native Native and and and and no inlining inlining no inlining inlining 1.00 1.00 2.19 2.79

-----------------------------------------------------------Benefit of inlining Interpreted Interpreted Native Native and and and and pls_integer simple_integer pls_integer simple_integer 1.07 1.07 1.16 1.48

-----------------------------------------------------------Benefit of native pls_integer pls_integer simple_integer simple_integer and and and and no inlining inlining no inlining inlining 4.78 5.18 10.53 14.49

从上述输出可以看到,默认情况下执行所占用的 CPU 时间为使用内联和 simple_integer 的原生编译的 14.49 倍 — 无论用哪种标准来衡量, 这都是非 常显著的性能改进。

总结
现在您应该已经了解了这些新特性的功能和用途。总结:
?

?

?

?

? ?

从 语法上讲,在可以使用 pls_integer 的任何位置都可以使用 simple_integer 数据类型,但要注意值的潜在回绕和非空要求。这意味 着不能盲目地处处使用简单整数。 如果应用程序不会意外超出最大值或低 于最小值,则将简单整数与原生编译 结合使用是一种很好的方法。 与原生编译结合使用时,simple_integer 的优势非常明显,而与解释编 译结合使用时则不明显。请注意,即使与解释编译结合使用, simple_integer 也同样是有益无害的。 内联与原生编译结合使用时其优势也要比与解释编译结合使用时大得多。 这一点更难解释。不严格地讲,接近普通编译后端的代码越紧凑,原生分 支在域中执行智能优化(在解释分支中不可行)的机会越多。 当程序比较顺从时 (即, 不是使用 SQL 开发的, 且不使用 Oracle 数字、 日期等),原生编译的优势最明显。请注意,即使符合这些条件,性能改 进的程度也会在很大的范围内变化。 在 Oracle Database 11g 中选择原生编译和内联是一件自然而然的事情。 不选的唯一原因可能是编译时间较长 (也许在早期的开发阶段确实如此) 。 可以安全使用 simple_integer 的机会不是很多。但一旦出现这种机会, 就应该牢牢抓住它。


相关文章:
概(8)答案.doc
概(8)答案 - 习题 1. 已知某炼铁厂的铁水含碳量在正常情况下服从正态分布
8的乘8的乘法口诀_图文.ppt
8的乘8的乘法口诀 - 口算下面个题,并说出用哪一句口诀。 4×6=24 四六二
希伯来书第八章.doc
这约是神主动另立的新约(8~9节) 4.这约将律法写在人的心上(10~12节)
link8.doc
link8 - LINK8 单元描述 名称: 名称:LINK8三维杆(或桁架)单元 有效产品: 有效产品:MP ME PR PP ED LINK8 单元说明: 单元说明: LINK8 单元是...
dreamweaver8使用教程.doc
dreamweaver8使用教程 - 第一天的内容可能让你觉得枯燥乏味,不过, “工欲善其事,必先利其器” 让我们 , 一起来了解 Dreamweaver8 的操作环境,完成站点的创建。 ...
好领导的八个标准.doc
8、立行而不拖拉 做领导工作,贵在求真务实,要在雷厉风行。领导干部千万不能只说不
八个严禁.doc
8、不准违反规定拥有非上市公司 企业 的股份或者证券; 有非上市公司(企业 的股
8的口诀_图文.ppt
8的口诀 - 口算下面个题,并说出用哪一句口诀。 4×6=24 四六二十四 7×
8_工业以太网_图文.ppt
8_工业以太网 - 工业控制网络 主讲教师:王振力 第8章 工业以太网 8.1 工业以太网简介 8.2 EPA 8.3 PROFINET 8.4 HSE 8.5 Ethernet/IP ...
八知道.doc
知道 - 1. 一般情况 (床号 姓名 性别 年龄 主管医生 责任护士 ) 2
8以内乘法.xls
8以内乘法 - 按F9可自动翻页,无限次使用... 8以内乘法_二年级数学_数学_小学教育_教育专区。按F9可自动翻页,无限次使用 8×1= 8×4= 3×7= 3×6= 4×4...
模八.doc
8、 使他兴奋的是,他不仅被这所大学录取了,还获得了全额奖学金。 (admiss
“一…就…”的八个句型.doc
8.At the sight/thought/mention of+名词,+主句
8人制足球比赛规则.doc
8人制足球比赛规则 - 8 人制足球比赛规则 一、比赛场地 长度:最长 75 米
八大傻.doc
“傻”: 1、下班马上上市场 2、回家立即下厨房 3、买衣从来不高档 4、有钱就知存银行 5、再远都挤公交车 6、一心一意为家忙 7、最多认识两女友 8、...
八要八不准.doc
5、要便民利民快捷高效,不准马虎拖拉; 6、要文明礼貌热情周到,不准怠慢群众; 7、要公示补偿接受监督,不准暗箱操作; 8、要严查违规依章处理,不准姑息迁就。 您...
成功家长应具备的八个能力.doc
8.启蒙教育:开发孩子智力的能力 “雏凤清于老凤声” 自古就是人们最乐于接受的恭
8章课后作业_图文.ppt
8章课后作业 - 【题 8-6】 】 如图所示,设已知四杆机构各构件的长度为 如
八支斋戒.doc
关斋戒即:1、不杀生;2、不盗;3、不淫;4、不妄语;5、不饮酒;6、不香华严 身,歌舞观听;7、不得坐卧高广严丽的床座;8、不得非时食。 关斋戒...
第八章答案.doc
章答案 - 第章答案 8-1 若由 MgO 和 Al2O3 球形颗粒之间的
更多相关文章: