Package Initilization Performance Research

1) Package Initilization Performance Research
1@@@@ Cache a whole list of values (memory table)
   You had batter exist a primary key for your test table, index by primary key
   , moreover, you had batter choose the integer as the primary key.
   such as the contents of a static, reference code lookup table.

Note:
  The version of memory table is stoped in the loaded time

    @@@Example: Prepare a emplu1 for handling exception in emplu2
                And versus emplu2 which use memory table.
    SYS@ocm> !cat tmp.sql
    CREATE OR REPLACE PACKAGE emplu1
    IS
        FUNCTION onerow
            (  emp_id_in  IN  hr.employees.employee_id%TYPE )
          RETURN hr.employees%ROWTYPE;
    END;
    /
    CREATE OR REPLACE PACKAGE BODY emplu1
    IS
        FUNCTION onerow
            (  emp_id_in  IN  hr.employees.employee_id%TYPE )
          RETURN hr.employees%ROWTYPE
        IS
           CURSOR onerow_cur IS
              SELECT *
                    FROM hr.employees
               WHERE employee_id = emp_id_in;
   
           onerow_rec   hr.employees%ROWTYPE;
   
        BEGIN   
           OPEN  onerow_cur;
           FETCH onerow_cur INTO onerow_rec;
           CLOSE onerow_cur;
           RETURN onerow_rec;
        END;
    END;
    /
    SYS@ocm> @tmp.sql
    Package created.
    Package body created.
   
   @@@Example: Cache table hr.employees to an associate array    
    calling data from the associate array.           
    SYS@ocm> !cat tmpx.sql
    CREATE OR REPLACE PACKAGE emplu2
    IS
        FUNCTION onerow
            (  emp_id_in  IN  hr.employees.employee_id%TYPE )
          RETURN hr.employees%ROWTYPE;
    END;
    /
    CREATE OR REPLACE PACKAGE BODY emplu2
    IS
        ----associate array  " array(employee_id) := hr.employees%ROWTYPE "
        TYPE tab_aat IS TABLE OF hr.employees%ROWTYPE
           INDEX BY BINARY_INTEGER;
        tab_aa    tab_aat;
   
        FUNCTION onerow
            (  emp_id_in  IN  hr.employees.employee_id%TYPE )
          RETURN hr.employees%ROWTYPE
        IS
        BEGIN
           RETURN tab_aa(emp_id_in);
        EXCEPTION
           WHEN NO_DATA_FOUND THEN
              RETURN emplu1.onerow(emp_id_in);
        END;
    BEGIN
       FOR rec IN (SELECT * FROM hr.employees)
       LOOP
          tab_aa(rec.employee_id) := rec;
       END LOOP;
    END;
    /
    SYS@ocm> @tmpx.sql
    Package created.
    Package body created.
   
   
   @@@Create a anonymous block to test.
    SYS@ocm> !cat test.sql
    DECLARE
        PROCEDURE test_memory_tab
            (  counter   IN  INTEGER
             , emp_id_in IN  hr.employees.employee_id%TYPE )
        IS
           emprec  hr.employees%ROWTYPE;
        BEGIN
           sf_timer.set_factor(counter);
           sf_timer.start_timer;
           FOR i  IN 1 .. counter
           LOOP
              emprec := emplu1.onerow(emp_id_in);
           END LOOP;
           sf_timer.show_elapsed_time('database table');
          
           sf_timer.set_factor(counter);
           sf_timer.start_timer;
           FOR i  IN 1 .. counter
           LOOP
              emprec := emplu2.onerow(emp_id_in);
           END LOOP;
           sf_timer.show_elapsed_time('memory table');
        END;
    BEGIN
      test_memory_tab(10000000, 100);
    END;
    /
    SYS@ocm> @test.sql
    database table - Elapsed CPU : 197.48 seconds. Factored: .00002 seconds.
    memory table - Elapsed CPU : 5.72 seconds. Factored: 0 seconds.
    PL/SQL procedure successfully completed.
   
Summary:
   Exactly quicker.
   emplu1 grain data from cursor, even though it could cached in Share Pool,
   so-called soft prase, still slow
   emplu2 grain data from PGA, it is faster.


2@@@@ Cache a single value, such as the name of the current user
the global variable g_user hold the value of STANDARD.USER.
If you calling the function repetitively, It would be return from
cache, so more speed then run STANDARD.USER function each time.
Use the constant is fastest.

    SYS@ocm> !cat tmp.sql
    CREATE OR REPLACE PACKAGE thisuser
    IS
       cname  CONSTANT VARCHAR2(30) := USER;
       FUNCTION name  RETURN VARCHAR2;
    END;
    /
    CREATE OR REPLACE PACKAGE BODY thisuser
    IS
       g_user  VARCHAR2(30) := USER;
       FUNCTION name RETURN VARCHAR2 IS
       BEGIN
          RETURN g_user;
       END;
    END;
    /
    SYS@ocm> @tmp.sql
    Package created.
    Package body created.

   @@@Package Constant is fastest, but danger, It is public
    SYS@ocm> !cat test_thisuser.sql
    CREATE OR REPLACE PROCEDURE test_thisuser
            (  count_in  IN  PLS_INTEGER )
    IS
       l_name  all_users.username%TYPE;
    BEGIN
       ----1. Use package function testuser.name
       sf_timer.start_timer;
       FOR i IN 1 .. count_in
       LOOP
          l_name := thisuser.name;
       END LOOP;
       sf_timer.show_elapsed_time('Packaged Function');
   
       ----2. Use the Package Constant
       sf_timer.start_timer;
       FOR i IN 1 .. count_in
       LOOP
          l_name := thisuser.cname;
       END LOOP;
       sf_timer.show_elapsed_time('Packaged Contant ');
      
       ----3. Use the built-in function STANDARD.USER
       sf_timer.start_timer;
       FOR i IN 1 .. count_in
       LOOP
          l_name := USER;
       END LOOP;
       sf_timer.show_elapsed_time('USER Function');
   
    END test_thisuser;
    /  
    BEGIN
       test_thisuser(10000000);
    END;
    /
    SYS@ocm> @test_thisuser.sql
    Procedure created.
   
    Packaged Function - Elapsed CPU : 2.03 seconds.
    Packaged Contant - Elapsed CPU : .47 seconds.
    USER Function - Elapsed CPU : 78.04 seconds.
    PL/SQL procedure successfully completed.

Summary:
   Package function is use the private variable or constant, it is more save
   , after all it would be modifed by user when constant in package header.
   At last, package function which use private variable is best, even though it
   is not fastest.

你可能感兴趣的:(table,memory)