SlideShare a Scribd company logo
=============Optimizer mode
Parameter level:
How to identify current Optimizer setting
select value from v$parameter where name='optimizer_mode';
show parameter optimizer_mode;
Session level:
select substr(sql_text,1,50) from v$sql
where sql_text like '%optimizer mode%'
select optimizer_mode
from v$sql
where sql_text like '%1st query for optimizer mode%';
alter session set optimizer_mode=all_rows;
select optimizer_mode
from v$sql
where sql_text like '%2nd query for optimizer mode%';
alter session set optimizer_mode=choose;
select optimizer_mode
from v$sql
where sql_text like '%3rd query for optimizer mode%';
alter session set optimizer_mode=rule;
select optimizer_mode
from v$sql
where sql_text like '%4th query for optimizer mode%';
alter session set optimizer_mode = first_rows;
-------
Explain plan
Create PLAN_TABLE using the script:
select * from table(dbms_xplan.display);
explain plan for select empno, empname from employee;
explain plan for select empno, empname from employee where empno=206;
explain plan for
select emp.empno, emp.empname, dept.dname from employee emp, department dept
where emp.deptno=dept.deptno;
by default merge join - cost
explain plan for
select emp.empno, emp.empname, dept.dname from employee emp, department dept
where dept.deptno=emp.deptno;
================
Query Transformations:
1) Simple View Merging:
select e.first_name, e.last_name, dept_locs_v.street_address,
dept_locs_v.postal_code
from employees e,
(select d.department_id, d.department_name, l.street_address, l.postal_code
from departments d, locations l
where d.location_id = l.location_id) dept_locs_v
where dept_locs_v.department_id = e.department_id
and e.last_name = 'Smith';
--
select e.empname, dept_locs_v.street_address, dept_locs_v.postal_code
from employee e,
(select d.deptno, d.dname, l.street_address, l.postal_code
from department d, locations l
where d.locid = l.locid) dept_locs_v
where dept_locs_v.deptno = e.deptno
and e.empname = 'Susan';
post - Merge :
select e.empname, l.street_address, l.postal_code
from employee e, department d, locations l
where d.locid = l.locid
and d.deptno = e.deptno
and e.empname = 'Susan';
2) Predicate pushing:
Oracle supports pushing of predicates into a given view. Assume we had a set of
layered views, like this:
-- View One
CREATE VIEW vw_layer_one
AS SELECT * FROM emp;
-- view two
CREATE VIEW vw_layer_two_dept_100
AS SELECT * FROM vw_layer_one
WHERE deptno=100;
Then assume we issued this query:
SELECT * FROM vw_layer_two_dept_100
WHERE empid=100;
The predicate in this statement is the where empid=100 statement. You may have
one of tens or even hundreds of predicates (if you have hundreds, we don t want�
to be supporting your SQL code!). Oracle will, in many cases, push those
predicates down into the views being called. Thus, Oracle will transform the
VW_LAYER_ONE view into a SQL statement that looks like this:
CREATE VIEW vw_layer_one
AS SELECT * FROM emp
WHERE deptno=100
AND empid=100;
Best perf - use bind variables instead of literals:
SELECT * FROM vw_layer_two_dept_100
WHERE empid=:b100;
3) Subquery Unnesting
select /*+ gather_plan_statistics */ ename from emp where sal > (select
max(sal) from emp e where e.empno = emp.empno);
Subqueries can be unnested in to a join. Above is shows that a subquery is
unnested in to a view and then joined to other row sources. In this listing, a
correlated subquery is moved in to a view VW_SQ_1, unnested and then joined
using Nested Loops Join or hash join technique. There are many different
variations of Subquery Unnesting possible, but the crux of the matter is that
subqueries can be unnested, joined and then costed.
Explain Plan:
select * from table(dbms_xplan.display);
=============Lesson 2
SELECT job,sum(sal)
FROM emp e, dept d
WHERE e.deptno=d.deptno GROUP BY job;
The tabular representation is a top-down, left-to-right traversal of the
execution tree. When you read a
plan tree you should start from the bottom left and work across and then up. In
the above example,
begin by looking at the leaves of the tree. In this case the leaves of the tree
are implemented using a full
table scans of the EMP and the DEPT tables. The rows produced by these table
scans will be
consumed by the join operator. Here the join operator is a hash-join (other
alternatives include nested loop or sort-merge join). Finally the group-by
operator implemented here using hash (alternative would
be sort) consumes rows produced by the join-operator, and return the final
result set to the end user.
============
Example of Dynamic Sampling:
create table demo_ds
as
select owner, object_type
from all_objects;
select count(*) from demo_ds;
set autotrace traceonly explain
select /*+ dynamic_sampling(demo_ds 0) */ * from demo_ds
---------------
Hash ex
SELECT deptno, job, SUM(sal)
FROM employee
GROUP BY deptno, job;
uses sort merge
select a.dname,b.empname,b.empno
from department a,employee b
where a.deptno = b.deptno;
Use nested loop
select /*+ USE_NL(b a) */ a.dname,b.empname,b.empno
from department a,employee b
where a.deptno = b.deptno;
=============Generic
1. SQL Performance Tuning team recommends using COUNT(1) instead COUNT(*) for
SQL query performance optimization.
Example:
Do not use:
SELECT COUNT(*)
FROM master;
Use:
SELECT COUNT(1)
FROM master;
2. Never compare NULL with NULL. Consider that NULL is not like an empty string
or like the number 0. Also NULL can not be not equal to NULL (NULL != NULL).
SELECT COUNT(1)
FROM all_users
WHERE 1 = 1;
Result: With condition 1 = 1 you will get result. But in this case you can also
omit condition 1 = 1.
SELECT COUNT(1)
FROM all_users
WHERE NULL = NULL;
Result: With condition NULL = NULL you will get result 0.
SELECT COUNT(1)
FROM all_users
WHERE NULL != NULL;
Result: With condition NULL != NULL you will also get result 0.
3. If you are using more than one table, make sure to use table aliases.
SELECT COUNT(1)
FROM master m, detail d
WHERE m.id = d.master_id;
4. It is good practice to use table column names in an SQL query. This way the
SQL statements will be more readable, but that is not the main reason. Example:
If in INSERT statement you use SELECT * FROM x and at some point you add a new
column in table x, SQL will return an error. The third reason why it is better
to use table column names is to reduce network traffic.
5. In WHERE statements make sure to compare string with string and number with
number, for optimal SQL query performance.
Example:
Note: Column id is NUMBER Data Type.
Do not use:
SELECT id, apn, charging_class
FROM master
WHERE id = '4343';
Use:
SELECT id, apn, charging_class
FROM master
WHERE id = 4343;
6. Do not change column values in WHERE statements if possible, recommended by
SQL Performance Tuning.
Example:
Do not use:
WHERE SUBSTR(a.serial_id, INSTR(b.serial_id, ',') - 1) = SUBSTR(b.serial_id,
INSTR(b.serial_id, ',') - 1)
Use:
WHERE a.serial_id = b.serial_id
7. Avoid using complex expressions.
Examples:
Avoid:
WHERE serial_id = NVL(:a1, serial_id)
WHERE NVL(serial_id,-1) = ( 1, etc...)
8. If you need to use SQL functions on join predicates that is okay, but do not
use them with indexed table columns.
9. EXISTS vs. IN for sub queries
If the selective predicate is in the sub query, then use IN. If the selective
predicate is in the parent query, then use EXISTS.
10. RETURNING clause
INSERT, UPDATE or DELETE can be used with RETURNING clause when appropriate.
This way the number of calls to the database are reduced.
11. SQL Performance Tuning recommends using CASE statements. It is more
efficient to run a single SQL statement, rather than two separate SQL
statements.
Example:
Do not use:
SELECT COUNT (1)
FROM emp
WHERE salary <= 1000;
SELECT COUNT (1)
FROM emp
WHERE salary BETWEEN 1000 AND 2000;
Use:
SELECT COUNT (CASE WHEN salary <= 1000
THEN 1 ELSE null END) count_1,
COUNT (CASE WHEN salary BETWEEN 1001 AND 2000
THEN 1 ELSE null END) count_2
FROM emp;
12. Use UNION ALL instead of UNION, if possible
Example:
Do not use:
SELECT id, name
FROM emp_bmw
UNION
SELECT id, name
FROM emp_bmw_welt
Use:
SELECT id, name
FROM emp_bmw
UNION ALL
SELECT id, name
FROM emp_bmw_welt
13. SQL Performance Tuning recommends to use minimal number of sub queries, if
possible.
Example:
Do not use:
SELECT id, manufacturer, model
FROM cars
WHERE price = ( SELECT MAX(price)
FROM cars_bmw
)
AND year = ( SELECT MAX(year)
FROM cars_bmw
)
Use:
SELECT id, manufacturer, model
FROM cars
WHERE (price, year) = ( SELECT MAX(price), MAX(year)
FROM cars_bmw
)
14. SQL Performance Tuning recommends when cretin data are used frequently, it
is a good idea to store them into intermediate tables.
15. SQL Performance Tuning OR vs. IN.
Our tests showed that using IN in WHERE condition is a little faster then using
OR.
Example:
Do not use:
SELECT *
FROM CDRS_NR
WHERE RECORD_TYPE = 'MTC'
OR RECORD_TYPE = 'MOC'
OR RECORD_TYPE = 'SMSO'
Use:
SELECT *
FROM CDRS_NR
WHERE RECORD_TYPE IN ('MTC', 'MOC', 'SMSO')
==============
Which departments have at least one employee?
--Looks for every dept from dept table in employee table, collects to remove the
duplicate;
SELECT DISTINCT d.department_name
FROM departments d, employees e
WHERE e.department_id = d.department_id;
Oracle performs an existence check (semi-join) for each record in the department
table; no duplicates are produced.
SELECT d.dname
FROM department d
WHERE not EXISTS (
SELECT *
FROM employee e
WHERE deptno = d.deptno
);
below qry uses hash
SELECT DISTINCT d.dname
FROM department d, employee e
WHERE e.deptno = d.deptno;
to make it use sort merge
SELECT /*+ USE_MERGE(d e) */ DISTINCT d.dname
FROM department d, employee e
WHERE e.deptno = d.deptno;
SELECT /*+ NO_USE_HASH USE_MERGE(d e) */ DISTINCT d.dname
FROM department d, employee e
WHERE e.deptno = d.deptno;
=====Use Exists
SELECT DISTINCT o.order_id, o.order_date
FROM
orders o,
order_items ol
WHERE
LOWER(o.order_state) = : order_state AND
ol.order_id = o.order_id AND
ol.item_id IN (
SELECT item_id
FROM items
WHERE item_state = : item_state
)
ORDER BY o.order_date;
--prevents oracle from using any index on order_state column,
Below is the query re-written:
SELECT
order_id,
order_date
FROM orders o
WHERE order_state = : order_state
AND EXISTS (
SELECT *
FROM order_items ol
WHERE order_id = o.order_id
AND EXISTS (
SELECT *
FROM items
WHERE item_id = ol.item_id
AND item_state = : item_state
)
)
ORDER BY order_date;
Note: Usually IN has the slowest performance.
IN is efficient when most of the filter criteria is in the sub-query.
EXISTS is efficient when most of the filter criteria is in the main query.
== Usage of Having clause
Do not use:
SELECT subject, count(subject)
FROM student_details
GROUP BY subject
HAVING subject!= 'Vancouver' AND subject!= 'Toronto';
Use:
SELECT subject, count(subject)
FROM student_details
WHERE subject != 'Science'
AND subject != 'Maths'
GROUP BY subject;
===Try to Minimize number of subqueries;
Do not use:
SELECT first_name , salary
FROM employees
WHERE salary = (SELECT MAX(salary) FROM employees)
AND comm1 = (SELECT MAX(comm1) FROM employees) ;
AND emp_dept = 'Electronics';
Use:
SELECT first_name
FROM employees
WHERE (salary, comm1 ) = (SELECT MAX (salary), MAX (comm1)
FROM employees) ;
AND dept = 'Electronics';
---use Exists instead of distinct
Do not use:
SELECT DISTINCT d.dept_id, d.dept
FROM dept d,employee e
WHERE e.dept = e.dept;
Use:
SELECT d.dept_id, d.dept
FROM dept d
WHERE EXISTS ( SELECT 'X' FROM employee e WHERE e.dept = d.dept);
--Other Where conditions
Do: SELECT id, first_name, age FROM student_details WHERE age > 10;
Don't: SELECT id, first_name, age FROM student_details WHERE age != 10;
or SELECT id, first_name, age FROM student_details WHERE age NOT = 10
Do: SELECT id, first_name, age
FROM student_details
WHERE first_name LIKE 'Chan%';
Don't:
SELECT id, first_name, age
FROM student_details
WHERE SUBSTR(first_name,1,3) = 'Cha';
Do:
SELECT id, first_name, age
FROM student_details
WHERE first_name LIKE NVL ( :name, '%');
Don't:
SELECT id, first_name, age
FROM student_details
WHERE first_name = NVL ( :name, first_name);
Do:
SELECT product_id, product_name
FROM product
WHERE unit_price BETWEEN MAX(unit_price) and MIN(unit_price)
Don't:
SELECT product_id, product_name
FROM product
WHERE unit_price >= MAX(unit_price)
and unit_price <= MIN(unit_price)
Do:
SELECT id, name, salary
FROM employee
WHERE dept = 'Electronics'
AND location = 'Bangalore';
Don't:
SELECT id, name, salary
FROM employee
WHERE dept || location= 'ElectronicsBangalore';
Use non-column expression on one side of the query because it will be processed
earlier.
Do:
SELECT id, name, salary
FROM employee
WHERE salary < 25000
Don't:
SELECT id, name, salary
FROM employee
WHERE salary + 10000 < 35000;
Use DECODE to avoid the scanning of same rows or joining the same table
repetitively.
DECODE can also be made used in place of GROUP BY or ORDER BY clause.
Eg: Write like
SELECT id FROM employee
WHERE name LIKE 'Ramesh%'
and location = 'Bangalore';
Don't: SELECT DECODE(location,'Bangalore',id,NULL) id FROM employee
WHERE name LIKE 'Ramesh%';
--Order of Predicates in Where clause
place predicates first , the one which eliminates more rows first.
Where Gender = 'Male' and Designation = 'SSE'
--Order of Tables names
Low selectivity - does not use index
High selectivity - uses index
---Indexes
- Create index for columns that are repeatedly used
- Creating index on Foreign Key - helps as most of the join conditions
arebased on PK & FK
- Don't create Index for columns which are frequently updated
- Get rid of overlapping indexes
- Consider deleting indiex when loading huge voume of data into table
To store large binary objects, first place them in the file system and add the
file path in the database.
--Follow general rules - Tips for writing more efficient SQL:
a) Use single case for all SQL verbs
b) Begin all SQL verbs on a new line
c) Separate all words with a single space
d) Right or left aligning verbs within the initial SQL verb
e) Rewrite complex subqueries with temporary tables - Oracle created the global
temporary table (GTT) and the SQL WITH operator to help divide-and-conquer
complex SQL sub-queries (especially those with with WHERE clause subqueries,
SELECT clause scalar subqueries and FROM clause in-line views). Tuning SQL
with temporary tables (and materializations in the WITH clause) can result in
amazing performance improvements.
f) Use minus instead of EXISTS subqueries - Some say that using the minus
operator instead of NOT IN and NOT Exists will result in a faster execution
plan.
g) Use SQL analytic functions - The Oracle analytic functions can do multiple
aggregations (e.g. rollup by cube) with a single pass through the tables, making
them very fast for reporting SQL.
h) Re-write NOT EXISTS and NOT EXISTS subqueries as outer joins - In many
cases of NOT queries (but ONLY where a column is defined as NULL), you can re-
write the uncorrelated subqueries into outer joins with IS NULL tests. Note
that this is a non-correlated sub-query, but it could be re-written as an outer
join.
select book_key from book
where
book_key NOT IN (select book_key from sales);
Below we combine the outer join with a NULL test in the WHERE clause without
using a sub-query, giving a faster execution plan.
select b.book_key from book b, sales s
where
b.book_key = s.book_key(+)
and
s.book_key IS NULL;
i)Index your NULL values - If you have SQL that frequently tests for NULL,
consider creating an index on NULL values. To get around the optimization of
SQL queries that choose NULL column values (i.e. where emp_name IS NULL), we can
create a function-based index using the null value built-in SQL function to
index only on the NULL columns.
j)Leave column names alone - Never do a calculation on an indexed column unless
you have a matching function-based index (a.k.a. FBI).
where salary*5 > :myvalue
where substr(ssn,7,4) = "1234"
where to_char(mydate,mon) = "january"
k) Avoid the use of NOT IN or HAVING. Instead, a NOT EXISTS subquery may run
faster (when appropriate).
l) Avoid the LIKE predicate = Always replace a "like" with an equality, when
appropriate.
m) Never mix data types - If a WHERE clause column predicate is numeric, do not
to use quotes. For char index columns, always use quotes. There are mixed data
type predicates:
where cust_nbr = "123"
where substr(ssn,7,4) = 1234
n) Use decode and case - Performing complex aggregations with the "decode" or
"case" functions can minimize the number of times a table has to be selected.
o) Don't fear full-table scans - Not all OLTP queries are optimal when they uses
indexes. If your query will return a large percentage of the table rows, a
full-table scan may be faster than an index scan. This depends on many
factors, including your configuration (values for
db_file_multiblock_read_count, db_block_size), query parallelism and the number
of table/index blocks in the buffer cache.
p)Use those aliases - Always use table aliases when referencing columns.

More Related Content

PDF
Oracle Performance Tuning Fundamentals
DOCX
Oracle Database 19c (19.3) Installation on Windows (Step-by-Step)
PDF
Top 5 mistakes when writing Spark applications
DOCX
What is difference between dbms and rdbms
PPT
Sga internals
PPTX
Oracle DBA
PDF
Oracle Database SQL Tuning Concept
PPTX
Database Consolidation using the Oracle Multitenant Architecture
Oracle Performance Tuning Fundamentals
Oracle Database 19c (19.3) Installation on Windows (Step-by-Step)
Top 5 mistakes when writing Spark applications
What is difference between dbms and rdbms
Sga internals
Oracle DBA
Oracle Database SQL Tuning Concept
Database Consolidation using the Oracle Multitenant Architecture

What's hot (20)

PDF
Tanel Poder - Scripts and Tools short
PPTX
Filepermissions in linux
PDF
Cosco: An Efficient Facebook-Scale Shuffle Service
PPT
Unix File System
PDF
Improving SparkSQL Performance by 30%: How We Optimize Parquet Pushdown and P...
PDF
Etsy Activity Feeds Architecture
PPT
UKOUG, Oracle Transaction Locks
PPTX
Apache Spark Architecture
PDF
Troubleshooting Complex Performance issues - Oracle SEG$ contention
PDF
Storing time series data with Apache Cassandra
PPTX
What is a Kernel? : Introduction And Architecture
PPTX
ASH and AWR on DB12c
PPTX
AWR and ASH Deep Dive
PPTX
Basic commands of linux
PDF
Exploring Oracle Database Performance Tuning Best Practices for DBAs and Deve...
PPTX
Computer system organization
PDF
DB2 LUW - Backup and Recovery
PPT
Query processing-and-optimization
PDF
Oracle 21c: New Features and Enhancements of Data Pump & TTS
PDF
Oracle statistics by example
Tanel Poder - Scripts and Tools short
Filepermissions in linux
Cosco: An Efficient Facebook-Scale Shuffle Service
Unix File System
Improving SparkSQL Performance by 30%: How We Optimize Parquet Pushdown and P...
Etsy Activity Feeds Architecture
UKOUG, Oracle Transaction Locks
Apache Spark Architecture
Troubleshooting Complex Performance issues - Oracle SEG$ contention
Storing time series data with Apache Cassandra
What is a Kernel? : Introduction And Architecture
ASH and AWR on DB12c
AWR and ASH Deep Dive
Basic commands of linux
Exploring Oracle Database Performance Tuning Best Practices for DBAs and Deve...
Computer system organization
DB2 LUW - Backup and Recovery
Query processing-and-optimization
Oracle 21c: New Features and Enhancements of Data Pump & TTS
Oracle statistics by example
Ad

Viewers also liked (20)

PDF
Oracle SQL Performance Tuning and Optimization v26 chapter 1
PPTX
SQL Tuning Sets: Generieren, Verwenden, Transferieren, Szenarios
PPT
Les 15 perf_sql
DOC
Analyzing awr report
PPTX
Delphix Patching Epiphany
PPT
Oracle - SQL-PL/SQL context switching
PDF
FlashSystems 2016 update
PPT
Oracle SQL, PL/SQL Performance tuning
PPTX
Oracle DB 12c SQL Tuning
PDF
Oracle SQL tuning with SQL Plan Management
PDF
Oracle 11G SCAN: Concepts and Implementation Experience Sharing
PPT
Hfm intro v2
PPT
Hyperion Planning Class
PDF
Bisp training calendar jan 2012
PPT
Hyperion analyzer 31 july
PDF
Getting started-with-oracle-so a- lab 11
PPT
Hfm intro v2
PPT
PPTX
Reaching Out From PL/SQL (OPP 2010)
PPT
02 Essbase
Oracle SQL Performance Tuning and Optimization v26 chapter 1
SQL Tuning Sets: Generieren, Verwenden, Transferieren, Szenarios
Les 15 perf_sql
Analyzing awr report
Delphix Patching Epiphany
Oracle - SQL-PL/SQL context switching
FlashSystems 2016 update
Oracle SQL, PL/SQL Performance tuning
Oracle DB 12c SQL Tuning
Oracle SQL tuning with SQL Plan Management
Oracle 11G SCAN: Concepts and Implementation Experience Sharing
Hfm intro v2
Hyperion Planning Class
Bisp training calendar jan 2012
Hyperion analyzer 31 july
Getting started-with-oracle-so a- lab 11
Hfm intro v2
Reaching Out From PL/SQL (OPP 2010)
02 Essbase
Ad

Similar to Oracle sql tuning (20)

PPT
Oracle tips and tricks
PPTX
Oracle: Basic SQL
PPTX
Oracle: Basic SQL
DOCX
Trig
PPT
Chinabankppt
PPTX
ADV Powepoint 3 Lec.pptx
PPTX
Beginers guide for oracle sql
ODP
Mysqlppt
PDF
Database development coding standards
PPTX
DBMS UNIT 9.pptx..................................
PPT
Les08-Oracle
DOC
PPT
SQL Tuning Overview
PDF
Oracle
PDF
How To Control IO Usage using Resource Manager
PPT
Sql dml & tcl 2
PPT
Sql query [select, sub] 4
PPT
Module03
PPT
PPT
SAS Proc SQL
Oracle tips and tricks
Oracle: Basic SQL
Oracle: Basic SQL
Trig
Chinabankppt
ADV Powepoint 3 Lec.pptx
Beginers guide for oracle sql
Mysqlppt
Database development coding standards
DBMS UNIT 9.pptx..................................
Les08-Oracle
SQL Tuning Overview
Oracle
How To Control IO Usage using Resource Manager
Sql dml & tcl 2
Sql query [select, sub] 4
Module03
SAS Proc SQL

Recently uploaded (20)

PDF
System and Network Administration Chapter 2
PPTX
history of c programming in notes for students .pptx
PDF
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
PDF
Wondershare Filmora 15 Crack With Activation Key [2025
PPTX
Operating system designcfffgfgggggggvggggggggg
PPTX
L1 - Introduction to python Backend.pptx
PPTX
Why Generative AI is the Future of Content, Code & Creativity?
PDF
Product Update: Alluxio AI 3.7 Now with Sub-Millisecond Latency
PDF
Understanding Forklifts - TECH EHS Solution
PDF
Digital Systems & Binary Numbers (comprehensive )
PPTX
CHAPTER 2 - PM Management and IT Context
PDF
Design an Analysis of Algorithms II-SECS-1021-03
PPTX
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
PPTX
Computer Software and OS of computer science of grade 11.pptx
PPTX
Transform Your Business with a Software ERP System
PDF
Upgrade and Innovation Strategies for SAP ERP Customers
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PDF
iTop VPN Free 5.6.0.5262 Crack latest version 2025
PDF
How to Choose the Right IT Partner for Your Business in Malaysia
PPTX
Odoo POS Development Services by CandidRoot Solutions
System and Network Administration Chapter 2
history of c programming in notes for students .pptx
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
Wondershare Filmora 15 Crack With Activation Key [2025
Operating system designcfffgfgggggggvggggggggg
L1 - Introduction to python Backend.pptx
Why Generative AI is the Future of Content, Code & Creativity?
Product Update: Alluxio AI 3.7 Now with Sub-Millisecond Latency
Understanding Forklifts - TECH EHS Solution
Digital Systems & Binary Numbers (comprehensive )
CHAPTER 2 - PM Management and IT Context
Design an Analysis of Algorithms II-SECS-1021-03
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
Computer Software and OS of computer science of grade 11.pptx
Transform Your Business with a Software ERP System
Upgrade and Innovation Strategies for SAP ERP Customers
Design an Analysis of Algorithms I-SECS-1021-03
iTop VPN Free 5.6.0.5262 Crack latest version 2025
How to Choose the Right IT Partner for Your Business in Malaysia
Odoo POS Development Services by CandidRoot Solutions

Oracle sql tuning

  • 1. =============Optimizer mode Parameter level: How to identify current Optimizer setting select value from v$parameter where name='optimizer_mode'; show parameter optimizer_mode; Session level: select substr(sql_text,1,50) from v$sql where sql_text like '%optimizer mode%' select optimizer_mode from v$sql where sql_text like '%1st query for optimizer mode%'; alter session set optimizer_mode=all_rows; select optimizer_mode from v$sql where sql_text like '%2nd query for optimizer mode%'; alter session set optimizer_mode=choose; select optimizer_mode from v$sql where sql_text like '%3rd query for optimizer mode%'; alter session set optimizer_mode=rule; select optimizer_mode from v$sql where sql_text like '%4th query for optimizer mode%'; alter session set optimizer_mode = first_rows; ------- Explain plan Create PLAN_TABLE using the script: select * from table(dbms_xplan.display); explain plan for select empno, empname from employee; explain plan for select empno, empname from employee where empno=206; explain plan for select emp.empno, emp.empname, dept.dname from employee emp, department dept where emp.deptno=dept.deptno; by default merge join - cost explain plan for select emp.empno, emp.empname, dept.dname from employee emp, department dept where dept.deptno=emp.deptno; ================ Query Transformations: 1) Simple View Merging: select e.first_name, e.last_name, dept_locs_v.street_address, dept_locs_v.postal_code from employees e, (select d.department_id, d.department_name, l.street_address, l.postal_code from departments d, locations l
  • 2. where d.location_id = l.location_id) dept_locs_v where dept_locs_v.department_id = e.department_id and e.last_name = 'Smith'; -- select e.empname, dept_locs_v.street_address, dept_locs_v.postal_code from employee e, (select d.deptno, d.dname, l.street_address, l.postal_code from department d, locations l where d.locid = l.locid) dept_locs_v where dept_locs_v.deptno = e.deptno and e.empname = 'Susan'; post - Merge : select e.empname, l.street_address, l.postal_code from employee e, department d, locations l where d.locid = l.locid and d.deptno = e.deptno and e.empname = 'Susan'; 2) Predicate pushing: Oracle supports pushing of predicates into a given view. Assume we had a set of layered views, like this: -- View One CREATE VIEW vw_layer_one AS SELECT * FROM emp; -- view two CREATE VIEW vw_layer_two_dept_100 AS SELECT * FROM vw_layer_one WHERE deptno=100; Then assume we issued this query: SELECT * FROM vw_layer_two_dept_100 WHERE empid=100; The predicate in this statement is the where empid=100 statement. You may have one of tens or even hundreds of predicates (if you have hundreds, we don t want� to be supporting your SQL code!). Oracle will, in many cases, push those predicates down into the views being called. Thus, Oracle will transform the VW_LAYER_ONE view into a SQL statement that looks like this: CREATE VIEW vw_layer_one AS SELECT * FROM emp WHERE deptno=100 AND empid=100; Best perf - use bind variables instead of literals: SELECT * FROM vw_layer_two_dept_100 WHERE empid=:b100; 3) Subquery Unnesting select /*+ gather_plan_statistics */ ename from emp where sal > (select max(sal) from emp e where e.empno = emp.empno); Subqueries can be unnested in to a join. Above is shows that a subquery is unnested in to a view and then joined to other row sources. In this listing, a correlated subquery is moved in to a view VW_SQ_1, unnested and then joined using Nested Loops Join or hash join technique. There are many different variations of Subquery Unnesting possible, but the crux of the matter is that subqueries can be unnested, joined and then costed. Explain Plan: select * from table(dbms_xplan.display); =============Lesson 2 SELECT job,sum(sal)
  • 3. FROM emp e, dept d WHERE e.deptno=d.deptno GROUP BY job; The tabular representation is a top-down, left-to-right traversal of the execution tree. When you read a plan tree you should start from the bottom left and work across and then up. In the above example, begin by looking at the leaves of the tree. In this case the leaves of the tree are implemented using a full table scans of the EMP and the DEPT tables. The rows produced by these table scans will be consumed by the join operator. Here the join operator is a hash-join (other alternatives include nested loop or sort-merge join). Finally the group-by operator implemented here using hash (alternative would be sort) consumes rows produced by the join-operator, and return the final result set to the end user. ============ Example of Dynamic Sampling: create table demo_ds as select owner, object_type from all_objects; select count(*) from demo_ds; set autotrace traceonly explain select /*+ dynamic_sampling(demo_ds 0) */ * from demo_ds --------------- Hash ex SELECT deptno, job, SUM(sal) FROM employee GROUP BY deptno, job; uses sort merge select a.dname,b.empname,b.empno from department a,employee b where a.deptno = b.deptno; Use nested loop select /*+ USE_NL(b a) */ a.dname,b.empname,b.empno from department a,employee b where a.deptno = b.deptno; =============Generic 1. SQL Performance Tuning team recommends using COUNT(1) instead COUNT(*) for SQL query performance optimization. Example: Do not use: SELECT COUNT(*) FROM master; Use: SELECT COUNT(1) FROM master; 2. Never compare NULL with NULL. Consider that NULL is not like an empty string or like the number 0. Also NULL can not be not equal to NULL (NULL != NULL). SELECT COUNT(1) FROM all_users WHERE 1 = 1; Result: With condition 1 = 1 you will get result. But in this case you can also omit condition 1 = 1.
  • 4. SELECT COUNT(1) FROM all_users WHERE NULL = NULL; Result: With condition NULL = NULL you will get result 0. SELECT COUNT(1) FROM all_users WHERE NULL != NULL; Result: With condition NULL != NULL you will also get result 0. 3. If you are using more than one table, make sure to use table aliases. SELECT COUNT(1) FROM master m, detail d WHERE m.id = d.master_id; 4. It is good practice to use table column names in an SQL query. This way the SQL statements will be more readable, but that is not the main reason. Example: If in INSERT statement you use SELECT * FROM x and at some point you add a new column in table x, SQL will return an error. The third reason why it is better to use table column names is to reduce network traffic. 5. In WHERE statements make sure to compare string with string and number with number, for optimal SQL query performance. Example: Note: Column id is NUMBER Data Type. Do not use: SELECT id, apn, charging_class FROM master WHERE id = '4343'; Use: SELECT id, apn, charging_class FROM master WHERE id = 4343; 6. Do not change column values in WHERE statements if possible, recommended by SQL Performance Tuning. Example: Do not use: WHERE SUBSTR(a.serial_id, INSTR(b.serial_id, ',') - 1) = SUBSTR(b.serial_id, INSTR(b.serial_id, ',') - 1) Use: WHERE a.serial_id = b.serial_id 7. Avoid using complex expressions. Examples: Avoid: WHERE serial_id = NVL(:a1, serial_id) WHERE NVL(serial_id,-1) = ( 1, etc...) 8. If you need to use SQL functions on join predicates that is okay, but do not use them with indexed table columns. 9. EXISTS vs. IN for sub queries If the selective predicate is in the sub query, then use IN. If the selective predicate is in the parent query, then use EXISTS. 10. RETURNING clause
  • 5. INSERT, UPDATE or DELETE can be used with RETURNING clause when appropriate. This way the number of calls to the database are reduced. 11. SQL Performance Tuning recommends using CASE statements. It is more efficient to run a single SQL statement, rather than two separate SQL statements. Example: Do not use: SELECT COUNT (1) FROM emp WHERE salary <= 1000; SELECT COUNT (1) FROM emp WHERE salary BETWEEN 1000 AND 2000; Use: SELECT COUNT (CASE WHEN salary <= 1000 THEN 1 ELSE null END) count_1, COUNT (CASE WHEN salary BETWEEN 1001 AND 2000 THEN 1 ELSE null END) count_2 FROM emp; 12. Use UNION ALL instead of UNION, if possible Example: Do not use: SELECT id, name FROM emp_bmw UNION SELECT id, name FROM emp_bmw_welt Use: SELECT id, name FROM emp_bmw UNION ALL SELECT id, name FROM emp_bmw_welt 13. SQL Performance Tuning recommends to use minimal number of sub queries, if possible. Example: Do not use: SELECT id, manufacturer, model FROM cars WHERE price = ( SELECT MAX(price) FROM cars_bmw ) AND year = ( SELECT MAX(year) FROM cars_bmw ) Use: SELECT id, manufacturer, model FROM cars WHERE (price, year) = ( SELECT MAX(price), MAX(year) FROM cars_bmw ) 14. SQL Performance Tuning recommends when cretin data are used frequently, it is a good idea to store them into intermediate tables. 15. SQL Performance Tuning OR vs. IN. Our tests showed that using IN in WHERE condition is a little faster then using OR.
  • 6. Example: Do not use: SELECT * FROM CDRS_NR WHERE RECORD_TYPE = 'MTC' OR RECORD_TYPE = 'MOC' OR RECORD_TYPE = 'SMSO' Use: SELECT * FROM CDRS_NR WHERE RECORD_TYPE IN ('MTC', 'MOC', 'SMSO') ============== Which departments have at least one employee? --Looks for every dept from dept table in employee table, collects to remove the duplicate; SELECT DISTINCT d.department_name FROM departments d, employees e WHERE e.department_id = d.department_id; Oracle performs an existence check (semi-join) for each record in the department table; no duplicates are produced. SELECT d.dname FROM department d WHERE not EXISTS ( SELECT * FROM employee e WHERE deptno = d.deptno ); below qry uses hash SELECT DISTINCT d.dname FROM department d, employee e WHERE e.deptno = d.deptno; to make it use sort merge SELECT /*+ USE_MERGE(d e) */ DISTINCT d.dname FROM department d, employee e WHERE e.deptno = d.deptno; SELECT /*+ NO_USE_HASH USE_MERGE(d e) */ DISTINCT d.dname FROM department d, employee e WHERE e.deptno = d.deptno; =====Use Exists SELECT DISTINCT o.order_id, o.order_date FROM orders o, order_items ol WHERE LOWER(o.order_state) = : order_state AND ol.order_id = o.order_id AND ol.item_id IN ( SELECT item_id FROM items WHERE item_state = : item_state ) ORDER BY o.order_date; --prevents oracle from using any index on order_state column, Below is the query re-written: SELECT order_id,
  • 7. order_date FROM orders o WHERE order_state = : order_state AND EXISTS ( SELECT * FROM order_items ol WHERE order_id = o.order_id AND EXISTS ( SELECT * FROM items WHERE item_id = ol.item_id AND item_state = : item_state ) ) ORDER BY order_date; Note: Usually IN has the slowest performance. IN is efficient when most of the filter criteria is in the sub-query. EXISTS is efficient when most of the filter criteria is in the main query. == Usage of Having clause Do not use: SELECT subject, count(subject) FROM student_details GROUP BY subject HAVING subject!= 'Vancouver' AND subject!= 'Toronto'; Use: SELECT subject, count(subject) FROM student_details WHERE subject != 'Science' AND subject != 'Maths' GROUP BY subject; ===Try to Minimize number of subqueries; Do not use: SELECT first_name , salary FROM employees WHERE salary = (SELECT MAX(salary) FROM employees) AND comm1 = (SELECT MAX(comm1) FROM employees) ; AND emp_dept = 'Electronics'; Use: SELECT first_name FROM employees WHERE (salary, comm1 ) = (SELECT MAX (salary), MAX (comm1) FROM employees) ; AND dept = 'Electronics'; ---use Exists instead of distinct Do not use: SELECT DISTINCT d.dept_id, d.dept FROM dept d,employee e WHERE e.dept = e.dept; Use: SELECT d.dept_id, d.dept FROM dept d WHERE EXISTS ( SELECT 'X' FROM employee e WHERE e.dept = d.dept);
  • 8. --Other Where conditions Do: SELECT id, first_name, age FROM student_details WHERE age > 10; Don't: SELECT id, first_name, age FROM student_details WHERE age != 10; or SELECT id, first_name, age FROM student_details WHERE age NOT = 10 Do: SELECT id, first_name, age FROM student_details WHERE first_name LIKE 'Chan%'; Don't: SELECT id, first_name, age FROM student_details WHERE SUBSTR(first_name,1,3) = 'Cha'; Do: SELECT id, first_name, age FROM student_details WHERE first_name LIKE NVL ( :name, '%'); Don't: SELECT id, first_name, age FROM student_details WHERE first_name = NVL ( :name, first_name); Do: SELECT product_id, product_name FROM product WHERE unit_price BETWEEN MAX(unit_price) and MIN(unit_price) Don't: SELECT product_id, product_name FROM product WHERE unit_price >= MAX(unit_price) and unit_price <= MIN(unit_price) Do: SELECT id, name, salary FROM employee WHERE dept = 'Electronics' AND location = 'Bangalore'; Don't: SELECT id, name, salary FROM employee WHERE dept || location= 'ElectronicsBangalore'; Use non-column expression on one side of the query because it will be processed earlier. Do: SELECT id, name, salary FROM employee WHERE salary < 25000 Don't: SELECT id, name, salary FROM employee WHERE salary + 10000 < 35000; Use DECODE to avoid the scanning of same rows or joining the same table repetitively. DECODE can also be made used in place of GROUP BY or ORDER BY clause.
  • 9. Eg: Write like SELECT id FROM employee WHERE name LIKE 'Ramesh%' and location = 'Bangalore'; Don't: SELECT DECODE(location,'Bangalore',id,NULL) id FROM employee WHERE name LIKE 'Ramesh%'; --Order of Predicates in Where clause place predicates first , the one which eliminates more rows first. Where Gender = 'Male' and Designation = 'SSE' --Order of Tables names Low selectivity - does not use index High selectivity - uses index ---Indexes - Create index for columns that are repeatedly used - Creating index on Foreign Key - helps as most of the join conditions arebased on PK & FK - Don't create Index for columns which are frequently updated - Get rid of overlapping indexes - Consider deleting indiex when loading huge voume of data into table To store large binary objects, first place them in the file system and add the file path in the database. --Follow general rules - Tips for writing more efficient SQL: a) Use single case for all SQL verbs b) Begin all SQL verbs on a new line c) Separate all words with a single space d) Right or left aligning verbs within the initial SQL verb e) Rewrite complex subqueries with temporary tables - Oracle created the global temporary table (GTT) and the SQL WITH operator to help divide-and-conquer complex SQL sub-queries (especially those with with WHERE clause subqueries, SELECT clause scalar subqueries and FROM clause in-line views). Tuning SQL with temporary tables (and materializations in the WITH clause) can result in amazing performance improvements. f) Use minus instead of EXISTS subqueries - Some say that using the minus operator instead of NOT IN and NOT Exists will result in a faster execution plan. g) Use SQL analytic functions - The Oracle analytic functions can do multiple aggregations (e.g. rollup by cube) with a single pass through the tables, making them very fast for reporting SQL. h) Re-write NOT EXISTS and NOT EXISTS subqueries as outer joins - In many cases of NOT queries (but ONLY where a column is defined as NULL), you can re- write the uncorrelated subqueries into outer joins with IS NULL tests. Note that this is a non-correlated sub-query, but it could be re-written as an outer join. select book_key from book where book_key NOT IN (select book_key from sales); Below we combine the outer join with a NULL test in the WHERE clause without using a sub-query, giving a faster execution plan.
  • 10. select b.book_key from book b, sales s where b.book_key = s.book_key(+) and s.book_key IS NULL; i)Index your NULL values - If you have SQL that frequently tests for NULL, consider creating an index on NULL values. To get around the optimization of SQL queries that choose NULL column values (i.e. where emp_name IS NULL), we can create a function-based index using the null value built-in SQL function to index only on the NULL columns. j)Leave column names alone - Never do a calculation on an indexed column unless you have a matching function-based index (a.k.a. FBI). where salary*5 > :myvalue where substr(ssn,7,4) = "1234" where to_char(mydate,mon) = "january" k) Avoid the use of NOT IN or HAVING. Instead, a NOT EXISTS subquery may run faster (when appropriate). l) Avoid the LIKE predicate = Always replace a "like" with an equality, when appropriate. m) Never mix data types - If a WHERE clause column predicate is numeric, do not to use quotes. For char index columns, always use quotes. There are mixed data type predicates: where cust_nbr = "123" where substr(ssn,7,4) = 1234 n) Use decode and case - Performing complex aggregations with the "decode" or "case" functions can minimize the number of times a table has to be selected. o) Don't fear full-table scans - Not all OLTP queries are optimal when they uses indexes. If your query will return a large percentage of the table rows, a full-table scan may be faster than an index scan. This depends on many factors, including your configuration (values for db_file_multiblock_read_count, db_block_size), query parallelism and the number of table/index blocks in the buffer cache. p)Use those aliases - Always use table aliases when referencing columns.