16 Sort Progression 0 1 1 16 dbms_application_info 9 1000 1000 3 rows selected. Each session is allocated a maximum of four rows in the V$SESSION_LONGOPS virtual table for tracking long operations. Rows are identified by the combination of context and stepid. If calls to DBMS_APPLICATION_INFO.SET_SESSION_LONGOPS are made with more than four distinct combinations of context and stepid, rows will be re−used in least−recently−used order. All of the parameters except hint correspond directly to like−named columns in the V$SESSION_LONGOPS virtual table. While there are no restrictions on values stored in these columns, Oracle makes the following suggestions as a way of organizing information about the progress of long running operations: stepsofar If the long−running operation consists of distinct individual steps, the amount of work which has been done so far for this step. steptotal If the long−running operation consists of distinct individual steps, the total amount of work expected to be done in this step. sofar The amount of work that has been done so far. totalwork The total amount of work expected to be done in this long−running operation. application_data_1, application_data_2, application_data_3 Any numbers the client wishes to store. Also note that all parameters to SET_SESSION_LONGOPS (except hint) default to zero. This means that calls to the procedure need not specify values for all parameters, which is convenient in the case of such a long parameter list. However, it also means that any unspecified parameters in a call to SET_SESSION_LONGOPS will have their corresponding columns in V$SESSION_LONGOPS set to zero for that row after the call, which may not be the desired behavior. 7.1 Getting Started with DBMS_APPLICATION_INFO 7.3 DBMS_APPLICATION_INFO Examples Copyright (c) 2000 O'Reilly & Associates. All rights reserved. [Appendix A] What's on the Companion Disk? 7.2.6 The DBMS_APPLICATION_INFO.SET_SESSION_LONGOPSprocedure 376 Chapter 7 Defining an Application Profile 7.3 DBMS_APPLICATION_INFO Examples Oracle suggests that one way to extend DBMS_APPLICATION_INFO is to capture session performance statistics as part of the process of registering modules and actions. To demonstrate how this might be done, I have created a package called register_app. 7.3.1 About the register_app Package The programs in register_app are very similar to those in DBMS_APPLICATION_INFO. Here is the package specification: /* Filename on companion disk: register.sql */* CREATE OR REPLACE PACKAGE register_app IS /* || Enhances DBMS_APPLICATION_INFO by capturing performance || statistics when module, action, or client_info are set. || || Statistics may be displayed in SQL*Plus for tracking and || debugging purposes. A useful enhancement would be to || extend this idea to a logging feature, so stats are logged || to a table for analysis. || || Also enforces requirement that a module be registered before || an action can be registered. || || Author: John Beresniewicz, Savant Corp || Created: 09/01/97 || || Compilation Requirements: || || SELECT on SYS.V_$MYSTAT || SELECT on SYS.V_$STATNAME || || Execution Requirements: || || */ /* registers the application module */ PROCEDURE module (module_name_IN IN VARCHAR2 ,action_name_IN IN VARCHAR2 DEFAULT 'BEGIN'); /* registers the action within module */ PROCEDURE action(action_name_IN IN VARCHAR2); /* registers additional application client information */ PROCEDURE client_info(client_info_IN IN VARCHAR2); /* returns the currently registered module */ FUNCTION current_module RETURN VARCHAR2; 377 /* returns the currently registered action */ FUNCTION current_action RETURN VARCHAR2; /* returns the currently registered client info */ FUNCTION current_client_info RETURN VARCHAR2; /* sets stat display for SQL*Plus ON (TRUE) or OFF (FALSE) */ PROCEDURE set_display_TF(display_ON_TF_IN IN BOOLEAN); END register_app; The module, action, and client_info programs of register_app correspond directly to the SET_MODULE, SET_ACTION, and SET_CLIENT_INFO programs of DBMS_APPLICATION_INFO; indeed, each of these programs eventually calls its counterpart. The difference is that the programs in register_app first collect session performance information and store it in a private package global record, before calling the appropriate DBMS_APPLICATION_INFO program. 7.3.2 The action Procedure Here is the body of the action procedure: /* Filename on companion disk: register.sql */* PROCEDURE action(action_name_IN IN VARCHAR2) IS BEGIN /* || raise error if trying to register an action when module || has not been registered */ IF current_module IS NULL AND action_name_IN IS NOT NULL THEN RAISE_APPLICATION_ERROR(−20001, 'Module not registered'); ELSE set_stats; SYS.DBMS_APPLICATION_INFO.SET_ACTION(action_name_IN); END IF; END action; Note that the action procedure is written to enforce the rule that an action can be registered only if a module has previously been registered. The action procedure also calls a procedure called set_stats. This procedure is private to the package, and does the work of collecting and saving resource statistics whenever new module, action, or client information is registered. 7.3.3 The set_stats Procedure The set_stats procedure loads session performance information into a private global record named stat_rec. Here are the definitions of stat_rec and the PL/SQL record type on which it is based: /* record type to hold performance stats */ TYPE stat_rectype IS RECORD (timer_hsecs NUMBER := 0 ,logical_rds NUMBER := 0 ,physical_rds NUMBER := 0 ); /* private global to hold stats at begin of each module/action */ stat_rec stat_rectype; Now let's take a look at the set_stats procedure: [Appendix A] What's on the Companion Disk? 7.3.2 The action Procedure 378 /* Filename on companion disk: register.sql/* || Gets current performance stats from V$MYSTAT and || sets the global record stat_rec. If display_TF_ is TRUE || then uses DBMS_OUTPUT to display the stat differences || since last call to set_stats. */ PROCEDURE set_stats IS temp_statrec stat_rectype; diff_statrec stat_rectype; /* || Embedded inline function to retrieve stats by name || from V$MYSTAT. */ FUNCTION get_stat(statname_IN IN VARCHAR2) RETURN NUMBER IS /* return value −9999 indicates problem */ temp_stat_value NUMBER := −9999; /* cursor retrieves stat value by name */ CURSOR stat_val_cur(statname VARCHAR2) IS SELECT value FROM sys.v_$mystat S ,sys.v_$statname N WHERE S.statistic# = N.statistic# AND N.name = statname; BEGIN OPEN stat_val_cur(statname_IN); FETCH stat_val_cur INTO temp_stat_value; CLOSE stat_val_cur; RETURN temp_stat_value; EXCEPTION WHEN OTHERS THEN IF stat_val_cur%ISOPEN THEN CLOSE stat_val_cur; END IF; RETURN temp_stat_value; END get_stat; BEGIN /* || load current values for performance statistics */ temp_statrec.timer_hsecs := DBMS_UTILITY.GET_TIME; temp_statrec.logical_rds := get_stat('session logical reads'); temp_statrec.physical_rds := get_stat('physical reads'); /* || calculate diffs between current and previous stats */ diff_statrec.timer_hsecs := temp_statrec.timer_hsecs − stat_rec.timer_hsecs; diff_statrec.logical_rds := temp_statrec.logical_rds − stat_rec.logical_rds; diff_statrec.physical_rds := temp_statrec.physical_rds − stat_rec.physical_rds; [Appendix A] What's on the Companion Disk? 7.3.2 The action Procedure 379 /* || Both current module AND client info NULL indicates || initialization for session and stats should not be displayed. */ IF display_TF AND (current_module IS NOT NULL OR current_client_info IS NOT NULL) THEN DBMS_OUTPUT.PUT_LINE('Module: '||current_module); DBMS_OUTPUT.PUT_LINE('Action: '||current_action); DBMS_OUTPUT.PUT_LINE('Client Info: '||current_client_info); DBMS_OUTPUT.PUT_LINE('Stats: '|| 'elapsed secs:'|| TO_CHAR(ROUND(diff_statrec.timer_hsecs/100,2))|| ', physical reads: '||TO_CHAR(diff_statrec.physical_rds)|| ', logical reads: '||TO_CHAR(diff_statrec.logical_rds) ); END IF; /* OK, now initialize stat_rec to current values */ stat_rec := temp_statrec; END set_stats; The set_stats procedure logic is relatively straightforward: 1. Current values for the session performance statistics are gathered and the previous values (stored in the private global record stat_rec) are subtracted from them. These differences represent the changes in statistics since the last call to set_stats and are held in the record diff_statrec. Note that this works even for the initial call to set_stats because the declaration of stat_rectype assigns a default value of zero to all fields. Thus, on the first call, stat_rec will be initialized with zeros and diff_statrec will contain the current statistics. 2. The difference performance statistics are displayed using DBMS_OUTPUT if the display flag is set and this is not the first call to register application information. 3. Current values of the session performance statistics are saved in stat_rec for the next call to set_stats. Exercise for the reader: Enhance the register_app package to log module and action performance statistics to a table for resource accounting. Be sure to allow for tracking by username and session. 7.3.4 The Information Procedures The register_app package also contains three functions that return the currently registered information for the session. These functions invoke the DBMS_APPLICATION_INFO procedures READ_MODULE and READ_CLIENT_INFO and return the respective information. Procedures that return data in OUT parameters can often be encapsulated usefully with functions in this way. This promotes more terse and readable code, as illustrated by the following code excerpts from the register_app package: /* Filename on companion disk: register.sql */* /* returns the currently registered module */ FUNCTION current_module RETURN VARCHAR2; /* returns the currently registered client info */ FUNCTION current_client_info RETURN VARCHAR2; PROCEDURE set_stats [Appendix A] What's on the Companion Disk? 7.3.4 The Information Procedures 380 . V$SESSION_LONGOPS virtual table. While there are no restrictions on values stored in these columns, Oracle makes the following suggestions as a way of organizing information about the progress of. DBMS_APPLICATION_INFO.SET_SESSION_LONGOPSprocedure 376 Chapter 7 Defining an Application Profile 7.3 DBMS_APPLICATION_INFO Examples Oracle suggests that one way to extend DBMS_APPLICATION_INFO is to capture session performance statistics