First of all, let’s setup the environment:
1. on the database server create a new directory to be used for creating profiler trace files:
oracle@obi:oracle$ mkdir profiler
oracle@obi:oracle$ chmod o-rx profiler/
2. create the DIRECTORY object in the database too, and grant read/write privileges to the testing user (in our case TALEK user):
SQL> create directory profiler_dir as '/opt/oracle/profiler';
Directory created.
SQL> grant read, write on directory profiler_dir to talek;
Grant succeeded.
3. grant execute privilege for DBMS_HPROF package to the TALEK user:
SQL> grant execute on dbms_hprof to talek;
Grant succeeded.
4. connect using TALEK user and create the following package (the only difference between the first and second approach is the type of the l_count variable):
create or replace package trash is
procedure approach_1;
procedure approach_2;
end trash;
/
create or replace package body trash is
procedure approach_1 as
l_count pls_integer := 0;
begin
for i in 1..10000 loop
l_count := l_count + 1;
end loop;
dbms_output.put_line(l_count);
end;
procedure approach_2 as
l_count simple_integer := 0;
begin
for i in 1..10000 loop
l_count := l_count + 1;
end loop;
dbms_output.put_line(l_count);
end;
end trash;
/
5. Profile the approaches:
SQL> exec dbms_hprof.start_profiling(location => 'PROFILER_DIR', filename => 'test.trc');
PL/SQL procedure successfully completed
SQL> exec trash.approach_1;
PL/SQL procedure successfully completed
SQL> exec trash.approach_2;
PL/SQL procedure successfully completed
SQL> exec dbms_hprof.stop_profiling;
PL/SQL procedure successfully completed
6. Analyze the generated trace file. For this we’ll use the "plshprof" command line utility.
oracle@obi:profiler$ plshprof -output report test.trc
PLSHPROF: Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 - Production
[8 symbols processed]
[Report written to 'report.html']
Aaaaand, the WINNER is:
TALEK.TRASH.APPROACH_1 -> 5713 (microseconds)
TALEK.TRASH.APPROACH_2 -> 100706 (microseconds)
Well… this is unexpected. According to Oracle docs, the SIMPLE_INTEGER should be faster. Ok, back to official doc: "The new PL/SQL SIMPLE_INTEGER data type is a binary integer for use with native compilation which is neither null checked nor overflow checked". Ahaaa… native compilation! Let’s check this:
SQL> show parameter plsql_code_type
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
plsql_code_type string INTERPRETED
So, we have a first clue and a first conclusion. If the database doesn’t use NATIVE compilation the SIMPLE_INTEGER type is actually much slower.
Let’s switch to native compilation. This can be easily done because the "plsql_code_type" parameter is dynamic:
SQL> alter system set plsql_code_type=native scope=both;
System altered.
It is important to compile once again the package because otherwise the old PLSQL byte code will be used (you can use "alter package trash compile plsql_code_type=native;"), then repeat the profiler tests.
The new results are:
TALEK.TRASH.APPROACH_2 -> 3927 (microseconds)
TALEK.TRASH.APPROACH_1 -> 12556 (microseconds)
Now, the second approach with SIMPLE_INTEGER is much faster and, interestingly, the PLS_INTEGER approach is slightly slower on native compilation compared with the same approach on the initial PLSQL interpreted environment.
Okey, one more thing. I really enjoy using the new 11g hierarchical profiler. From my point of view is a big step forward compared with the old DBMS_PROFILER, and the provided HTML reports produced by "plshprof" are quite lovely.