Download presentation
Presentation is loading. Please wait.
1
Best Practices on PL/SQL & SQL Tuning
fuyuncat
2
PLSQL Basic Best Practices Tuning ways
3
PLSQL Basic Best Practices Tuning ways
4
What is PLSQL? • What is PL/SQL?
– Oracle’s procedural extension to SQL. – Supplements SQL with several high-level programming features such as block structure, variables, constants and types, the assignment statement, conditional statements, loops, customized error handling, and structured data. • Properties: – Proprietary Oracle language – Tightly integrated with SQL – Can increase performance by grouping statements into blocks of code – Portable to any Oracle platform – Used within many Oracle tools – Stored program units can increase security
5
Capabilities & Restrictions
Capabilities – PL/SQL can call: DML statements standard SQL functions other PL/SQL programs Restrictions PL/SQL programs cannot directly contain DDL statements
6
Program Structure PL/SQL like many high-level languages, groups its statement into units called blocks. Blocks can be unnamed (anonymous blocks) or named (subprograms) The subprograms can be either functions or procedures.
7
PL/SQL Program Structure
PL/SQL is a block-structured language A PL/SQL block consists of 3 parts DECLARE -- Declarative variables; constants; cursors; BEGIN -- Executable PL/SQL and SQL DML statements; EXCEPTION -- Exception Handling exception handlers; END;
8
Anonymous Block An anonymous block has the following structure declare
-- Declaration Section -- Data, subprogram declarations begin -- Executable Section null; -- Program Statements exception -- Exception Section -- Exception handlers when others then null; -- Default handler end;
9
Stored Procedures and Functions
increased performance shared code lowered maintenance cost portability security
10
Packages A package is a group of related PL/SQL objects (variables, constants, types, and cursors), procedures, and functions that is stored in the DB. A package definition contains of two parts: the package specification and the package body.
11
Tools for PL/SQL Development
SQL*Plus is the traditional tool Included with all Oracle database products Third Party Tools PLSQL Developer Toad
12
PL/SQL Storage & Execution
On the server Triggers Stored procedures Stored functions On the client Anonymous blocks Execution All execute on the server
13
Executing PL/SQL
14
Parsing & Compiling PL/SQL
15
PLSQL Basic Best Practices Tuning ways
16
Best Practices After completing this lesson, you should be able to do the following: Best Practice for Coding Style and Conventions Best Practice for Variable and Data Structures Best Practice for Control Structures Best Practice for Exception Handling Best Practice for Writing SQL in PL/SQL Best Practice for program construction Best Practice for Using Packages
17
Best Practice for Coding Style and Convention
Setup Coding Standard Benefits – Well-formed coding can minimize the cost of maintenance, enhancement, review E.g. REPLACE PACKAGE CROSS_CHARGE IS PROCEDURE SET_CROSS_CHARGE_DEPARTMENT (DEPT IN VARCHAR2); FUNCTION CROSS_CHARGE_VALUE (VALUE IN NUMBER) RETURN NUMBER; END CROSS_CHARGE; / The above coding has some problems such as 1) All uppercase 2) No indentation and 3) No comment
18
Best Practice for Coding Style and Convention
Standardize the names of program elements Benefits – Concentrate on program development and new developer can follow the standard easily E.g. Use prefix or suffix to identify the type of the variable such as a. g_ for global variable b. T_ for type objects such as collections, objects, records, ref cursors etc c. Use same case convention for user-defined types such as all uppercase d. Keep variable name short (maximum 30 characters) and self-explained as readable format e. Organize like items together such as record variable declaration, constant declaration
19
Best Practice for Coding Style and Convention
Standardize module and program headers Benefits – Minimize the code change effort and maintenance effort E.g. • Version, author and copyright information • Access Information – where is the program stored? Database (which schema), File (Which file and which disk) • Objective – What is the objective of this program do? • Dependency – Any dependency to run this program? Any dependency to other program? • Algorithm – Is there any special algorithm used in the program? If so, specify them in details • Modification History – By whom? When? And for what purpose to modify? • Exceptions – What errors might be raised by the program?
20
Best Practice for Coding Style and Convention
Labeling by block and loop label Benefit – Improve code readability E.g. CREATE OR REPLACE PROCEDURE LOOPING IS BEGIN <<BEGIN_LOOPING>> DECLARE a number; b number; BEGIN <<FIRST_LOOPING>> FOR I in LOOP a := a + i; <<SECOND_LOOPING>> ….
21
Best Practice for Coding Style and Convention
Use parentheses for complex expressions Benefit – Easier to understand the logic and intent of complex expressions E.g. By using the parentheses, we can easily express the sequence of the operation in the expression. For example 7 – T * 3 MOD 4 It is better to add parentheses to reduce the ambiguous. For 7 – ((T * 3) MOD 4)
22
Best Practice for Coding Style and Convention
Using file extension to self-explain purpose of code Benefit – Easier for developers to work with and maintain the code E.g we should use the OS file extension carefully to differentiate different kinds of coding. For example a. Package Specification - .pks b. Package Body - .pkb c. Package Specification and body - .pkg d. Procedure - .pro e. Function - .fun f. Table Creation script - .tab g. Synonym Creation Script - .syn h. Index Creation Script - .ind
23
Best Practice for Variable and Data Structures
Use CONSTANT to declare variable which won’t change its value BENEFIT – Improve code readability and reduce the chance of careless modification Put variable initialization by complex expression in execution section BENEFIT – Reduce the maintenance effort and help on logic debugging E.g CREATE OR REPLACE PROCEDURE get_today_survey_statistics IS Avoid => all_survey_name survey.survey_name%TYPE := get_today_survey(SYSDATE); BEGIN …
24
Best Practice for Variable and Data Structures
When program terminates, clean up all structure gracefully BENEFIT – Reduce the risk of memory leakage, unclosed file and make sure gracefully exit of program E.g. CREATE OR REPLACE PROCEDURE save_survey IS fid UTL_FILE.file_type; PROCEDURE cleanup IS BEGIN UTL_FILE.FCLOSE(fid); END; fid := UTL_FILE.FOPEN(‘/tmp’, ‘save_survey.txt’, ‘A’); … cleanup; EXCEPTION WHEN NO_DATA_FOUND THEN
25
Best Practice for Variable and Data Structures
Be careful on the implicit data type conversion BENEFIT – The behavior of data type conversion is predictable Do NOT access package variable directly BENEFIT – Inhibit the illegal access to package variable which may affect the package logic Declare literal constants and TYPE definition in package BENEFIT – Easier declaration management and improve readability and maintainability of code
26
Best Practice for Control Structures
Use ELSIF for mutually exclusive condition test BENEFIT – Improves code readability and more efficient for mutually exclusive condition test Use IF…ELSIF to test single, simple condition BENEFIT – Improve code readability and maintainability E.g. IF conA AND NOT ( conB OR conC) THEN action1; ELSIF conA AND (conB OR conC) THEN action2; ELSIF NOT conA and conD THEN action3; END IF; =>> Change to Left IF conA THEN IF (conB OR conC) THEN action2; ELSE action1; END IF; ELSIF conD THEN action3;
27
Best Practice for Control Structures
Do NOT use EXIT or RETURN within WHILE and FOR loop BENEFIT – Easier for code debugging BEGIN FOR I in LOOP IF survey_date is NOT NULL then return survey_date; END IF; END LOOP; RAISE NO_SURVEY; EXCEPTION WHEN NO_SURVEY THEN RETURN NULL; END; BEGIN FOR I in LOOP IF survey_date is NOT NULL then when_survey := survey_date; END IF; END LOOP; IF when_survey is NULL then return NULL; ELSIF return when_survey; END;
28
Best Practice for Control Structures
Use single EXIT in simple loop BENEFIT – Important in complex loop and easier on debug and improve code readability LOOP IF birthday IS NULL THEN present := FALSE; EXIT; ELSIF survey_date IS NULL THEN ELSIF survey_date = birthday THEN present := TRUE; END IF; END LOOP; LOOP IF birthday IS NULL THEN present := FALSE; EXIT_LOOP := FALSE; ELSIF survey_date IS NULL THEN ELSIF survey_date = birthday THEN present := TRUE; EXIT_LOOP := TRUE; END IF; EXIT WHEN EXIT_LOOP; END LOOP;
29
Best Practice for Control Structures
Move static expression outside loops BENEFIT – Improve code efficiency DECLARE survey_customer survey.survey_name%TYPE; CURSOR survey_review IS SELECT survey_name, comment from survey where SURVEY_DATE = SYSDATE; BEGIN FOR rec IN survey_review LOOP IF LENGTH(survey_review.comment) > 100 THEN survey_review.comment := substr(survey_review.comment, 1, 100); survey_customer := survey_name; END IF; END LOOP; END; DECLARE CURSOR survey_review IS SELECT substr(comment, 1, 100) from survey where SURVEY_DATE = SYSDATE; BEGIN FOR rec IN survey_review LOOP survey.survey_customer := survey_name; END LOOP; END;
30
Best Practice for Exception Handling
Do NOT use parameter passing as error handling mechanism BENEFIT – Simple code and improve readability E.g. CREATE OR REPLACE FUNCTION survey_analysis (s_date IN DATE, error OUT INTEGER) RETURN INTEGER; In the above case, the user of function survey_analysis must check the OUT parameter (error) before they can use the return value.
31
Best Practice for Exception Handling
Raise exception for ERROR only BENEFIT – Improve readability, debug and maintenance E.g. CREATE OR REPLACE FUNCTION first_long_comment (s_date IN DATE) RETURN survey.survey_name%TYPE; IS CURSOR check_comment SELECT comment FROM survey WHERE length(comment) > 100 and survey_date = s_date; BEGIN IF s_date IS NULL THEN raise quit_function; END IF; FOR I IN check_comment LOOP; RETURN check_comment.comment; END LOOP; EXCEPTION WHEN quit_function THEN RETURN NULL; END;
32
Best Practice for Exception Handling
Do NOT overload an exception for multiple errors BENEFIT – Clear-cut definition for different exception handling and easier to debug Use WHEN OTHERS only for unknown exceptions BENEFIT – Improve readability and easier to maintain Document all package exceptions in package specification BENEFIT – Improve readability
33
Best Practice for Writing SQL in PL/SQL
Use incremental COMMITs to avoid rollback segment errors when changing large number of rows BENEFIT – Make the code more robust Use autonomous transactions to isolate the effect of COMMITs and ROLLBACKs BENEFIT – The autonomous transaction can help to write log to database without affect the main transaction Use function instead of anonymous statement for single-row SQL BENEFIT – Better sharing, easier maintenance, and better exception handling
34
Best Practice for Writing SQL in PL/SQL
Use package to hold multi-row query cursor for sharing BENEFIT – Reduce maintenance effort and easy for new user to use pre-defined query Fetch cursor data into records instead of variable BENEFIT – Self-maintenance coding Do NOT use cursor COUNT function unless it is necessary to know number of occurrence BENEFIT – Better performance and improve readability Do NOT use cursor FOR loop for single-row query BENEFIT – Improve code efficiency Use one single SQL statement to replace FOR Loop BENEFIT – Improve performance
35
Best Practice for Writing SQL in PL/SQL
Specify columns in SELECT FOR UPDATE statement BENEFIT – Keep minimum number of locks and improve readability E.g. CURSOR change_comment_cur IS SELECT survey_name, comment FROM survey where length(comment) > 100 FOR UPDATE OF COMMENT; Use RETURNING clause for retrieving multiple rows BENEFIT – Improve performance and less coding
36
Best Practice for Writing SQL in PL/SQL
Use bulk binding for large query BENEFIT – Improve performance Put INSERT, UPDATE, DELETE statement inside procedure calls BENEFIT – Standardize DML statement and exception handling for DML statement
37
Best Practice for Writing SQL in PL/SQL
Reference cursor attributes immediately after executing SQL operation BENEFIT – Unexpected behavior and difficulty to debug DECLARE PROCEDURE display_longest_comment IS longest_comment survey.comment%TYPE; BEGIN SELECT max(length(comment)) into longest_comment where rownum = 1; END; UPDATE survey SET comment = substr(I.comment, 1, 100) where length(comment) > 100; display_longest_comment; DBMS_OUTPUT.PUT_LINE(‘The number of modified comment is ‘ || SQL%ROWCOUNT || ‘!’); Use FORALL to improve performance of collection-based DML BENEFIT – Improve performance
38
Best Practice for program construction
Use NOCOPY to minimize OUT and IN OUT parameter overhead BENEFIT – Improve performance Limit functions to single RETURN BENEFIT – Reduce error and easier to debug Avoid to use IN OUT and OUT parameter in function BENEFIT – Easier to reuse and easier to debug Do NOT return NULL from Boolean function BENEFIT – Easier to reuse
39
Best Practice for Using Packages
Build package specification before package body BENEFIT – Minimize the cost of code maintenance Write flexible package BENEFIT – Easier to reuse CREATE OR REPLACE PACKAGE BODY survey_statistics IS PROCEDURE analyze_rating (s_date IN DATE, error_log_mode BOOLEAN); … END; Build tracing facility for package status BENEFIT – Easier to debug
40
Best Practice for Using Packages
Cache data in package body BENEFIT – Improve performance E.g. CREATE OR REPLACE PACKAGE getuser IS name CONSTANT VARCHAR2(100) := USER; END getuser; Separate package specification from body to different source code files BENEFIT – Reduce cost of maintenance
41
Best Practice for Using Packages
Use package header to describe element definition in the package BENEFIT – Reduce cost of code maintenance E.g. CREATE OR REPLACE PACKAGE BODY <package_name> IS /* PACKAGE HEADER */ /* Constant declaration */ /* Variables declaration */ /* Exceptions declaration */ /* Types declaration */ /* Private program */ /* Public program */ End <name>;
42
PLSQL Basic Best Practices Tuning ways
43
Tuning PL/SQL code Tune your PL/SQL code to meet performance standards
Use the RETURNING clause Understand bulk binds Rephrase conditional statements Identify data type and constraint issues Use dynamic SQL Compare SQL to PL/SQL Trace PL/SQL code
44
The RETURNING Clause Include the RETURNING clause with an INSERT, UPDATE, and DELETE to return column values PROCEDURE update_salary (p_emp_id NUMBER) IS v_name VARCHAR2(15); v_new_sal NUMBER; BEGIN UPDATE emp SET sal = sal * 1.1 WHERE empno = p_emp_id RETURNING ename, sal INTO v_name, v_new_sal; END update_salary;
45
Bulk Binding Context Switching between SQL engine and PL/SQL engine
Reducing context switching can help performance Nested Table, VARRAY and index-by table are most suffered by context switching
46
Bulk Binding Bind whole arrays of values at once, rather than loop to perform fetch, insert, update, and delete on multiple rows Keywords to support bulk binding FORALL instructs the PL/SQL engine to bulk-bind input collections before sending them to the SQL engine FORALL index IN lower_bound..upper_bound Sql_statement; BULK COLLECT instructs the SQL engine to bulk bind output collections before returning them to the PL/SQL engine … BULK COLLECT INTO collection_name[, collection_name] …
47
Bulk Binding Example DECLARE TYPE Numlist IS VARRAY (100) OF NUMBER;
Id NUMLIST := NUMLIST(7902, 7698, 7839); BEGIN FORALL I IN Id.FIRST..Id.LAST – bulk-bind the VARRAY UPDATE emp SET sal = 1.1 * sal WHERE mgr = Id(I); END; /
48
Bulk Binding Example DECLARE TYPE Emplist IS VARRAY(100) OF NUMBER;
TYPE Numlist IS TABLE OF emp.sal%TYPE; Empids EMPLIST:= EMPLIST(7369, 7499, 7521, 7566, 7654, 7698); Bonlist NUMLIST; BEGIN FORALL I IN Empids.FIRST..Empids.LAST UPDATE emp SET comm = 0.1 * sal WHERE empno = Empids(I) RETURNING sal BULK COLLECT INTO Bonlist; END; /
49
Rephrase Conditional Control Statements
In logical expressions, the PL/SQL stops evaluating the expression as soon as the result is determined Scenario 1: IF TRUE|FALSE OR (comm IS NULL) THEN .. END IF; Scenario 2: IF credit_ok(cust_id) AND (loan < 5000) THEN
50
Avoid Implicit Data Type Conversion
PL/SQL performs implicit conversion between structurally different data types Implicit conversion is common with NUMBER data types Example: When assigning a pls_integer variable to a number variable
51
Use PLS_INTEGER Data Type for Integers
Use PLS_INTEGER when dealing with integer data: It is an efficient data type for integer variables It requires less storage than INTEGER or NUMBER Its operations use machine arithmetic, which is faster than library arithmetic
52
Use Index-by Tables of Records and Objects
Convert a series of related index-by tables or scalars to tables of records. Benefits include: Better performance: Decreases the number of index-by table operations such as lookup, insert, and so on Improved memory utilization: Fewer index-by tables results in improved memory utilization
53
Use User-Defined Records as Arguments
Passing records as arguments DECLARE TYPE EmpRec IS RECORD ( emp_id emp.empno%TYPE, last_name VARCHAR2(10), job_title VARCHAR2(15), salary NUMBER(7,2)); … PROCEDURE raise_salary (emp_info EmpRec) Referencing record field names in function calls that return a record … := function_name(parameters).field_name
54
Use Index-by Tables as Arguments
Example PACKAGE emp_actions IS TYPE EnameTabTyp IS TABLE OF emp.ename%TYPE INDEX BY BINARY_INTEGER; TYPE SalTabTyp IS TABLE OF emp.sal%TYPE INDEX BY BINARY_INTEGER; … PROCEDURE hire_batch(ename_tab IN EnameTabTyp, sal_tab IN SalTabTyp, ….); PROCEDURE log_names (ename_tab IN EnameTabTyp); END emp_actions;
55
The NOT NULL Constraint
PROCEDURE calc_m IS m NUMBER NOT NULL := 0; a NUMBER; b NUMBER; BEGIN … m := a + b; END; PROCEDURE calc_m IS m NUMBER; -- no constraint a NUMBER; b NUMBER; BEGIN … m := a + b; IF m IS NULL THEN -- raise error END IF; END;
56
The NOT NULL Constraint
Rules for NULLs: Comparisons involving NULLS always yield NULL Applying the logical operator NOT to a NULL yields NULL In conditional control statements, if the condition yields NULL, its associated sequence of statements is not executed … X := 5; Y := NULL; If x != y THEN -- yields NULL, not TRUE sequence_of_statements; -- not executed END IF;
57
The NOT NULL Constraint
PL/SQL treats a zero-length string like a NULL value Null_string := MY_FUNCTION(‘’); Zip_code := SUBSTR(address, 25, 0); Valid := (name != ‘’); The concatenation operator ignores NULL values ‘apple’ || NULL || NULL || ‘sauce’ -> applesauce
58
Native Dynamic SQL Provides native support for dynamic SQL directly in the PL/SQL language Provides the ability to dynamically execute SQL statements whose complete text is unknown until execution time Is used to place dynamic SQL statements directly into PL/SQL blocks Uses these statements to support this feature: EXECUTE IMMEIDATE OPEN FETCH CLOSE
59
Native Dynamic SQL Example CREATE PROCEDURE insert_into_table
(table_name VARCHAR2, deptnumber NUMBER, deptname VARCHAR2, location VARCHAR2) IS stmt_str VARCHAR2(200); BEGIN stmt_str := ‘INSERT INTO ‘ || table_name || ‘ values (:deptno, :dname, :loc)’; EXECUTE IMMEDIATE stmt_str USING Deptnumber, deptname, location; END insert_into_table;
60
Advantage of Native Dynamic SQL Over dbms_sql
Is easier to use than dbms_sql and requires less code Enhances performance because the PL/SQL interpreter provides native support for it Support all types supported by static SQL in PL/SQL, including user-defined types Can fetch rows directly into PL/SQL records
61
SQL Versus PL/SQL SQL processes sets of data as a group rather than as individual units PL/SQL offers flow-control statements that are absent in SQL Use PL/SQL with caution when Performing high volume inserts Using user-defined PL/SQL functions Using external procedure calls Using utl_file package
62
SQL Versus PL/SQL Some simple set processing is markedly faster than the equivalent PL/SQL BEGIN INSERT INTO dept2 SELECT deptno, ename FROM big_emp; END; Avoid using procedural code when it may be better to use SQL … FOR I IN LOOP counter := counter + 1; SELECT deptno, ename INTO v_number, v_name FROM big_emp WHERE empno = counter; INSERT INTO dept2 VALUES(v_number, v_name); END LOOP;…
63
Tracing PL/SQL Execution
Tracing PL/SQL execution provides you with a better understanding of the program execution path, and is possible by using the dbms_trace package Enable specific subprograms for tracing (optional) Start tracing session (Trace Data) Run application to be traced Stop tracing session
64
Tracing PL/SQL Execution
Tracing PL/SQL execution provides you with a better understanding of the program execution path, and is possible by using the dbms_trace package Enable specific subprograms for tracing (optional) Start tracing session (Trace Data) Run application to be traced Stop tracing session
65
Tracing PL/SQL Execution
The dbms_trace package contains: set_plsql_trace (trace_level INTEGER) clear_plsql_trace plsql_trace_version
66
Tracing PL/SQL Execution
Using set_plsql_trace, select a trace level to identify how to trace calls, exceptions, SQL, and lines of code Trace level constants: trace_all_calls trace_enabled_calls trace_all_sql trace_enabled_sql trace_all_exceptions trace_enabled_exceptions trace_enabled_lines trace_all_lines trace_stop trace_pause trace_resume
67
Tracing PL/SQL : Steps Enable specific program units for trace data collection Use dbms_trace.set_plsql_trace to identify a trace level Start tracing by running your PL/SQL code Use dbms_trace.clear_plsql_trace to stop tracing data Read and interpret the trace information
68
Step 1 : Enable Specific Subprograms
Enable specific subprograms with one of two methods: Enable a subprogram by compiling it with the debug option: ALTER SESSION SET PLSQL_DEBUG=true; CREATE OR REPLACE …. Recompile a specific subprogram with the debug option: ALTER [PROCEDURE | FUNCTION | PACKAGE BODY] <subprogram-name> COMPILE DEBUG;
69
Steps 2 and 3 : Identify a Trace Level and Start Tracing
Identify the trace level by using dbms_trace.set_plsql_trace EXECUTE DBMS_TRACE.SET_PLSQL_TRACE – (tracelevel1 + tracelevel2 ….) Execute the code to be traced EXECUTE my_program
70
Step 4 : Turn Off Tracing Remember to turn tracing off by using the procedure dbms_trace.clear_plsql_trace EXECUTE DBMS_TRACE.CLEAR_PLSQL_TRACE
71
Step 5 : Examine the Trace Information
Examine the trace information in either the data dictionary or in trace files: Oracle8i, release uses dictionary views Prior to release trace files are generated Call tracing writes out he program unit type, name, and stack depth Exception tracing writes out the line number
72
Plsql_trace_runs and plsql_trace_events
Oracle8i, release writes trace information to dictiary views plsql_trace_runs dictionary view Plsql_trace_events dictionary view Run the tracetab.sql script to create the dictionary views Need privileges to view the trace information in the dictionary views
73
Plsql_trace_runs and plsql_trace_events
SELECT proc_name, proc_line, event_proc_name, event_comment FROM plsql_trace_events WHERE event_proc_name = ‘RAISE_SAL’ OR PROC_NAME = ‘RAISE_SAL’; PROC_NAME PROC_LINE EVENT_PROC_NAME EVENT_COMMENT RAISE_SAL Procedure Call RAISE_SAL Exception raised RAISE_SAL Exception handled 0 RAISE_SAL Return from procedure call
74
Execution Plan Explain Plan Third Party Tools SQL Trace
75
Other practices for SQL Tuning
SQL Trace & Tkprof DBMS_Profile AUTO Trace Set event
76
Q & A
77
Thanks! fuyuncat
Similar presentations
© 2025 SlidePlayer.com Inc.
All rights reserved.