Skip to main content

Performance difference in using different PLSQL numeric type.

 In most of the article on PLSQL performance it is always recommended to use PLS_INTEGER as a  numeric data-type whenever  there is any arithmetic calculation. Have you even wondered why does PLS_INTEGER perform much better when compared to other PLSQL numeric datatype ?

It is because when compared to other data-types
  1. Its value requires less storage space than other numeric data-types (represented internally as 22-byte Oracle numbers) .
  2. PLS_INTEGER operations use machine arithmetic
Here is an example that demonstrates the difference.

--Code taken from www.oracle-base.com
SET SERVEROUTPUT ON
DECLARE
  l_number1          NUMBER := 1;
  l_number2          NUMBER := 1;
  l_integer1         INTEGER := 1;
  l_integer2         INTEGER := 1;
  l_pls_integer1     PLS_INTEGER := 1;
  l_pls_integer2     PLS_INTEGER := 1;
  l_binary_integer1  BINARY_INTEGER := 1;
  l_binary_integer2  BINARY_INTEGER := 1;
  l_loops            NUMBER := 10000000;
  l_start            NUMBER;
BEGIN
  -- Time NUMBER.
  l_start := DBMS_UTILITY.get_time;
 
  FOR i IN 1 .. l_loops LOOP
    l_number1 := l_number1 + l_number2;
  END LOOP;
 
  DBMS_OUTPUT.put_line('NUMBER         : ' ||
                       (DBMS_UTILITY.get_time - l_start));

  -- Time INTEGER.
  l_start := DBMS_UTILITY.get_time;
 
  FOR i IN 1 .. l_loops LOOP
    l_integer1 := l_integer1 + l_integer2;
  END LOOP;
 
  DBMS_OUTPUT.put_line('INTEGER        : ' ||
                       (DBMS_UTILITY.get_time - l_start));

  -- Time PLS_INTEGER.
  l_start := DBMS_UTILITY.get_time;
 
  FOR i IN 1 .. l_loops LOOP
    l_pls_integer1 := l_pls_integer1 + l_pls_integer2;
  END LOOP;
 
  DBMS_OUTPUT.put_line('PLS_INTEGER    : ' ||
                       (DBMS_UTILITY.get_time - l_start));

  -- Time BINARY_INTEGER.
  l_start := DBMS_UTILITY.get_time;
 
  FOR i IN 1 .. l_loops LOOP
    l_binary_integer1 := l_binary_integer1 + l_binary_integer2;
  END LOOP;
 
  DBMS_OUTPUT.put_line('BINARY_INTEGER : ' ||
                       (DBMS_UTILITY.get_time - l_start));
END;
/





SQL> -- Oracle 8i

NUMBER         : 303
INTEGER        : 500
PLS_INTEGER    : 266
BINARY_INTEGER : 851

PL/SQL procedure successfully completed.

SQL>

SQL> -- Oracle 9i

NUMBER         : 65
INTEGER        : 100
PLS_INTEGER    : 51
BINARY_INTEGER : 128

PL/SQL procedure successfully completed.

SQL>

SQL> -- Oracle 10g

NUMBER         : 66
INTEGER        : 115
PLS_INTEGER    : 19
BINARY_INTEGER : 18

PL/SQL procedure successfully completed.

SQL>

SQL> -- Oracle 11g

NUMBER         : 49
INTEGER        : 112
PLS_INTEGER    : 17
BINARY_INTEGER : 18

PL/SQL procedure successfully completed.

SQL>

From the test results we can conclude that PLS_INTEGER has got the best performance when compared to any other numeric datatype. From 10g onwards BINARY_INTEGER also uses machine arithmetic, hence there is no comparable difference between both the data-type.

From 11g onwards, if you are compiling your PLSQL code natively there is a new data-type SIMPLE_INTEGER needs to be used.The SIMPLE_INTEGER datatype is a subtype of the PLS_INTEGER  datatype and can dramatically increase the speed of integer arithmetic in natively compiled code, but only shows marginal performance improvements in interpreted code. The following procedure compares the performance of the SIMPLE_INTEGER and PLS_INTEGER  datatypes.

CREATE OR REPLACE PROCEDURE simple_integer_test_proc AS
  l_start               NUMBER;
  l_loops               NUMBER := 10000000;
  l_pls_integer         PLS_INTEGER := 0;
  l_pls_integer_incr    PLS_INTEGER := 1;
  l_simple_integer      SIMPLE_INTEGER := 0;
  l_simple_integer_incr SIMPLE_INTEGER := 1;
BEGIN

  l_start := DBMS_UTILITY.get_time;

  FOR i IN 1 .. l_loops LOOP
    l_pls_integer := l_pls_integer + l_pls_integer_incr;
  END LOOP;

  DBMS_OUTPUT.put_line('PLS_INTEGER: ' || (DBMS_UTILITY.get_time - l_start) || ' hsecs');

  l_start := DBMS_UTILITY.get_time;

  FOR i IN 1 .. l_loops LOOP
    l_simple_integer := l_simple_integer + l_simple_integer_incr;
  END LOOP;

  DBMS_OUTPUT.put_line('SIMPLE_INTEGER: ' || (DBMS_UTILITY.get_time - l_start) || ' hsecs');


END simple_integer_test_proc;
/


Test Results :

SQL> EXEC simple_integer_test_proc;
PLS_INTEGER: 30 hsecs
SIMPLE_INTEGER: 23 hsecs


PL/SQL procedure successfully completed.

SQL> alter sessALTER SESSION SET PLSQL_CODE_TYPE=NATIVE;

SQL> ALTER SESSION SET PLSQL_CODE_TYPE=NATIVE;

Session altered.

SQL> ALTER PROCEDURE simple_integer_test_proc COMPILE;

Procedure altered.

SQL> EXEC simple_integer_test_proc;
PLS_INTEGER: 14 hsecs
SIMPLE_INTEGER: 3 hsecs


PL/SQL procedure successfully completed.

Comments


  1. too good piece of information, I had come to know about your site from my friend sajid, bangalore,i have read atleast 11 posts of yours by now, and let me tell you, your web-page gives the best and the most interesting information. This is just the kind of information that i had been looking for, i'm already your rss reader now and i would regularly watch out for the new post, once again hats off to you! Thanks a lot once again, Regards, sql and plsql

    ReplyDelete

Post a Comment

Popular posts from this blog

Check Whether File Exists on the Server Using PLSQL

There are different packages using which you can check whether a file exists on the database / application server. The different ways are 1. Using UTL_HTTP from Web Server 2. Using UTL_FILE from Database Server 3. Using DBMS_LOB from Database Server 1. You can also use UTL_HTTP package to check whether a file exists on a web server from the database. SET SERVEROUTPUT ON DECLARE   url       VARCHAR2(256) := 'http://www.oracle.com/index1.html';   username  VARCHAR2(256);   password  VARCHAR2(256);   req       UTL_HTTP.REQ;   resp      UTL_HTTP.RESP; BEGIN   req := UTL_HTTP.BEGIN_REQUEST(url);   IF (username IS NOT NULL) THEN     UTL_HTTP.SET_AUTHENTICATION(req, username, password);   END IF;   resp := UTL_HTTP.GET_RESPONSE(req);   DBMS_OUTPUT.PUT_LINE('response -->' || resp.status_code); END; / If the f...

11.2 PLSQL New Feature : How to use DBMS_PARALLEL_EXECUTE to Update Large Tables in Parallel

The DBMS_PARALLEL_EXECUTE package enables you to incrementally update the data in a large table in parallel, in two high-level steps: 1. Group sets of rows in the table into smaller chunks. 2. Apply the desired UPDATE statement to the chunks in parallel, committing each time you have finished processing a chunk. This technique is recommended whenever you are updating a lot of data. Its advantages are: o You lock only one set of rows at a time, for a relatively short time, instead of locking the entire table. o You do not lose work that has been done if something fails before the entire operation finishes. o You reduce rollback space consumption. o You improve performance Different Ways to Spilt Workload : 1. CREATE_CHUNKS_BY_NUMBER_COL: Chunks the table associated with the given task by the specified column. 2. CREATE_CHUNKS_BY_ROWID : Chunks the table associated with the given task by ROWID 3. CREATE_CHUNKS_BY_SQL : Chunks the table associated with the given task by me...

PRAGMA AUTONOMOUS_TRANSACTION with Transaction Isolation

What is PRAGMA ? PRAGMA is a language construct that specifies how a compiler (or assembler or interpreter) should process its input. PRAGMA keyword in PLSQL is used to direct compiler to work differently when compared to the normal code. Pragmas are processed at compile time, not at run time. What is AUTONOMOUS_TRANSACTION ? The AUTONOMOUS_TRANSACTION pragma changes the way a subprogram works within a transaction. A subprogram marked with this pragma can do SQL operations and commit or roll back those operations, without committing or rolling back the data in the main transaction. The statement clearly states that autonomous transaction executes independent of main transaction. The concept was crystal clear to me and I had used it extensively in designing some of the solution. Very recently a question raised in my mind. Will the changes made by autonomous transaction be visible in the main transaction ?  I didn't have an answer and hence tried to do a research. L...