Oracle Performance Tuning
Oracle Performance Tuning
I/O Waits db file sequential read, db file scattered gc buffer busy, gc cr request, gc
read, direct path read current block
CPU and Memory latch free, buffer busy waits, PGA memory gc current block busy, gc cr
Waits block
Concurrency Waits enq: TX - row lock contention gc buffer busy, global enqueue
Network Waits SQL*Net message from/to client gc buffer busy, gc current block
Other Waits log file sync, log file parallel write gc cr write, buffer busy waits
SRX (Share Row Allows inserts but prevents updates or INSERT while preventing updates
Exclusive) deletes. or deletes
Oracle RAC (Real Application Clusters) involves multiple resources that need to be monitored for
proper functioning and performance. Below is a detailed table listing key Oracle RAC resources and
their corresponding Oracle views, procedures, functions, or packages used to monitor their status.
Oracle RAC Resources and Corresponding Monitoring Views/Procedures/Functions/Packages
RAC Resource Oracle Description
View/Procedure/Function/Package for
Monitoring
Instance Status V$INSTANCE Provides status of the Oracle
instance, including whether it is
open, mounted, or down.
Cluster V$CR_BLOCKED, Monitors cluster interconnect
Interconnect (network) issues and global
Status V$GC_STATS, cache statistics.
Global Cache (GC) V$GC_STATS, Provides statistics on global
Status cache performance, such as
V$CACHE block transfers, misses, and
waits.
Global Enqueue V$GES_STAT, Monitors global enqueue service
Service (GES) (GES), which manages locks
V$SESSION_WAIT across RAC nodes.
Global Resource V$GCS_RESOURCE Displays information about
Directory (GRD) resources managed by Global
Cache Service (GCS).
Redo Log Sync V$LOG, V$SESSION_WAIT, Monitors redo log
V$LOG_HISTORY synchronization activity across
RAC instances.
Shared Memory V$SGA Provides statistics about the
(SGA) shared memory, including buffer
cache, redo log buffer, and other
SGA components.
Clusterware V$CLUSTER Displays information about
Status Oracle Clusterware status (such
as whether the node is part of
the cluster).
Disk Group (ASM) V$ASM_DISKGROUP, V$ASM_DISK, Monitors Oracle ASM disk
V$ASM_FILE groups and disks for status,
usage, and performance.
Instance Alert V$DIAG_INFO Provides diagnostic information,
Logs including alert logs for instances
in the RAC setup.
RAC Service V$SERVICE Monitors database services and
their status in the RAC
environment.
Instance Recovery V$INSTANCE_RECOVERY Provides information related to
instance recovery in the RAC
setup.
Log Writer (LGWR) V$LOG Provides status on the log writer
process, specifically its activity
related to redo logs and log file
synchronizations.
Instance Waits V$SESSION_WAIT, V$WAITSTAT, Provides session-level and
V$SYSTEM_EVENT system-level wait events, helping
to analyze instance resource
contention.
Enqueue Locks V$GES_ENQUEUE Provides information on
enqueue lock contention and
usage across RAC instances.
Cluster Cache V$CACHE, V$CACHE_TRANSFER, Monitors cache fusion activity
Fusion V$GLOBAL_CACHE_STAT across RAC instances.
Data Guard V$DATAGUARD_STATUS, Monitors Data Guard status and
V$ARCHIVED_LOG log apply activity, including the
standby database.
Process/Session V$SESSION, V$PROCESS, Monitors individual processes
Information V$SESSION_WAIT, V$BACKGROUND and sessions, as well as the
background processes of RAC
nodes.
File System Status V$ASM_FILE, V$FILESTAT, V$DATABASE Monitors status and
performance of file systems and
tablespaces in the RAC system.
Locking V$LOCK, V$GES_STAT Monitors lock contention in the
Mechanism RAC environment (global
enqueues and local locks).
SQL Performance V$SQLAREA, V$SQL_PLAN, V$SQLSTATS Monitors SQL execution
in RAC performance in the RAC
environment, including plan
execution times and resource
usage.
Redo Transport V$ARCHIVE_DEST, Provides information about the
V$ARCHIVE_DEST_STATUS, status of redo log transport
V$DATAGUARD_STATUS across RAC instances, especially
for Data Guard setups.
Cache Fusion V$GLOBAL_CACHE_STATS, Monitors global cache fusion
V$GLOBAL_CACHE_TRANSFER, V$CACHE (GCF) and its transfer statistics in
a multi-node RAC environment.
Flashback V$FLASHBACK_LOG Provides status and statistics of
the flashback technology,
especially important for disaster
recovery.
Instance Failover V$INSTANCE_FAILOVER, Monitors instance failover
V$CLUSTER_DATABASE activity, and provides cluster
database health status.
Dynamic Database V$SERVICE_STATS, V$SERVICE Provides the status of dynamic
Services services, which can be moved or
relocated between nodes in a
RAC setup.
Node Failures V$NODE_FAILURE Monitors node failure status,
including details of a node going
down or being recovered in the
cluster.
Interconnect V$INTERCONNECT Monitors the latency between
Latency Oracle RAC instances connected
via the interconnect.
how you can read and understand an execution plan and check for performance issues beyond the
cost. I'll provide a detailed nested SQL example and explain how to interpret the execution plan using
different scenarios like full table scans, index scans, nested loops, joins, sorting, and more.
Steps to Analyze Execution Plan:
1. Check the Execution Order: The execution plan is a tree, and the order of operations starts
from the leaf nodes (most granular operations like full table scans or index scans) and goes
up to the root node (final result set).
2. Check Access Methods:
o Full Table Scan (FTS): Indicates a full scan of the table, which can be inefficient for
large tables.
o Index Scan: Using an index to retrieve data. This is faster than a full table scan, but it
depends on the selectivity of the index.
o Index Range Scan: A more efficient version of an index scan where only a subset of
index keys are retrieved.
o Index Unique Scan: Efficiently retrieves a single row based on a unique index.
3. Look at Join Methods:
o Nested Loop Join: Good for small result sets and index lookups.
o Merge Join: Typically used when both sides are sorted and when large result sets are
involved.
o Hash Join: Used for large datasets, particularly when the join condition is non-equi.
4. Look for Expensive Operations:
o Sorts: Sorting operations (especially large sorts) can be expensive and may require
temp space.
o Filters/Predicates: Conditions that filter out rows. If they are applied after expensive
joins, the cost will be higher.
5. Look for Missing Indexes: If there's a full table scan, it could indicate that an index could
improve the performance.
Sample Execution Plan:
Let’s break down the execution plan for this query. You can get the execution plan by running the
following:
EXPLAIN PLAN FOR
SELECT e.employee_id, e.first_name, e.last_name, d.department_name
FROM employees e
JOIN departments d
ON e.department_id = d.department_id
WHERE e.salary > 50000
ORDER BY e.last_name;
Here’s a simplified example of the execution plan (you would see more details in the real output):
To provide a comparison of the execution plans for the different approaches I shared (e.g., traditional
join, EXISTS, IN, WITH, CROSS JOIN, LEFT JOIN), I will explain how to analyze the execution plans in
Oracle for each query type. Then, I will describe the likely execution plan differences and
performance implications.
1. Execution Plan for Traditional Join
SQL:
SELECT e.employee_id, e.first_name, e.last_name, d.department_name
FROM employees e JOIN departments d ON e.department_id = d.department_id
WHERE e.salary > 50000;
Execution Plan:
When you use a standard JOIN, Oracle will most likely perform a Nested Loops Join or Hash Join,
depending on the data distribution and indexes. The execution plan might look like this:
Nested Loops is often used when the join condition is indexed, and the outer query fetches a
small result set.
Cost represents the relative cost of the operation. The lower the cost, the better.
2. Execution Plan for EXISTS
SQL:
Execution Plan:
In the case of EXISTS, Oracle will likely use a Semi Join or Correlated Subquery. Here's how the
execution plan might look:
Semi Join indicates that the subquery will return rows only once it finds a match, reducing
unnecessary processing.
Filter is used for subquery checks and will stop once it finds a match.
You're correct to point out that when using the EXISTS clause, Oracle may not necessarily choose
Hash Join, Merge Join, or Nested Loops Join depending on the query structure and data distribution.
Specifically, Full Table Scan (FTS) might be preferred, even if the columns involved in the query are
indexed.
Let's break down the reasoning behind this choice and the behavior of the EXISTS clause:
.
Example for such big query :
SELECT
c.customer_name,
SUM(o.order_total) AS total_sales,
COUNT(DISTINCT p.product_id) AS unique_products
FROM customers c
INNER JOIN orders o ON c.customer_id = o.customer_id
INNER JOIN order_details od ON o.order_id = od.order_id
INNER JOIN products p ON od.product_id = p.product_id
WHERE o.order_date BETWEEN TO_DATE('2023-01-01', 'YYYY-MM-DD') AND TO_DATE('2023-12-31',
'YYYY-MM-DD')
AND (p.product_category = 'Electronics' OR p.product_category = 'Clothing')
GROUP BY c.customer_name
HAVING COUNT(DISTINCT p.product_id) > 2
ORDER BY total_sales DESC;
Below is a tabular format with the columns Purpose, When to Use, Syntax, and Conditions for some
commonly used Oracle hints:
Hint Purpose When to Use Syntax Conditions
Use when an index is
SELECT /*+ INDEX(table_name available and
When you want to ensure
Forces the query index_name) */ column1 beneficial,
INDEX an index is used instead of a
to use an index FROM table_name WHERE particularly for large
full table scan (FTS).
column1 = value; tables with high
cardinality.
Use when the table is
small or has very few
When an index scan is not SELECT /*+ FULL(table_name)
Forces a full qualifying rows
FULL optimal and a full table scan */ column1 FROM table_name
table scan (FTS) where FTS may be
is faster. WHERE column2 = value;
more efficient than
an index scan.
SELECT /*+ USE_NL(table1 Best when the outer
When joining a small table
Forces a nested table2) */ column1 FROM table is small, making
USE_NL with a large one and nested
loop join table1, table2 WHERE the nested loop join
loops are ideal.
table1.col = table2.col; efficient.
Suitable when both
SELECT /*+ USE_MERGE(table1
When both tables are large tables are large, and
USE_ME Forces a merge table2) */ column1 FROM
and a merge join would be sorting or indexing
RGE join table1, table2 WHERE
more efficient. can be used to speed
table1.col = table2.col;
up the merge join.
SELECT /*+ USE_HASH(table1 Hash joins are ideal
USE_HA Forces a hash When neither table is sorted table2) */ column1 FROM for large tables
SH join and both are large. table1, table2 WHERE without indexes on
table1.col = table2.col; the join columns.
SELECT /*+ NO_MERGE(table1 Use if the optimizer's
NO_ME Prevents the use When a merge join would table2) */ column1 FROM automatic choice of a
RGE of a merge join be inefficient. table1, table2 WHERE merge join is causing
table1.col = table2.col; performance issues.
Use when the index
SELECT /*+
is poorly maintained
When an index is not NO_INDEX(table_name
NO_IND Prevents the use or when a full table
helpful or can cause index_name) */ column1
EX of an index scan might be more
inefficiency. FROM table_name WHERE
efficient than using
column1 = value;
an index.
Ensure your system
When the query is large or SELECT /*+ supports parallelism
PARALL Forces parallel complex and parallel PARALLEL(table_name, degree) (multiple CPUs,
EL execution execution would improve */ column1 FROM table_name sufficient resources).
speed. WHERE column2 = value; Useful for large
datasets.
SELECT /*+
STAR_T Use in a star schema
Forces star When joining a fact table STAR_TRANSFORMATION(table
RANSFO when a fact table is
transformation with multiple dimension 1 table2) */ column1 FROM
RMATIO joined with multiple
optimization tables (star schema). table1, table2 WHERE
N dimension tables.
table1.col = table2.col;
Use when the query
SELECT /*+ LEADING(table1
Specifies the When you want to control involves multiple
LEADIN table2) */ column1 FROM
join order the order of joins in a multi- joins, and the
G table1, table2 WHERE
explicitly table query. optimizer’s join order
table1.col = table2.col;
is suboptimal.
ORDERE Forces the When you need to enforce a SELECT /*+ ORDERED */ Use when the
D optimizer to use specific join order. column1 FROM table1, table2 optimizer does not
the join order as WHERE table1.col = table2.col; choose the best join
specified in the order, and the order
Hint Purpose When to Use Syntax Conditions
of joins needs to be
FROM clause
enforced.
Forces
Use when the
materialization
SELECT /*+ MATERIALIZE */ optimizer avoids
of a subquery When a subquery should be
MATERI column1 FROM (SELECT materializing a
(turns a materialized for better
ALIZE column1 FROM table1) subquery that could
subquery into a performance.
subquery; improve
temporary
performance.
table)
Use when sorting is
redundant or
When sorting operations are SELECT /*+ NO_SORT */ unnecessary, such as
NO_SO Prevents sorting
unnecessary and can be column1 FROM table_name when data is already
RT operations
avoided. WHERE column1 = value; sorted or sorting
operations are too
costly.
Here's a comparison of key access patterns between Oracle and PostgreSQL in a table format. The
comparison focuses on joins, table scans, and index usage in execution plans for both databases.
Access Oracle PostgreSQL
Pattern
Full Table Used when no index is available or Similar to Oracle. PostgreSQL uses a "Seq Scan"
Scan when a large portion of the table for full table scans.
needs to be accessed.
Index Scan INDEX RANGE SCAN, INDEX UNIQUE Index Scan and Index Only Scan for efficient data
SCAN, INDEX FULL SCAN. Can be retrieval using indexes.
range-based or unique-based scans.
Bitmap Index BITMAP INDEX SCAN, used for PostgreSQL doesn't natively support bitmap
Scan columns with low cardinality (e.g., indexes, but can simulate bitmap-based filtering
gender, status). using Bitmap Index Scan in certain cases with GIN
or GiST indexes.
Hash Join HASH JOIN, used for large, unsorted PostgreSQL also uses a Hash Join for joining large,
datasets, where a hash table is built unsorted datasets.
for one input table.
Merge Join SORT MERGE JOIN, when both Merge Join in PostgreSQL, similar to Oracle, when
inputs are sorted on the join key. inputs are pre-sorted or can be sorted.
Efficient for ordered data.
Nested Loop NESTED LOOP, common when one Nested Loop Join in PostgreSQL is used when
table is small or an index is used on there's a small outer relation or index on the inner
the inner table. relation.
Bitmap Index BITMAP INDEX AND, BITMAP INDEX PostgreSQL does not have direct bitmap indexing
Operations OR, combines multiple bitmap index but uses GIN (Generalized Inverted Index) or GiST
scans for complex conditions. (Generalized Search Tree) for similar operations.
Sort Merge A hybrid approach for joining sorted Merge Join in PostgreSQL, similar to Oracle, for
Join tables. More efficient when sorting joining sorted datasets.
is already done or possible.
Cartesian Join CROSS JOIN, occurs when no join Cross Join in PostgreSQL, same behavior.
condition is provided, resulting in a
cross product of rows.
Index Join Used when an index can directly Index Scan with Nested Loop for joining via index
retrieve rows for a nested loop or joins.
hash join.
Hash Anti Join HASH ANTI JOIN, used when the Anti Join can be simulated with NOT EXISTS or
first table's rows need to be LEFT JOIN with a filter in PostgreSQL.
returned only if there's no matching
row in the second table.
Hash Semi HASH SEMI JOIN, used to return Simulated in PostgreSQL using EXISTS or IN
Join rows from the first table if there is a clauses.
matching row in the second table.
Merge Anti SORT MERGE ANTI JOIN, a variant of Similar logic can be achieved with NOT EXISTS or
Join merge join for non-matching rows. LEFT JOIN with a filter.
Merge Semi SORT MERGE SEMI JOIN, returns Can be simulated in PostgreSQL with EXISTS or IN.
Join rows from the first table if there's a
match in the second table.
Clustered Join Usually occurs in specialized Not native in PostgreSQL. Can be simulated with
configurations like RAC, where partitioning or using table clustering based on a
tables are co-located for better specific index.
access.
Index Scan INDEX RANGE SCAN with additional Index Scan with additional WHERE conditions in
with Filter filters for more efficient lookups. the scan.
Clustered Used when Oracle finds that data is Not native in PostgreSQL. However, partitioning
Nested Loop co-located (usually in RAC setups), or parallel query execution can help reduce disk
reducing disk I/O. I/O.
Table Scan A table scan combined with an Seq Scan combined with Index Scan where an
with Index index filter. index is used to filter rows after the table scan.
Filter
Key Differences:
1. Bitmap Indexes: Oracle has built-in support for bitmap indexes, while PostgreSQL relies on
GIN and GiST indexes for similar functionality.
2. Clustered Joins: Oracle may use clustered joins in highly optimized environments (like RAC),
while PostgreSQL doesn't natively support this but can achieve similar effects using
partitioning or clustering.
3. Anti/Semi Joins: PostgreSQL does not have a native "anti join" or "semi join" operator in
execution plans, but they can be simulated using NOT EXISTS, LEFT JOIN, and IN clauses.
Overall, while both Oracle and PostgreSQL offer similar join and access patterns, Oracle provides
more fine-tuned options (like Bitmap Index Operations and Clustered Joins) out of the box, whereas
PostgreSQL relies on general-purpose strategies and flexible indexing systems (like GIN and GiST) to
achieve similar results.