Oracle - 函数与过程性能比较
Oracle - 函数与过程性能比较
我正在组合一个用于执行一些操作并返回日期范围的关联数组的包。我一直在使用函数,但我开始怀疑是否从性能上来说这是最好的选择,所以我编写了一个测试包来进行检查:
CREATE OR REPLACE PACKAGE pk_perf_test IS TYPE pt_rDateSpan IS RECORD ( start_date DATE, end_date DATE ); TYPE pt_aaDateTable IS TABLE OF pt_rDateSpan INDEX BY PLS_INTEGER; FUNCTION pf_getDateTable (p_nInputParam INTEGER) RETURN pt_aaDateTable; PROCEDURE pp_getDateTable (p_nInputParam INTEGER, op_aaDateTable OUT pt_aaDateTable); PROCEDURE pp_getDateTable_NoCopy (p_nInputParam INTEGER, op_aaDateTable OUT NOCOPY pt_aaDateTable); END pk_perf_test;
每个函数/过程只是运行相同的查询,使用输入参数作为绑定变量将结果使用BULK COLLECT存储到集合中。像这样:
CREATE OR REPLACE PACKAGE BODY pk_perf_test IS FUNCTION pf_getDateTable (p_nInputParam INTEGER) RETURN pt_aaDateTable IS l_aaToRet pt_aaDateTable; BEGIN SELECT mt.start_date, mt.end_date BULK COLLECT INTO l_aaToRet FROM my_table mt INNER JOIN my_other_table mot ON mt.pk_col = mot.fk_col WHERE mt.pk_col = p_nInputParam; RETURN l_aaToRet; END pf_getDateTable; PROCEDURE pp_getDateTable (p_nInputParam INTEGER, op_aaDateTable OUT pt_aaDateTable) IS BEGIN SELECT mt.start_date, mt.end_date BULK COLLECT INTO op_aaDateTable FROM my_table mt INNER JOIN my_other_table mot ON mt.pk_col = mot.fk_col WHERE mt.pk_col = p_nInputParam; END pp_getDateTable; PROCEDURE pp_getDateTable_NoCopy (p_nInputParam INTEGER, op_aaDateTable OUT NOCOPY pt_aaDateTable) IS BEGIN SELECT mt.start_date, mt.end_date BULK COLLECT INTO op_aaDateTable FROM my_table mt INNER JOIN my_other_table mot ON mt.pk_col = mot.fk_col WHERE mt.pk_col = p_nInputParam; END pp_getDateTable_NoCopy; END pk_perf_test;
然后,我编写了一个简短的脚本来测试它们的性能:
DECLARE l_tsStartTS TIMESTAMP WITH LOCAL TIME ZONE; l_iFunctionTotal INTERVAL DAY TO SECOND := INTERVAL '0' SECOND; l_iProcedureTotal INTERVAL DAY TO SECOND := INTERVAL '0' SECOND; l_iNoCopyTotal INTERVAL DAY TO SECOND := INTERVAL '0' SECOND; l_aaDummy pk_perf_test.pt_aaDateTable; l_nDummy INTEGER := 123; l_nCaseCount INTEGER := 0; CURSOR c_ids IS SELECT mt.pk_col FROM my_table SAMPLE (10) mt; BEGIN --Priming Query Run to make sure plan is cached SELECT mt.start_date, mt.end_date BULK COLLECT INTO l_aaDummy FROM my_table mt INNER JOIN my_other_table mot ON mt.pk_col = mot.fk_col WHERE mt.pk_col = l_nDummy; FOR r IN c_ids LOOP l_nCaseCount := l_nCaseCount + 1; l_aaDummy.DELETE; l_tsStartTS := SYSTIMESTAMP; l_aaDummy := pk_perf_test.pf_getDateTable(r.pk_col); l_iFunctionTotal := l_iFunctionTotal + (SYSTIMESTAMP-l_tsStartTS); l_aaDummy.DELETE; l_tsStartTS := SYSTIMESTAMP; pk_perf_test.pp_getDateTable(r.pk_col, l_aaDummy); l_iProcedureTotal := l_iProcedureTotal + (SYSTIMESTAMP-l_tsStartTS); l_aaDummy.DELETE; l_tsStartTS := SYSTIMESTAMP; pk_perf_test.pp_getDateTable_NoCopy(r.pk_col, l_aaDummy); l_iNoCopyTotal := l_iNoCopyTotal + (SYSTIMESTAMP-l_tsStartTS); END LOOP; dbms_output.put_line('Total Cases: '||l_nCaseCount); dbms_output.put_line('Function Total: '||l_iFunctionTotal); dbms_output.put_line('Procedure Total: '||l_iProcedureTotal); dbms_output.put_line('No Copy Total: '||l_iNoCopyTotal); END; /
我得到了以下结果:
Total Cases: 10787 Function Total: +00 00:00:22.857400 Procedure Total: +00 00:00:04.346413 No Copy Total: +00 00:00:01.942333
现在是我的问题。我明白为什么NOCOPY比普通过程快。但我不明白为什么普通过程比函数快得多?我认为这可能是一个偶然现象,所以我在多个环境中运行了多次,并得到了类似的结果(我发布的结果实际上是所有运行的平均值)。有人能解释为什么性能会如此不同吗?或者指出我测试中的缺陷?
问题的原因:
该问题的原因是关于Oracle中函数(Function)和过程(Procedure)的性能差异的疑问。询问者想知道函数和过程在性能方面是否有差异。
解决方法:
根据该问题的回答者,函数和过程在性能方面没有差异。它们之间唯一的区别是它们的工作方式。因此,根据具体情况选择使用函数或过程即可。
总结:
在Oracle中,函数和过程的性能没有差异。它们的区别在于它们的工作方式。因此,根据具体情况选择使用函数或过程即可,不会对性能产生影响。