top of page

Tags

Archive

Oracle Sql & Plsql performance Tips

I'm this blog post I will outline some real time use cases related to performance tuning on oracle sql and plsql. šŸ’”šŸ’»šŸš€


Below are examples demonstrating the best practices for Oracle SQL & PL/SQL performance tuning.


1. SQL Performance Tuning Examples

a. Avoid SELECT *Ā and Fetch Only Required Columns


āŒ Bad Practice

SELECT * FROM employees WHERE department_id = 10;


āœ… Optimized Version

SELECT employee_id, first_name, salary FROM employees WHERE department_id = 10;


Why?Ā Fetching only necessary columns reduces memory usage and improves performance.


b. Use EXISTSĀ Instead of IN


āŒ Bad PracticeĀ (Subquery with IN)

SELECT * FROM employees WHERE department_id IN (SELECT department_id FROM departments WHERE location_id = 100);


āœ… Optimized VersionĀ (EXISTSĀ is usually faster)

SELECT * FROM employees e WHERE EXISTS ( SELECT 1 FROM departments d WHERE d.department_id = e.department_id AND d.location_id = 100 );


Why?Ā EXISTSĀ stops searching as soon as it finds a match, whereas INĀ may check all rows.


c. Use Proper Indexing


āœ… Creating an Index on Frequently Queried Columns

CREATE INDEX idx_emp_dept ON employees(department_id);


āœ… Using a Composite Index for Multi-Column Queries

CREATE INDEX idx_emp_name_dept ON employees(last_name, department_id);


Why?Ā Indexes speed up lookups but should be used carefully, as too many indexes can slow down INSERT/UPDATE/DELETE.


d. Avoid Functions on Indexed Columns


āŒ Bad PracticeĀ (Function on an Indexed Column Prevents Index Usage)

SELECT * FROM employees WHERE UPPER(last_name) = 'SMITH';


āœ… Optimized Version (Function-Based Index)

CREATE INDEX idx_upper_lastname ON employees(UPPER(last_name)); SELECT * FROM employees WHERE UPPER(last_name) = 'SMITH';


Why?Ā Normal indexes don’t work when a function is applied to a column, so a function-based index is required.


e. Use UNION ALLĀ Instead of UNION

āŒ Bad PracticeĀ (Using UNIONĀ unnecessarily)

SELECT first_name FROM employees WHERE department_id = 10 UNION SELECT first_name FROM employees WHERE department_id = 20;


āœ… Optimized Version (UNION ALLĀ is Faster)

SELECT first_name FROM employees WHERE department_id = 10 UNION ALL SELECT first_name FROM employees WHERE department_id = 20;


Why?Ā UNIONĀ removes duplicates, which requires sorting. If duplicates are not a concern, UNION ALLĀ is much faster.


f. Analyzing Execution Plan

āœ… Check Execution Plan for Query Performance

EXPLAIN PLAN FOR SELECT FROM employees WHERE department_id = 10; SELECT FROM TABLE(DBMS_XPLAN.DISPLAY);


Why?Ā Helps understand how Oracle processes queries and find bottlenecks.


2. PL/SQL Performance Tuning Examples


a. Use BULK COLLECTĀ Instead of Row-by-Row Fetching


āŒ Bad Practice (Row-by-Row Processing)

DECLARE CURSOR emp_cursor IS SELECT employee_id, salary FROM employees; v_employee_id employees.employee_id%TYPE; v_salary employees.salary%TYPE;

BEGIN

FOR emp_rec IN emp_cursor LOOP -- Process each record one by one DBMS_OUTPUT.PUT_LINE(emp_rec.employee_id || ' - ' || emp_rec.salary);

END LOOP;

END;


āœ… Optimized Version Using BULK COLLECT


DECLARE TYPE emp_table IS TABLE OF employees%ROWTYPE; emp_list emp_table; BEGIN

SELECT * BULK COLLECT INTO emp_list FROM employees; FOR i IN emp_list.FIRST .. emp_list.LAST LOOP DBMS_OUTPUT.PUT_LINE(emp_list(i).employee_id || ' - ' || emp_list(i).salary); END LOOP; END;


Why?Ā BULK COLLECTĀ reduces context switching between PL/SQL and SQL engines, improving performance.


b. Use FORALLĀ Instead of FORĀ Loop for DML Operations

āŒ Bad Practice (Row-by-Row Insert - Slow)

DECLARE

CURSOR emp_cursor IS SELECT employee_id, salary FROM employees;

BEGIN FOR emp_rec IN emp_cursor LOOP INSERT INTO employee_backup VALUES (emp_rec.employee_id, emp_rec.salary); END LOOP;

COMMIT;

END;


āœ… Optimized Version Using FORALL


DECLARE

TYPE emp_table IS TABLE OF employees%ROWTYPE;

emp_list emp_table;

BEGIN

SELECT * BULK COLLECT INTO emp_list FROM employees;

FORALL i IN 1..emp_list.COUNT INSERT INTO employee_backup VALUES emp_list(i); COMMIT;

END;


Why?Ā FORALLĀ performs batch processing, reducing context switching and improving speed.


c. Use PL/SQL Function Result Caching


āœ… Enable Function Result Cache

CREATE OR REPLACE FUNCTION get_employee_name (p_emp_id NUMBER) RETURN VARCHAR2 RESULT_CACHE IS v_name employees.first_name%TYPE;

BEGIN

SELECT first_name INTO v_name FROM employees WHERE employee_id = p_emp_id; RETURN v_name;

END;


Why?Ā The RESULT_CACHEĀ stores function results in memory, reducing repetitive database calls.


3. Database-Level Tuning Examples

a. Gathering Table Statistics

āœ… Update Table Statistics for the Optimizer

EXEC DBMS_STATS.GATHER_TABLE_STATS('HR', 'EMPLOYEES');

Why?Ā Helps Oracle’s optimizer make better execution plan decisions.


b. Monitoring Database Performance with AWR Report

āœ… Generate AWR Report to Analyze Performance Issues

SELECT * FROM TABLE(DBMS_WORKLOAD_REPOSITORY.AWR_REPORT_HTML(10, 20));


Why?Ā AWR reports help identify slow queries, CPU bottlenecks, and inefficient execution plans.


Final Thoughts

Implementing these best practices can significantly improve the performance of Oracle SQL & PL/SQLĀ workloads.


Hope this helps . Happy learning.


Ā 
Ā 
Ā 

Recent Posts

See All

Comments


Other Posts you may Interested 

Subscribe Form

  • facebook
  • linkedin
bottom of page