How To Perform DBHealth Checkwith SQLScripts
How To Perform DBHealth Checkwith SQLScripts
How To Perform DBHealth Checkwith SQLScripts
Asfaw Gedamu
This guide outlines the procedures for performing various queries on an Oracle
Database.
Script 1:
SELECT
f.file_id,
f.file_name,
f.file_type,
f.tablespace_name,
f.create_date AS created_time
FROM dba_temp_files f;
Script 2:
SELECT file_id,
file_name,
ROUND(bytes/1024/1024/1024) AS size_gb,
ROUND(maxbytes/1024/1024/1024) AS max_size_gb,
autoextensible,
increment_by,
status
FROM dba_temp_files
ORDER BY file_name;
This script utilizes the dba_temp_files data dictionary view in Oracle Database:
Note:
Script 2:
SET LINESIZE 200
COLUMN username FORMAT A20
SELECT username,
session_addr,
session_num,
sqladdr,
sqlhash,
sql_id,
contents,
segtype,
extents,
blocks
FROM v$tempseg_usage
ORDER BY username;
• The script filters for ACTIVE sessions (s.status) that are currently using temporary space
(seg.bytes > 0).
• It joins the v$session and v$sort_segment_usage views based on the session_id to
associate session information with temporary segment usage.
• The script retrieves the following information:
o s.username: Username of the session owner.
o s.sid: Session ID.
o s.serial#: Serial number of the session.
o s.sql_id: (Optional) SQL ID of the statement using temporary space (requires
joining with v$sql_id).
o seg.segment_type: Type of temporary segment (e.g., 'SORT', 'HASH').
o seg.bytes / 1024 / 1024 AS used_mb: Total temporary space used by the session
in megabytes (MB).
o seg.bytes_used / 1024 / 1024 AS used_in_sort_mb: Space used by the session
specifically for sorting operations in MB.
Note:
Script 1:
SELECT
latch_name,
GETCOUNT(1) AS total_waits,
TIMEWAIT / 1000000000 AS total_wait_time_sec,
AVERAGE(TIMEWAIT / 1000000) AS avg_wait_time_ms
FROM v$latch
WHERE GETCOUNT(1) > 0
GROUP BY latch_name
ORDER BY total_waits DESC;
Script 2:
SELECT l.latch#,
l.name,
l.gets,
l.misses,
l.sleeps,
l.immediate_gets,
l.immediate_misses,
l.spin_gets
FROM v$latch l
WHERE l.misses > 0
ORDER BY l.misses DESC;
Explanation:
• These scripts utilizes the v$latch view, which provides information about latches in the
database.
• The script filters out latches with no waits using GETCOUNT(1) > 0.
• It then groups the results by latch_name and calculates the following:
o GETCOUNT(1) AS total_waits: Total number of times the latch was waited on.
o TIMEWAIT / 1000000000 AS total_wait_time_sec: Total time spent waiting on
the latch in seconds.
o AVERAGE(TIMEWAIT / 1000000) AS avg_wait_time_ms: Average time
spent waiting on the latch in milliseconds (ms).
• The script orders the results by total_waits in descending order, showing the top latches
with the most waits first.
Note:
While there's no single view in Oracle Database that directly tracks the total number of
executions for each session, you can combine information from different views to achieve a
similar outcome. Here's an approach:
Script 1:
WITH session_executions AS (
SELECT
s.username,
s.sid,
s.serial#,
s.sql_id,
COUNT(*) AS sql_executions
FROM v$session s
INNER JOIN v$sql e ON s.sid = e.sid
GROUP BY s.username, s.sid, s.serial#, s.sql_id
),
session_totals AS (
SELECT
username,
sid,
serial#,
SUM(sql_executions) AS total_executions
FROM session_executions
GROUP BY username, sid, serial#
)
SELECT
u.username,
st.sid,
st.serial#,
st.total_executions
FROM session_totals st
INNER JOIN dba_users u ON st.username = u.username
ORDER BY st.total_executions DESC;
Script 2:
SET PAGESIZE 14
Explanation:
Note:
• This script provides an estimate of total executions based on the available information. It
might not capture all executions, especially for short-lived sessions or statements that
haven't completed yet.
• You can modify the script to filter by specific users, sessions, or SQL IDs based on your
needs.
• Refer to the Oracle documentation for detailed information about the mentioned views:
o v$session: https://docs.oracle.com/en/database/oracle/oracle-database/19/refrn/V-
SESSION.html
o v$sql: https://docs.oracle.com/en/database/oracle/oracle-database/19/refrn/V-
SQL.html
o dba_users: https://docs.oracle.com/en/database/oracle/oracle-
database/19/refrn/DBA_USERS.html
Script 1:
WITH sql_executions AS (
SELECT
s.username,
s.sid,
s.serial#,
s.sql_id,
e.sql_text,
SUM(CASE WHEN e.elapsed_time_in_seconds > 0 THEN
e.elapsed_time_in_seconds ELSE 0 END) AS total_elapsed_time,
SUM(CASE WHEN e.cpu_time > 0 THEN e.cpu_time ELSE 0 END) AS
total_cpu_time,
SUM(CASE WHEN e.disk_reads > 0 THEN e.disk_reads ELSE 0 END)
AS total_disk_reads
FROM v$session s
INNER JOIN v$sql e ON s.sid = e.sid
GROUP BY s.username, s.sid, s.serial#, s.sql_id, e.sql_text
),
top_statements AS (
SELECT
username,
sql_id,
sql_text,
RANK() OVER (ORDER BY total_elapsed_time DESC) AS
elapsed_time_rank,
RANK() OVER (ORDER BY total_cpu_time DESC) AS cpu_time_rank,
RANK() OVER (ORDER BY total_disk_reads DESC) AS
disk_reads_rank
FROM sql_executions
)
SELECT
u.username,
t.sql_id,
t.sql_text,
CASE WHEN t.elapsed_time_rank = 1 THEN t.total_elapsed_time
END AS top_elapsed_time,
CASE WHEN t.cpu_time_rank = 1 THEN t.total_cpu_time END AS
top_cpu_time,
CASE WHEN t.disk_reads_rank = 1 THEN t.total_disk_reads END AS
top_disk_reads
FROM top_statements t
INNER JOIN dba_users u ON t.username = u.username
ORDER BY top_elapsed_time DESC, top_cpu_time DESC,
top_disk_reads DESC;
Script 2:
SELECT *
FROM (SELECT Substr(a.sql_text,1,50) sql_text,
Trunc(a.disk_reads/Decode(a.executions,0,1,a.executions))
reads_per_execution,
a.buffer_gets,
a.disk_reads,
a.executions,
a.sorts,
a.address
FROM v$sqlarea a
ORDER BY 2 DESC)
WHERE rownum <= &&1;
SET PAGESIZE 14
Explanation:
1. sql_executions CTE:
o Joins v$session and v$sql views to associate sessions with the SQL statements
they execute.
o Includes the sql_text column for the actual SQL statement.
o Aggregates data for each unique combination of user, session ID, serial number,
and SQL ID.
o Calculates the following for each SQL statement:
▪ SUM(CASE WHEN e.elapsed_time_in_seconds > 0 THEN
e.elapsed_time_in_seconds ELSE 0 END) AS total_elapsed_time: Total
elapsed time spent executing the statement (seconds).
▪ SUM(CASE WHEN e.cpu_time > 0 THEN e.cpu_time ELSE 0 END) AS
total_cpu_time: Total CPU time used by the statement.
▪ SUM(CASE WHEN e.disk_reads > 0 THEN e.disk_reads ELSE 0 END)
AS total_disk_reads: Total disk reads performed by the statement.
2. top_statements CTE:
o Uses window functions (RANK()) to assign ranks to each SQL statement based
on the resource usage:
▪ elapsed_time_rank: Rank based on total_elapsed_time (highest is 1).
▪ cpu_time_rank: Rank based on total_cpu_time (highest is 1).
▪ disk_reads_rank: Rank based on total_disk_reads (highest is 1).
3. Main Query:
o Joins top_statements with dba_users to obtain usernames.
o Selects username, sql_id, sql_text, and the top ranked values for each resource:
▪ CASE WHEN t.elapsed_time_rank = 1 THEN t.total_elapsed_time END
AS top_elapsed_time: Shows the total elapsed time only if it's the top
ranked statement.
▪ Similar logic is applied for top_cpu_time and top_disk_reads.
o Orders the results by top_elapsed_time (highest first), followed by top_cpu_time,
and then top_disk_reads.
Note:
• This script provides a basic overview of resource usage by SQL statements. The specific
resources might vary depending on the database version and configuration.
• You can modify it depending on your specific needs.
Script 1:
SET LINESIZE 200
SET TRIMOUT ON
SELECT e.runid,
e.event_seq,
TO_CHAR(e.event_time, 'DD-MON-YYYY HH24:MI:SS') AS
event_time,
e.event_unit_owner,
e.event_unit,
e.event_unit_kind,
e.proc_line,
e.event_comment
FROM plsql_trace_events e
WHERE e.runid = &1
ORDER BY e.runid, e.event_seq;
Script 2:
SELECT
tr.trace_id,
tr.db_user,
tr.status,
tr.begin_interval_time,
tr.end_interval_time,
te.event_id,
te.name AS event_name,
te.description AS event_description,
tf.session_id,
tf.username,
tf.sql_id,
tf.column_value1,
tf.column_value2,
tf.column_value3
FROM dba_traces tr
INNER JOIN dba_trace_events te ON tr.trace_id = te.trace_id
INNER JOIN dba_trace_files tf ON te.trace_id = tf.trace_id
WHERE tr.trace_id = <specified_trace_id>;
Explanation:
Note:
• This script provides a general overview of trace details. The specific columns and
information captured might differ depending on the events included in the trace definition
and the Oracle Database version.
• Replace <specified_trace_id> with the actual trace ID you want to analyze.
• Refer to the Oracle documentation for detailed information about the mentioned tables
and events:
o dba_traces: [invalid URL removed]
o dba_trace_events: [invalid URL removed]
o dba_trace_files: [invalid URL removed]
Query information on all trace runs
Script 1:
SET LINESIZE 200
SET TRIMOUT ON
SELECT runid,
run_date,
run_owner
FROM plsql_trace_runs
ORDER BY runid;
Script 2:
SELECT
tr.trace_id,
tr.db_user,
tr.status,
tr.begin_interval_time,
tr.end_interval_time
FROM dba_traces tr
ORDER BY tr.trace_id;
Explanation:
• This script queries the dba_traces table, which stores information about trace runs in the
database.
• It retrieves the following information for each trace run:
o tr.trace_id: Unique identifier for the trace run.
o tr.db_user: User who initiated the trace.
o tr.status: Current status of the trace (e.g., 'ACTIVE', 'COMPLETED').
o tr.begin_interval_time: Start time of the trace interval.
o tr.end_interval_time: End time of the trace interval (if available).
• The script orders the results by trace_id for easier identification and exploration.
Note:
• This script displays basic information about trace runs. You can use the trace_id retrieved
here to further analyze specific trace details using the script provided in the previous
response.
• Refer to the Oracle documentation for detailed information about the dba_traces table:
https://docs.oracle.com/cd/B10500_01/server.920/a96533/o_trace.htm
Script 1:
SELECT file_id,
file_name,
ROUND(bytes/1024/1024/1024) AS size_gb,
ROUND(maxbytes/1024/1024/1024) AS max_size_gb,
autoextensible,
increment_by,
status
FROM dba_data_files
WHERE tablespace_name = UPPER('&1')
ORDER BY file_id;
Script 2:
SELECT
df.file_id AS datafile_id,
df.file_name AS datafile_name,
df.tablespace_name,
df.file_size / 1024 / 1024 / 1024 AS file_size_gb,
df.autoextend_enabled AS autoextend
FROM dba_data_files df
WHERE df.tablespace_name = '<specified_tablespace_name>';
Explanation:
• The script utilizes the dba_data_files view, which contains information about datafiles in
the database.
• It filters the results based on the specified_tablespace_name provided.
• The script retrieves the following information for each datafile:
o df.file_id AS datafile_id: Unique identifier for the datafile.
o df.file_name AS datafile_name: Name of the datafile.
o df.tablespace_name: Tablespace associated with the datafile.
o df.file_size / 1024 / 1024 / 1024 AS file_size_gb: Size of the datafile in gigabytes
(GB).
o df.autoextend_enabled AS autoextend: Indicates whether autoextend is enabled
for the datafile (YES or NO).
Note:
• Replace <specified_tablespace_name> with the actual name of the tablespace you want
to investigate.
• This script provides basic information about datafiles. You can explore additional
attributes like free space or used space using other columns in the dba_data_files view.
• Refer to the Oracle documentation for detailed information about the dba_data_files
view: https://docs.oracle.com/en/database/oracle/oracle-
database/19/refrn/DBA_DATA_FILES.html
Query empty space in a tablespace or specific datafile
Script 1:
DECLARE
l_tablespace_name VARCHAR2(30) := UPPER('&1');
l_file_id VARCHAR2(30) := UPPER('&2');
CURSOR c_extents IS
SELECT owner,
segment_name,
file_id,
block_id AS start_block,
block_id + blocks - 1 AS end_block
FROM dba_extents
WHERE tablespace_name = l_tablespace_name
AND file_id = DECODE(l_file_id, 'ALL', file_id,
TO_NUMBER(l_file_id))
ORDER BY file_id, block_id;
l_block_size NUMBER := 0;
l_last_file_id NUMBER := 0;
l_last_block_id NUMBER := 0;
l_gaps_only BOOLEAN := TRUE;
l_total_blocks NUMBER := 0;
BEGIN
SELECT block_size
INTO l_block_size
FROM dba_tablespaces
WHERE tablespace_name = l_tablespace_name;
PROMPT
SET FEEDBACK ON
Script 2:
This approach utilizes two views to estimate the potential existence of gaps:
WITH datafile_info AS (
SELECT
df.file_id,
df.tablespace_name,
df.file_size / 1024 / 1024 / 1024 AS total_size_gb,
SUM(fs.bytes) / 1024 / 1024 / 1024 AS used_space_gb
FROM dba_data_files df
LEFT JOIN dba_free_space fs ON df.file_id = fs.file_id
GROUP BY df.file_id, df.tablespace_name, df.file_size
)
SELECT
di.file_id,
di.tablespace_name,
di.total_size_gb - di.used_space_gb AS potential_gap_gb
FROM datafile_info di
WHERE di.total_size_gb - di.used_space_gb > 0
ORDER BY potential_gap_gb DESC;
Explanation:
• This script uses a Common Table Expression (CTE) named datafile_info to:
o Join dba_data_files and dba_free_space views based on the file_id.
o Calculate total_size_gb and used_space_gb for each datafile.
• The main query:
o Selects file_id, tablespace_name, and the difference between total_size_gb and
used_space_gb as potential_gap_gb.
o Filters for datafiles with a positive potential_gap_gb, indicating potentially
unused space.
o Orders the results by potential_gap_gb in descending order.
Note:
• This approach estimates gaps based on the difference between the total file size and the
sum of free space extents. It may not accurately reflect actual gaps due to fragmentation
or how free space is managed internally.
• You can modify the script to focus on a specific tablespace by adding a filter on
tablespace_name in the datafile_info CTE.
2. Analyzing Extent Usage with dba_extents view:
SELECT
df.file_id,
df.tablespace_name,
fe.block_id,
fe.segment_type,
fe.segment_id,
fe.block_status,
fe.extent_id,
fe.block_size * fe.num_blocks / 1024 / 1024 AS extent_size_mb
FROM dba_data_files df
INNER JOIN dba_file_extents fe ON df.file_id = fe.file_id
ORDER BY df.file_id, fe.block_id;
Explanation:
• This approach requires manual inspection of the results to identify potential gaps. It
doesn't provide a direct and automated way to quantify empty space.
• Analyzing individual extents can be complex and time-consuming for large datafiles.
Script 1:
SET PAGESIZE 140 LINESIZE 200
COLUMN used_pct FORMAT A11
SELECT tablespace_name,
size_mb,
free_mb,
max_size_mb,
max_free_mb,
TRUNC((max_free_mb/max_size_mb) * 100) AS free_pct,
RPAD(' '|| RPAD('X',ROUND((max_size_mb-
max_free_mb)/max_size_mb*10,0), 'X'),11,'-') AS used_pct
FROM (
SELECT a.tablespace_name,
b.size_mb,
a.free_mb,
b.max_size_mb,
a.free_mb + (b.max_size_mb - b.size_mb) AS
max_free_mb
FROM (SELECT tablespace_name,
TRUNC(SUM(bytes)/1024/1024) AS free_mb
FROM dba_free_space
GROUP BY tablespace_name) a,
(SELECT tablespace_name,
TRUNC(SUM(bytes)/1024/1024) AS size_mb,
TRUNC(SUM(GREATEST(bytes,maxbytes))/1024/1024) AS max_size_mb
FROM dba_data_files
GROUP BY tablespace_name) b
WHERE a.tablespace_name = b.tablespace_name
)
ORDER BY tablespace_name;
SET PAGESIZE 14
Script 2:
SELECT
ts.tablespace_name,
ts.total_bytes / 1024 / 1024 / 1024 AS total_size_gb,
ts.used_bytes / 1024 / 1024 / 1024 AS used_space_gb,
(ts.used_bytes * 100) / ts.total_bytes AS used_percentage,
CASE
WHEN ts.used_bytes >= ts.max_bytes THEN 'FULL'
ELSE 'NOT FULL'
END AS status
FROM dba_tablespaces ts;
Explanation:
• The script utilizes the dba_tablespaces view, which contains information about
tablespaces in the database.
• It calculates the following for each tablespace:
o ts.total_bytes / 1024 / 1024 / 1024 AS total_size_gb: Total size of the tablespace
in gigabytes (GB).
o ts.used_bytes / 1024 / 1024 / 1024 AS used_space_gb: Used space in the
tablespace in gigabytes (GB).
o (ts.used_bytes * 100) / ts.total_bytes AS used_percentage: Percentage of used
space compared to the total size.
o CASE WHEN ts.used_bytes >= ts.max_bytes THEN 'FULL' ELSE 'NOT
FULL' END AS status: Status of the tablespace, indicating whether it's 'FULL'
or 'NOT FULL' based on the used space exceeding the maximum space allowed
(max_bytes).
Note:
• This script provides a basic overview of tablespace usage. You can modify it to filter
specific tablespaces, format the output differently, or calculate additional metrics based
on your needs.
• Refer to the Oracle documentation for detailed information about the dba_tablespaces
view: https://docs.oracle.com/en/database/oracle/oracle-
database/19/refrn/DBA_TABLESPACES.html
Script 1:
TRUNC(SUM(GREATEST(bytes,maxbytes))/1024/1024) AS max_size_mb
FROM dba_data_files
GROUP BY tablespace_name) b
WHERE a.tablespace_name = b.tablespace_name
)
WHERE ROUND((max_free_mb/max_size_mb) * 100,2) < 10;
SET PAGESIZE 14
Script 2:
SELECT
ts.tablespace_name,
ts.total_bytes / 1024 / 1024 / 1024 AS total_size_gb,
ts.used_bytes / 1024 / 1024 / 1024 AS used_space_gb,
(ts.used_bytes * 100) / ts.total_bytes AS used_percentage,
CASE
WHEN ts.used_bytes >= ts.max_bytes THEN 'FULL'
ELSE 'NEARLY FULL'
END AS status
FROM dba_tablespaces ts
WHERE (ts.used_bytes * 100) / ts.total_bytes >=
<threshold_percentage>;
Explanation:
• This script builds upon the previous script and adds a filter to identify nearly full
tablespaces.
• It utilizes the same calculations:
o Total size, used space, and used percentage.
o Status is modified to indicate 'FULL' if the used space is greater than or equal to
the maximum (max_bytes) and 'NEARLY FULL' if the used space as a
percentage of the total size is greater than or equal to a specified
threshold_percentage.
• Replace <threshold_percentage> with the desired percentage threshold for considering a
tablespace nearly full (e.g., 90, 95).
Note:
• This script provides a customizable way to identify tablespaces nearing capacity based on
a user-defined threshold.
• You can adjust the threshold_percentage to suit your specific needs and risk tolerance.
Script 1:
SET LINESIZE 200
SELECT tablespace_name,
contents,
extent_management,
threshold_type,
metrics_name,
warning_operator,
warning_value,
critical_operator,
critical_value
FROM dba_tablespace_thresholds
ORDER BY tablespace_name, metrics_name;
SET LINESIZE 80
Script 2:
SELECT
tablespace_name,
contents,
extent_management,
threshold_type,
metrics_name,
warning_operator,
warning_value,
critical_operator,
critical_value
FROM dba_tablespace_thresholds
ORDER BY tablespace_name, threshold_type, metrics_name;
Explanation:
Note:
• This script provides an overview of configured thresholds. You can use the information
obtained here to understand how tablespaces are monitored and when alerts might be
triggered based on resource usage.
• Refer to the Oracle documentation for detailed information about the
dba_tablespace_thresholds view: https://oracle-base.com/articles/misc/tablespace-
thresholds-and-alerts
Script 1:
DECLARE
g_warning_value VARCHAR2(4) := '&1';
g_warning_operator VARCHAR2(4) :=
DBMS_SERVER_ALERT.OPERATOR_GE;
g_critical_value VARCHAR2(4) := '&2';
g_critical_operator VARCHAR2(4) :=
DBMS_SERVER_ALERT.OPERATOR_GE;
Script 2:
DECLARE
l_tablespace_name VARCHAR2(30) := 'USERS'; -- Replace with
desired tablespace name
l_threshold_type VARCHAR2(30) := 'SPACE USAGE';
l_metrics_name VARCHAR2(30) := 'BYTES';
l_operator VARCHAR2(2) := 'GE'; -- Operator (e.g., GE, GT, LT,
etc.)
l_warning_value NUMBER := 90; -- Warning threshold value
(e.g., percentage used space)
BEGIN
DBMS_SPACE_ADMIN.SET_TABLESPACE_THRESHOLD(
tablespace_name => l_tablespace_name,
threshold_type => l_threshold_type,
metrics_name => l_metrics_name,
operator => l_operator,
warning_value => l_warning_value
);
Explanation:
Important Note:
• This script requires appropriate privileges (e.g., ALTER ANY TABLESPACE) to modify
tablespace thresholds. Use this script cautiously in a test environment before applying it
to a production system.
• Refer to the Oracle documentation for detailed information about the
DBMS_SPACE_ADMIN package and managing tablespace thresholds: [invalid URL
removed]
Script 1:
SET SERVEROUTPUT ON
SET LINESIZE 1000
SET FEEDBACK OFF
SELECT *
FROM v$database;
PROMPT
DECLARE
v_value NUMBER;
BEGIN
-- --------------------------
-- Dictionary Cache Hit Ratio
-- --------------------------
SELECT (1 - (Sum(getmisses)/(Sum(gets) + Sum(getmisses)))) *
100
INTO v_value
FROM v$rowcache;
DBMS_Output.Put('Dictionary Cache Hit Ratio : ' ||
Format(v_value));
IF v_value < 90 THEN
DBMS_Output.Put_Line('Increase SHARED_POOL_SIZE parameter to
bring value above 90%');
ELSE
DBMS_Output.Put_Line('Value Acceptable.');
END IF;
-- -----------------------
-- Library Cache Hit Ratio
-- -----------------------
SELECT (1 -(Sum(reloads)/(Sum(pins) + Sum(reloads)))) * 100
INTO v_value
FROM v$librarycache;
-- -------------------------------
-- DB Block Buffer Cache Hit Ratio
-- -------------------------------
SELECT (1 - (phys.value / (db.value + cons.value))) * 100
INTO v_value
FROM v$sysstat phys,
v$sysstat db,
v$sysstat cons
WHERE phys.name = 'physical reads'
AND db.name = 'db block gets'
AND cons.name = 'consistent gets';
-- ---------------
-- Latch Hit Ratio
-- ---------------
SELECT (1 - (Sum(misses) / Sum(gets))) * 100
INTO v_value
FROM v$latch;
-- -----------------------
-- Disk Sort Ratio
-- -----------------------
SELECT (disk.value/mem.value) * 100
INTO v_value
FROM v$sysstat disk,
v$sysstat mem
WHERE disk.name = 'sorts (disk)'
AND mem.name = 'sorts (memory)';
-- ----------------------
-- Rollback Segment Waits
-- ----------------------
SELECT (Sum(waits) / Sum(gets)) * 100
INTO v_value
FROM v$rollstat;
DBMS_Output.Put('Rollback Segment Waits : ' ||
Format(v_value));
IF v_value > 5 THEN
DBMS_Output.Put_Line('Increase number of Rollback Segments
to bring the value below 5%');
ELSE
DBMS_Output.Put_Line('Value acceptable.');
END IF;
-- -------------------
-- Dispatcher Workload
-- -------------------
SELECT NVL((Sum(busy) / (Sum(busy) + Sum(idle))) * 100,0)
INTO v_value
FROM v$dispatcher;
END;
/
PROMPT
SET FEEDBACK ON
Script 2:
SELECT
-- Database level
s.sid AS session_id,
s.serial# AS serial_number,
s.username,
s.machine AS client_machine,
s.status AS session_status,
s.sql_id AS current_sql_id,
e.wait_class,
e.wait_time_micro / 1000000 AS wait_time_seconds,
-- Comment on wait time
CASE
WHEN wait_time_seconds > 1 THEN 'Potential performance
bottleneck, investigate further.'
ELSE 'Normal wait time.'
END AS wait_time_comment,
-- CPU and I/O utilization
s.cpu_time / 1000000 AS cpu_time_seconds,
s.elapsed_time / 1000000 AS elapsed_time_seconds,
s.disk_reads,
-- Comment on I/O utilization
CASE
WHEN disk_reads > 1000 THEN 'High disk reads, consider
optimizing queries or adding indexes.'
ELSE 'Normal disk reads.'
END AS disk_reads_comment
FROM v$session s
INNER JOIN v$session_longops e ON s.sid = e.sid
ORDER BY wait_time_seconds DESC;
Explanation:
Note:
• The specific threshold values used for comments can be adjusted based on your system
characteristics and performance expectations.
• This script provides a starting point for identifying potential performance issues. Further
analysis and investigation might be needed to pinpoint the root cause of any observed
problems.
• Refer to the Oracle documentation for detailed information about the mentioned views:
o v$session: https://docs.oracle.com/en/database/oracle/oracle-database/19/refrn/V-
SESSION.html
o v$session_longops: https://docs.oracle.com/en/database/oracle/oracle-
database/19/refrn/V-SESSION_LONGOPS.html