Oracle Performance Tuning Starter Kit By Zulaikha Z · Oracle DBA Coach (20+ yrs
experience)
🔑 What’s Inside This kit gives you ready-to-use scripts + practice exercises to kickstart your
Oracle Performance Tuning journey. Follow them step by step, one per day, and you’ll quickly
build real confidence in tuning!
Pre-requisite
-- Drop the table if it already exists
DROP TABLE employees CASCADE CONSTRAINTS;
-- Create employees table
CREATE TABLE employees (
employee_id NUMBER(6) CONSTRAINT emp_emp_id_pk PRIMARY KEY,
first_name VARCHAR2(20),
last_name VARCHAR2(25) CONSTRAINT emp_last_name_nn NOT NULL,
email VARCHAR2(25) CONSTRAINT emp_email_nn NOT NULL,
phone_number VARCHAR2(20),
hire_date DATE CONSTRAINT emp_hire_date_nn NOT NULL,
job_id VARCHAR2(10) CONSTRAINT emp_job_nn NOT NULL,
salary NUMBER(8,2) CONSTRAINT emp_salary_ck CHECK (salary > 0),
commission_pct NUMBER(2,2),
manager_id NUMBER(6),
department_id NUMBER(4)
);
-- Add Foreign Key constraints (assuming departments and jobs exist)
ALTER TABLE employees
ADD CONSTRAINT emp_dept_fk FOREIGN KEY (department_id)
REFERENCES departments(department_id);
ALTER TABLE employees
ADD CONSTRAINT emp_job_fk FOREIGN KEY (job_id)
REFERENCES jobs(job_id);
ALTER TABLE employees
ADD CONSTRAINT emp_manager_fk FOREIGN KEY (manager_id)
REFERENCES employees(employee_id);
⚡ Key Points: - employee_id is PK. - last_name, email, hire_date, and job_id are mandatory. -
Includes a salary check constraint. - Foreign keys link to departments, jobs, and self-reference
for manager_id.
Sample Data for Employees Table
INSERT INTO employees VALUES (100, 'Steven', 'King', 'SKING', '515.123.4567', DATE
'2003-06-17', 'AD_PRES', 24000, NULL, NULL, 90);
INSERT INTO employees VALUES (101, 'Neena', 'Kochhar', 'NKOCHHAR', '515.123.4568',
DATE '2005-09-21', 'AD_VP', 17000, NULL, 100, 90);
INSERT INTO employees VALUES (102, 'Lex', 'De Haan', 'LDEHAAN', '515.123.4569',
DATE '2001-01-13', 'AD_VP', 17000, NULL, 100, 90);
INSERT INTO employees VALUES (103, 'Alexander', 'Hunold', 'AHUNOLD', '590.423.4567',
DATE '2006-01-03', 'IT_PROG', 9000, NULL, 102, 60);
INSERT INTO employees VALUES (104, 'Bruce', 'Ernst', 'BERNST', '590.423.4568', DATE
'2007-05-21', 'IT_PROG', 6000, NULL, 103, 60);
INSERT INTO employees VALUES (105, 'David', 'Austin', 'DAUSTIN', '590.423.4569',
DATE '2005-06-25', 'IT_PROG', 4800, NULL, 103, 60);
INSERT INTO employees VALUES (106, 'Valli', 'Pataballa', 'VPATABAL', '590.423.4560',
DATE '2006-02-05', 'IT_PROG', 4800, NULL, 103, 60);
INSERT INTO employees VALUES (107, 'Diana', 'Lorentz', 'DLORENTZ', '590.423.5567',
DATE '2007-02-07', 'IT_PROG', 4200, NULL, 103, 60);
INSERT INTO employees VALUES (108, 'Nancy', 'Greenberg', 'NGREENBE', '515.124.4569',
DATE '2002-08-17', 'FI_MGR', 12000, NULL, 101, 100);
INSERT INTO employees VALUES (109, 'Daniel', 'Faviet', 'DFAVIET', '515.124.4169', DATE
'2002-08-16', 'FI_ACCOUNT', 9000, NULL, 108, 100);
INSERT INTO employees VALUES (110, 'John', 'Chen', 'JCHEN', '515.124.4269', DATE
'2005-09-28', 'FI_ACCOUNT', 8200, NULL, 108, 100);
INSERT INTO employees VALUES (111, 'Ismael', 'Sciarra', 'ISCIARRA', '515.124.4369',
DATE '2005-09-30', 'FI_ACCOUNT', 7700, NULL, 108, 100);
INSERT INTO employees VALUES (112, 'Jose Manuel', 'Urman', 'JMURMAN',
'515.124.4469', DATE '2006-03-07', 'FI_ACCOUNT', 7800, NULL, 108, 100);
INSERT INTO employees VALUES (113, 'Luis', 'Popp', 'LPOPP', '515.124.4567', DATE
'2007-12-07', 'FI_ACCOUNT', 6900, NULL, 108, 100);
How this helps for tuning practice: - Multiple departments (90, 60, 100) → good for joins. -
Mix of high/low salaries → perfect for testing index vs full scan queries. - Self-referencing
manager hierarchy (manager_id) → useful for recursive queries.
🔹 Day 1: SQL Execution Plan Basics
EXPLAIN PLAN FOR
SELECT first_name, last_name
FROM employees
WHERE department_id = 50;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
✅ Practice: Run with/without an index → observe changes.
Lab Queries: 1. Identify Highest Paid Employees
SELECT employee_id, first_name, last_name, salary
FROM employees
ORDER BY salary DESC
FETCH FIRST 5 ROWS ONLY;
Practice: check execution plan before/after creating an index on salary.
2. Search by Employee Name
-- Bad: function on column
SELECT employee_id, first_name, last_name
FROM employees
WHERE UPPER(last_name) = 'KING';
-- Better: index-friendly
SELECT employee_id, first_name, last_name
FROM employees
WHERE last_name = 'King';
3. Department-wise Salary Cost
SELECT department_id, SUM(salary) AS total_salary
FROM employees
GROUP BY department_id;
Practice: see if a bitmap index on department_id helps.
4. Join with Departments
SELECT e.first_name, e.last_name, d.department_name
FROM employees e
JOIN departments d ON e.department_id = d.department_id
WHERE d.department_id = 60;
Helps to understand nested loops vs hash join.
5. Find Employees Without Manager
SELECT employee_id, first_name, last_name
FROM employees
WHERE manager_id IS NULL;
Teaches NULL handling in indexes.
6. Find Top N by Department
SELECT employee_id, first_name, last_name, salary, department_id
FROM (
SELECT e.*, RANK() OVER (PARTITION BY department_id ORDER BY salary DESC)
rnk
FROM employees e
)
WHERE rnk <= 3;
Great example for analytic functions + tuning.
🔹 Day 3: Detect Blocking Sessions
-- Session 1: Lock a row
UPDATE employees SET salary = salary + 100 WHERE employee_id = 105;
-- Session 2: Try to update same row (will block)
UPDATE employees SET salary = salary + 200 WHERE employee_id = 105;
SELECT s1.sid || ',' || s1.serial# AS blocker,
s2.sid || ',' || s2.serial# AS blocked,
s1.username AS blocker_user,
s2.username AS blocked_user,
s2.event
FROM v$session s1
JOIN v$session s2 ON s1.sid = s2.blocking_session
WHERE s1.blocking_session IS NULL;
Practice: Open 2 sessions, lock a row in one, update in another → see blocking in action.
🔹 Day 4: Generate AWR Report
-- Run from SQL*Plus as SYS
@?/rdbms/admin/awrrpt.sql
Practice: Compare AWR before & after workload → find Top SQL, waits.
🔹 Day 5: Instance Waits Snapshot
SELECT event, total_waits, time_waited
FROM v$system_event
ORDER BY time_waited DESC
FETCH FIRST 10 ROWS ONLY;
Practice: Observe which wait events dominate during peak load.
⚡ How to Use This Kit –
📆 Day 1: SQL Plan –
📆 Day 2: Top SQL –
📆 Day 3: Blocking Sessions –
📆 Day 4: AWR - 📆
Day 5: Waits Master one script per day,
Share your observations with Zulaikha, and get guidance on next-level SQL Tuning Advisor.
👩💻 Coach: Zulaikha Z · Oracle DBA Coach · 20+ Years Experience · Specialist in Performance
Tuning, Streams, and GoldenGate