2026-03-12 20:23:15
This commit is contained in:
730
tpt/exadata/exasnapper_install_latest.sql
Normal file
730
tpt/exadata/exasnapper_install_latest.sql
Normal file
@@ -0,0 +1,730 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- File name: exasnapper_install.sql (Exadata Snapper install) BETA
|
||||
--
|
||||
-- Purpose: Install required objects for the Session Snapper for Exadata tool
|
||||
--
|
||||
-- Author: Tanel Poder ( tanel.poder@enkitec.com | @tanelpoder )
|
||||
--
|
||||
-- Web: http://www.enkitec.com | http://blog.tanelpoder.com
|
||||
--
|
||||
-- Copyright: (c) 2012-2013 Tanel Poder. All Rights Reserved.
|
||||
--
|
||||
-- Disclaimer: This script is provided "as is", so no warranties or guarantees are
|
||||
-- made about its correctness, reliability and safety. Use it at your
|
||||
-- own risk!
|
||||
--
|
||||
-- Install: 1) Make sure that you have SELECT ANY DICTIONARY privileges
|
||||
-- or direct SELECT grants on the GV$ views referenced in this
|
||||
-- script
|
||||
--
|
||||
-- 2) Run @exasnapper_install.sql to create the objects
|
||||
--
|
||||
-- Usage: Take a snapshot of a running session (use QC SID if PX):
|
||||
--
|
||||
-- a) Monitor a running query - "DBA mode"
|
||||
--
|
||||
-- SELECT * FROM TABLE(exasnap.display_sid(<sid>, [snap_seconds], [detail_level]));
|
||||
--
|
||||
-- The SID argument can be just a number (SID in local instance) or a remote SID with
|
||||
-- @instance after it (like '123@4')
|
||||
--
|
||||
-- SELECT * FROM TABLE(exasnap.display_sid(123));
|
||||
-- SELECT * FROM TABLE(exasnap.display_sid('123@4', p_detail=>'%');
|
||||
--
|
||||
-- b) Take Before & After snapshots of a query execution - "Developer Mode"
|
||||
--
|
||||
-- 1) SELECT exasnap.begin_snap(123) FROM dual;
|
||||
-- or
|
||||
-- EXEC :begin_snap_id := exasnap.begin_snap(123);
|
||||
--
|
||||
-- 2) Run your query, wait until it finishes (or CTRL+C)
|
||||
--
|
||||
-- 3) SELECT exasnap.end_snap(123) FROM dual;
|
||||
-- or
|
||||
-- EXEC :end_snap_id := exasnap.end_snap(123);
|
||||
--
|
||||
-- 4) SELECT * FROM TABLE(exasnap.display_snap(:begin_snap_id, :end_snap_id, '%'));
|
||||
--
|
||||
--
|
||||
-- Other: This is still a pretty raw script in development and will
|
||||
-- probably change a lot once it reaches v1.0.
|
||||
--
|
||||
-- Exadata Snapper doesn't currently purge old data from its repository
|
||||
-- so if you use this version heavily, you may want to truncate the
|
||||
-- ex_ tables manually (should reporting get slow). I'll add the
|
||||
-- purging feature in the future.
|
||||
--
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
COL snap_name FOR A20
|
||||
COL snap_time FOR A30
|
||||
COL snap_type FOR A10
|
||||
COL taken_by FOR A10
|
||||
COL comm FOR A100
|
||||
|
||||
DROP TABLE ex_snapshot;
|
||||
DROP TABLE ex_session;
|
||||
DROP TABLE ex_sesstat;
|
||||
DROP SEQUENCE ex_snap_seq;
|
||||
DROP PACKAGE exasnap;
|
||||
DROP TYPE exastat_result_t;
|
||||
DROP TYPE exastat_result_r;
|
||||
DROP TYPE exastat_metrics_t;
|
||||
DROP TYPE exastat_metrics_r;
|
||||
|
||||
CREATE SEQUENCE ex_snap_seq ORDER NOCACHE;
|
||||
|
||||
CREATE TABLE ex_snapshot (
|
||||
snap_id NUMBER NOT NULL
|
||||
, snap_time TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL
|
||||
, snap_name VARCHAR2(100) NOT NULL
|
||||
, snap_type VARCHAR2(100) NOT NULL
|
||||
, taken_by VARCHAR2(100) DEFAULT user NOT NULL
|
||||
, comm VARCHAR2(4000)
|
||||
)
|
||||
/
|
||||
|
||||
ALTER TABLE ex_snapshot ADD CONSTRAINT ex_snapshot_pk PRIMARY KEY (snap_id);
|
||||
|
||||
CREATE TABLE ex_session (
|
||||
snap_id NUMBER NOT NULL
|
||||
, snap_time TIMESTAMP NOT NULL
|
||||
, inst_id NUMBER NOT NULL
|
||||
, sid NUMBER NOT NULL
|
||||
, serial# NUMBER NOT NULL
|
||||
, qc_inst NUMBER
|
||||
, qc_sid NUMBER
|
||||
, qc_serial# NUMBER
|
||||
, username VARCHAR2(100)
|
||||
, sql_id VARCHAR2(100)
|
||||
, dfo_tree NUMBER
|
||||
, server_set NUMBER
|
||||
, server# NUMBER
|
||||
, actual_degree NUMBER
|
||||
, requested_degree NUMBER
|
||||
, server_name VARCHAR2(100)
|
||||
, spid VARCHAR2(100)
|
||||
)
|
||||
/
|
||||
|
||||
ALTER TABLE ex_session ADD CONSTRAINT ex_session_pk PRIMARY KEY (snap_id, inst_id, sid, serial#);
|
||||
|
||||
|
||||
CREATE TABLE ex_sesstat (
|
||||
snap_id NUMBER NOT NULL
|
||||
, snap_time TIMESTAMP NOT NULL
|
||||
, inst_id NUMBER NOT NULL
|
||||
, sid NUMBER NOT NULL
|
||||
, serial# NUMBER NOT NULL
|
||||
, stat_name VARCHAR2(100) NOT NULL
|
||||
, value NUMBER NOT NULL
|
||||
)
|
||||
/
|
||||
|
||||
ALTER TABLE ex_sesstat ADD CONSTRAINT ex_sesstat_pk PRIMARY KEY (snap_id, inst_id, sid, serial#, stat_name);
|
||||
|
||||
CREATE OR REPLACE TYPE exastat_result_r AS OBJECT (name VARCHAR2(1000));
|
||||
/
|
||||
|
||||
CREATE OR REPLACE TYPE exastat_result_t AS TABLE OF exastat_result_r;
|
||||
/
|
||||
|
||||
CREATE OR REPLACE TYPE exastat_metrics_r AS OBJECT (
|
||||
inst_id NUMBER
|
||||
, sid NUMBER
|
||||
, type VARCHAR2(20)
|
||||
, category VARCHAR2(25)
|
||||
, name VARCHAR2(30)
|
||||
, delta_value NUMBER
|
||||
, delta_value_per_sec NUMBER
|
||||
, seconds_in_snap NUMBER
|
||||
);
|
||||
/
|
||||
CREATE OR REPLACE TYPE exastat_metrics_t AS TABLE OF exastat_metrics_r;
|
||||
/
|
||||
|
||||
CREATE OR REPLACE PACKAGE exasnap AS
|
||||
TYPE m_lookuptab_t IS TABLE OF exastat_metrics_r INDEX BY VARCHAR2(100);
|
||||
|
||||
FUNCTION begin_snap(p_sid IN VARCHAR2 DEFAULT TO_CHAR(SYS_CONTEXT('userenv','sid')), p_name IN VARCHAR2 DEFAULT user) RETURN NUMBER;
|
||||
FUNCTION end_snap (p_sid IN VARCHAR2 DEFAULT TO_CHAR(SYS_CONTEXT('userenv','sid')), p_name IN VARCHAR2 DEFAULT user) RETURN NUMBER;
|
||||
FUNCTION take_snap (p_sid IN VARCHAR2 DEFAULT TO_CHAR(SYS_CONTEXT('userenv','sid')), p_name IN VARCHAR2 DEFAULT user, p_snap_type IN VARCHAR2 DEFAULT 'SNAP', p_dblink IN VARCHAR2 DEFAULT NULL) RETURN NUMBER;
|
||||
|
||||
PROCEDURE begin_snap(p_sid IN VARCHAR2 DEFAULT TO_CHAR(SYS_CONTEXT('userenv','sid')), p_name IN VARCHAR2 DEFAULT user);
|
||||
PROCEDURE end_snap (p_sid IN VARCHAR2 DEFAULT TO_CHAR(SYS_CONTEXT('userenv','sid')), p_name IN VARCHAR2 DEFAULT user);
|
||||
PROCEDURE take_snap (p_sid IN VARCHAR2 DEFAULT TO_CHAR(SYS_CONTEXT('userenv','sid')), p_name IN VARCHAR2 DEFAULT user, p_snap_type IN VARCHAR2 DEFAULT 'SNAP');
|
||||
|
||||
FUNCTION get_delta_metrics(p_begin_snap IN NUMBER DEFAULT NULL, p_end_snap IN NUMBER DEFAULT NULL) RETURN exastat_metrics_t;
|
||||
FUNCTION display_snap(p_begin_snap IN NUMBER DEFAULT NULL, p_end_snap IN NUMBER DEFAULT NULL, p_detail IN VARCHAR2 DEFAULT 'BASIC' ) RETURN exastat_result_t PIPELINED;
|
||||
FUNCTION get_sid(p_sid IN VARCHAR2, p_interval IN NUMBER DEFAULT 5) RETURN exastat_metrics_t;
|
||||
FUNCTION display_sid(p_sid IN VARCHAR2, p_interval IN NUMBER DEFAULT 5, p_detail IN VARCHAR2 DEFAULT 'BASIC') RETURN exastat_result_t PIPELINED;
|
||||
FUNCTION monitor_sid(p_sid IN VARCHAR2, p_interval IN NUMBER DEFAULT 5, p_detail IN VARCHAR2 DEFAULT 'BASIC') RETURN exastat_result_t PIPELINED;
|
||||
|
||||
END exasnap;
|
||||
/
|
||||
SHOW ERR;
|
||||
|
||||
-- main
|
||||
CREATE OR REPLACE PACKAGE BODY exasnap AS
|
||||
|
||||
|
||||
FUNCTION begin_snap(p_sid IN VARCHAR2 DEFAULT TO_CHAR(SYS_CONTEXT('userenv','sid')), p_name IN VARCHAR2 DEFAULT user) RETURN NUMBER IS
|
||||
BEGIN
|
||||
RETURN take_snap(p_sid, p_name, 'BEGIN');
|
||||
END begin_snap;
|
||||
|
||||
FUNCTION end_snap(p_sid IN VARCHAR2 DEFAULT TO_CHAR(SYS_CONTEXT('userenv','sid')), p_name IN VARCHAR2 DEFAULT user) RETURN NUMBER IS
|
||||
BEGIN
|
||||
RETURN take_snap(p_sid, p_name, 'END');
|
||||
END end_snap;
|
||||
|
||||
FUNCTION take_snap(p_sid IN VARCHAR2 DEFAULT TO_CHAR(SYS_CONTEXT('userenv','sid')), p_name IN VARCHAR2 DEFAULT user, p_snap_type IN VARCHAR2 DEFAULT 'SNAP', p_dblink IN VARCHAR2 DEFAULT NULL)
|
||||
RETURN NUMBER IS
|
||||
PRAGMA AUTONOMOUS_TRANSACTION;
|
||||
seq NUMBER;
|
||||
ts TIMESTAMP := SYSTIMESTAMP;
|
||||
lv_sid NUMBER := TO_NUMBER(REGEXP_SUBSTR(p_sid, '^\d+'));
|
||||
lv_inst_id NUMBER := NVL(REPLACE(REGEXP_SUBSTR(p_sid, '@\d+'), '@', ''),SYS_CONTEXT('USERENV','INSTANCE'));
|
||||
BEGIN
|
||||
SELECT ex_snap_seq.NEXTVAL INTO seq FROM dual;
|
||||
|
||||
INSERT INTO ex_snapshot VALUES (seq, ts, p_name, p_snap_type, user, NULL);
|
||||
|
||||
INSERT INTO ex_session
|
||||
SELECT
|
||||
seq
|
||||
, ts
|
||||
, pxs.inst_id
|
||||
, pxs.sid
|
||||
, pxs.serial#
|
||||
, pxs.qcinst_id qc_inst
|
||||
, pxs.qcsid qc_sid
|
||||
, pxs.qcserial# qc_serial#
|
||||
, s.username username
|
||||
, s.sql_id
|
||||
, pxs.server_group dfo_tree
|
||||
, pxs.server_set
|
||||
, pxs.server#
|
||||
, pxs.degree actual_degree
|
||||
, pxs.req_degree requested_degree
|
||||
, p.server_name
|
||||
, p.spid
|
||||
FROM
|
||||
gv$px_session pxs
|
||||
, gv$session s
|
||||
, gv$px_process p
|
||||
WHERE
|
||||
pxs.qcsid = lv_sid
|
||||
AND pxs.qcinst_id = lv_inst_id
|
||||
--AND s.sid = pxs.qcsid
|
||||
AND s.sid = pxs.sid
|
||||
AND s.serial# = pxs.serial#
|
||||
--AND s.serial# = pxs.qcserial# -- null
|
||||
AND p.sid = pxs.sid
|
||||
AND pxs.inst_id = s.inst_id
|
||||
AND s.inst_id = p.inst_id
|
||||
UNION ALL
|
||||
SELECT
|
||||
seq
|
||||
, ts
|
||||
, s.inst_id
|
||||
, s.sid
|
||||
, s.serial#
|
||||
, null -- qcinst
|
||||
, null -- qcsid
|
||||
, null -- qcserial
|
||||
, s.username
|
||||
, s.sql_id
|
||||
, null -- dfo_tree (server_group)
|
||||
, null -- server_set
|
||||
, null -- server#
|
||||
, null -- degree
|
||||
, null -- req_degree
|
||||
, s.program -- server_name
|
||||
, p.spid
|
||||
FROM
|
||||
gv$session s
|
||||
, gv$process p
|
||||
WHERE
|
||||
s.inst_id = p.inst_id
|
||||
AND s.paddr = p.addr
|
||||
AND s.sid = lv_sid
|
||||
AND s.inst_id = lv_inst_id;
|
||||
|
||||
INSERT INTO ex_sesstat
|
||||
SELECT
|
||||
seq
|
||||
, ts
|
||||
, ss.inst_id
|
||||
, ss.sid
|
||||
, s.serial#
|
||||
, sn.name stat_name
|
||||
, ss.value
|
||||
FROM
|
||||
gv$sesstat ss
|
||||
, gv$statname sn
|
||||
, gv$session s
|
||||
WHERE
|
||||
ss.inst_id = s.inst_id
|
||||
AND ss.inst_id = sn.inst_id
|
||||
AND s.inst_id = sn.inst_id
|
||||
AND s.sid = ss.sid
|
||||
AND sn.statistic# = ss.statistic#
|
||||
AND (s.inst_id, s.sid, s.serial#) IN (SELECT inst_id, sid, serial# FROM ex_session WHERE snap_id = seq)
|
||||
AND (ss.inst_id, ss.sid) IN (SELECT inst_id, sid FROM ex_session WHERE snap_id = seq);
|
||||
|
||||
IF p_snap_type IN ('BEGIN','END') THEN
|
||||
NULL;
|
||||
ELSE
|
||||
NULL;
|
||||
END IF;
|
||||
|
||||
COMMIT;
|
||||
|
||||
RETURN seq;
|
||||
END take_snap;
|
||||
|
||||
PROCEDURE begin_snap(p_sid IN VARCHAR2 DEFAULT TO_CHAR(SYS_CONTEXT('userenv','sid')), p_name IN VARCHAR2 DEFAULT user) IS
|
||||
tmp_id NUMBER;
|
||||
BEGIN
|
||||
tmp_id := begin_snap(p_sid);
|
||||
END begin_snap;
|
||||
|
||||
PROCEDURE end_snap(p_sid IN VARCHAR2 DEFAULT TO_CHAR(SYS_CONTEXT('userenv','sid')), p_name IN VARCHAR2 DEFAULT user) IS
|
||||
tmp_id NUMBER;
|
||||
BEGIN
|
||||
tmp_id := end_snap(p_sid);
|
||||
END end_snap;
|
||||
|
||||
PROCEDURE take_snap(p_sid IN VARCHAR2 DEFAULT TO_CHAR(SYS_CONTEXT('userenv','sid')), p_name IN VARCHAR2 DEFAULT user, p_snap_type IN VARCHAR2 DEFAULT 'SNAP') IS
|
||||
tmp_id NUMBER;
|
||||
BEGIN
|
||||
tmp_id := take_snap(p_sid, p_name, 'SNAP');
|
||||
END take_snap;
|
||||
|
||||
FUNCTION get_delta_metrics(p_begin_snap IN NUMBER DEFAULT NULL, p_end_snap IN NUMBER DEFAULT NULL) RETURN exastat_metrics_t IS
|
||||
lv_m exastat_metrics_t;
|
||||
lv_blocksize NUMBER := 8192;
|
||||
lv_asm_mirrors NUMBER := 2;
|
||||
BEGIN
|
||||
WITH stats AS (
|
||||
SELECT
|
||||
stat_name name
|
||||
, SUM(delta) value
|
||||
, AVG(snap_seconds) snap_seconds -- is the same for all records in this snap_id
|
||||
FROM (
|
||||
SELECT
|
||||
esn1.snap_id
|
||||
, esn1.snap_time begin_snap_time
|
||||
, esn2.snap_time end_snap_time
|
||||
, esn2.snap_time - esn1.snap_time snap_interval
|
||||
, TO_NUMBER(EXTRACT(second from esn2.snap_time - esn1.snap_time)) +
|
||||
TO_NUMBER(EXTRACT(minute from esn2.snap_time - esn1.snap_time)) * 60 +
|
||||
TO_NUMBER(EXTRACT(hour from esn2.snap_time - esn1.snap_time)) * 60 * 60 +
|
||||
TO_NUMBER(EXTRACT(day from esn2.snap_time - esn1.snap_time)) * 60 * 60 * 24 snap_seconds
|
||||
, esn1.snap_name begin_snap_name
|
||||
, esn2.snap_name end_snap_name
|
||||
, ess1.stat_name
|
||||
, ess1.value begin_value
|
||||
, ess2.value end_value
|
||||
, ess2.value - ess1.value delta
|
||||
FROM
|
||||
ex_snapshot esn1
|
||||
, ex_session es1
|
||||
, ex_sesstat ess1
|
||||
, ex_snapshot esn2
|
||||
, ex_session es2
|
||||
, ex_sesstat ess2
|
||||
WHERE
|
||||
-- snap_id
|
||||
esn1.snap_id = es1.snap_id
|
||||
AND ess1.snap_id = esn1.snap_id
|
||||
AND es1.snap_id = ess1.snap_id
|
||||
AND es1.inst_id = ess1.inst_id
|
||||
AND es1.sid = ess1.sid
|
||||
AND es1.serial# = ess1.serial#
|
||||
--
|
||||
AND esn2.snap_id = es2.snap_id
|
||||
AND es2.snap_id = ess2.snap_id
|
||||
AND ess2.snap_id = esn2.snap_id
|
||||
AND es2.inst_id = ess2.inst_id
|
||||
AND es2.sid = ess2.sid
|
||||
AND es2.serial# = ess2.serial#
|
||||
AND ess1.stat_name = ess2.stat_name
|
||||
AND ess1.inst_id = ess2.inst_id
|
||||
AND ess1.sid = ess2.sid
|
||||
AND ess1.serial# = ess2.serial#
|
||||
--
|
||||
AND esn1.snap_id = p_begin_snap
|
||||
AND esn2.snap_id = p_end_snap
|
||||
--
|
||||
-- AND ess2.value - ess1.value != 0 -- for testing
|
||||
)
|
||||
GROUP BY
|
||||
stat_name
|
||||
),
|
||||
sq AS (
|
||||
SELECT
|
||||
*
|
||||
FROM (
|
||||
SELECT
|
||||
0 inst_id
|
||||
, 0 sid
|
||||
, CASE WHEN TRIM(name) IN (
|
||||
'cell physical IO bytes sent directly to DB node to balance CPU'
|
||||
, 'cell physical IO bytes pushed back due to excessive CPU on cell'
|
||||
, 'cell physical IO bytes sent directly to DB node to balanceCPU u'
|
||||
) THEN
|
||||
'cell physical IO bytes sent directly to DB node to balance CPU'
|
||||
ELSE name
|
||||
END name
|
||||
, value
|
||||
FROM
|
||||
--gv$sesstat NATURAL JOIN v$statname
|
||||
stats
|
||||
WHERE
|
||||
1=1
|
||||
-- AND (name LIKE 'cell%bytes%' OR name LIKE 'physical%bytes%')
|
||||
AND TRIM(name) IN (
|
||||
'physical read total bytes'
|
||||
, 'physical write total bytes'
|
||||
, 'physical read total bytes optimized'
|
||||
, 'cell physical IO bytes eligible for predicate offload'
|
||||
, 'cell physical IO interconnect bytes'
|
||||
, 'cell physical IO interconnect bytes returned by smart scan'
|
||||
, 'cell physical IO bytes saved by storage index'
|
||||
, 'cell IO uncompressed bytes'
|
||||
, 'cell blocks processed by cache layer'
|
||||
, 'cell blocks processed by txn layer'
|
||||
, 'cell blocks processed by data layer'
|
||||
, 'cell blocks processed by index layer'
|
||||
, 'db block gets from cache'
|
||||
, 'consistent gets from cache'
|
||||
, 'db block gets direct'
|
||||
, 'consistent gets direct'
|
||||
-- following three stats are the same thing (named differently in different versions)
|
||||
, 'cell physical IO bytes sent directly to DB node to balance CPU'
|
||||
, 'cell physical IO bytes pushed back due to excessive CPU on cell'
|
||||
, 'cell physical IO bytes sent directly to DB node to balanceCPU u'
|
||||
, 'bytes sent via SQL*Net to client'
|
||||
, 'bytes received via SQL*Net from client'
|
||||
, 'table fetch continued row'
|
||||
, 'chained rows skipped by cell'
|
||||
, 'chained rows processed by cell'
|
||||
, 'chained rows rejected by cell'
|
||||
)
|
||||
)
|
||||
PIVOT (
|
||||
SUM(value)
|
||||
FOR name IN (
|
||||
'physical read total bytes' AS phyrd_bytes
|
||||
, 'physical write total bytes' AS phywr_bytes
|
||||
, 'physical read total bytes optimized' AS phyrd_optim_bytes
|
||||
, 'cell physical IO bytes eligible for predicate offload' AS pred_offloadable_bytes
|
||||
, 'cell physical IO interconnect bytes' AS interconnect_bytes
|
||||
, 'cell physical IO interconnect bytes returned by smart scan' AS smart_scan_ret_bytes
|
||||
, 'cell physical IO bytes saved by storage index' AS storidx_saved_bytes
|
||||
, 'cell IO uncompressed bytes' AS uncompressed_bytes
|
||||
, 'cell blocks processed by cache layer' AS cell_proc_cache_blk
|
||||
, 'cell blocks processed by txn layer' AS cell_proc_txn_blk
|
||||
, 'cell blocks processed by data layer' AS cell_proc_data_blk
|
||||
, 'cell blocks processed by index layer' AS cell_proc_index_blk
|
||||
, 'db block gets from cache' AS curr_gets_cache_blk
|
||||
, 'consistent gets from cache' AS cons_gets_cache_blk
|
||||
, 'db block gets direct' AS curr_gets_direct_blk
|
||||
, 'consistent gets direct' AS cons_gets_direct_blk
|
||||
, 'cell physical IO bytes sent directly to DB node to balance CPU' AS cell_bal_cpu_bytes
|
||||
, 'bytes sent via SQL*Net to client' AS net_to_client_bytes
|
||||
, 'bytes received via SQL*Net from client' AS net_from_client_bytes
|
||||
, 'table fetch continued row' AS chain_fetch_cont_row
|
||||
, 'chained rows skipped by cell' AS chain_rows_skipped
|
||||
, 'chained rows processed by cell' AS chain_rows_processed
|
||||
, 'chained rows rejected by cell' AS chain_rows_rejected
|
||||
)
|
||||
)
|
||||
),
|
||||
precalc AS (
|
||||
SELECT
|
||||
inst_id
|
||||
, sid
|
||||
, (phyrd_bytes) db_physrd_BYTES
|
||||
, (phywr_bytes) db_physwr_BYTES
|
||||
, (phyrd_bytes+phywr_bytes) db_physio_BYTES
|
||||
, pred_offloadable_bytes pred_offloadable_BYTES
|
||||
, phyrd_optim_bytes phyrd_optim_BYTES
|
||||
, (phyrd_optim_bytes-storidx_saved_bytes) phyrd_flash_rd_BYTES
|
||||
, storidx_saved_bytes phyrd_storidx_saved_BYTES
|
||||
, (phyrd_bytes-phyrd_optim_bytes) spin_disk_rd_BYTES
|
||||
, (phyrd_bytes-phyrd_optim_bytes+(phywr_bytes*lv_asm_mirrors)) spin_disk_io_BYTES
|
||||
, uncompressed_bytes scanned_uncomp_BYTES
|
||||
, interconnect_bytes total_ic_BYTES
|
||||
, smart_scan_ret_bytes smart_scan_ret_BYTES
|
||||
, (interconnect_bytes-smart_scan_ret_bytes) non_smart_scan_BYTES
|
||||
, (cell_proc_cache_blk * lv_blocksize) cell_proc_cache_BYTES
|
||||
, (cell_proc_txn_blk * lv_blocksize) cell_proc_txn_BYTES
|
||||
, (cell_proc_data_blk * lv_blocksize) cell_proc_data_BYTES
|
||||
, (cell_proc_index_blk * lv_blocksize) cell_proc_index_BYTES
|
||||
, (curr_gets_cache_blk * lv_blocksize) curr_gets_cache_BYTES
|
||||
, (cons_gets_cache_blk * lv_blocksize) cons_gets_cache_BYTES
|
||||
, (curr_gets_direct_blk * lv_blocksize) curr_gets_direct_BYTES
|
||||
, (cons_gets_direct_blk * lv_blocksize) cons_gets_direct_BYTES
|
||||
, cell_bal_cpu_bytes cell_bal_cpu_BYTES
|
||||
, net_to_client_bytes net_to_client_BYTES
|
||||
, net_from_client_bytes net_from_client_BYTES
|
||||
, chain_fetch_cont_row
|
||||
, chain_rows_skipped
|
||||
, chain_rows_processed
|
||||
, chain_rows_rejected
|
||||
, (chain_rows_skipped * lv_blocksize) chain_blocks_skipped
|
||||
, (chain_rows_processed * lv_blocksize) chain_blocks_processed
|
||||
, (chain_rows_rejected * lv_blocksize) chain_blocks_rejected
|
||||
FROM sq
|
||||
),
|
||||
precalc2 AS (
|
||||
SELECT
|
||||
inst_id
|
||||
, sid
|
||||
, db_physio_BYTES
|
||||
, db_physrd_BYTES
|
||||
, db_physwr_BYTES
|
||||
, pred_offloadable_BYTES
|
||||
, phyrd_optim_BYTES
|
||||
, phyrd_flash_rd_BYTES + spin_disk_rd_BYTES phyrd_disk_and_flash_BYTES
|
||||
, phyrd_flash_rd_BYTES
|
||||
, phyrd_storidx_saved_BYTES
|
||||
, spin_disk_io_BYTES
|
||||
, spin_disk_rd_BYTES
|
||||
, ((spin_disk_io_BYTES - spin_disk_rd_BYTES)) AS spin_disk_wr_BYTES
|
||||
, scanned_uncomp_BYTES
|
||||
, ROUND((scanned_uncomp_BYTES/NULLIF(phyrd_flash_rd_BYTES+spin_disk_rd_BYTES, 0))*db_physrd_BYTES) est_full_uncomp_BYTES
|
||||
, total_ic_BYTES
|
||||
, smart_scan_ret_BYTES
|
||||
, non_smart_scan_BYTES
|
||||
, cell_proc_cache_BYTES
|
||||
, cell_proc_txn_BYTES
|
||||
, cell_proc_data_BYTES
|
||||
, cell_proc_index_BYTES
|
||||
, cell_bal_cpu_BYTES
|
||||
, curr_gets_cache_BYTES
|
||||
, cons_gets_cache_BYTES
|
||||
, curr_gets_direct_BYTES
|
||||
, cons_gets_direct_BYTES
|
||||
, net_to_client_BYTES
|
||||
, net_from_client_BYTES
|
||||
, chain_fetch_cont_row
|
||||
, chain_rows_skipped
|
||||
, chain_rows_processed
|
||||
, chain_rows_rejected
|
||||
, chain_blocks_skipped
|
||||
, chain_blocks_processed
|
||||
, chain_blocks_rejected
|
||||
FROM
|
||||
precalc
|
||||
),
|
||||
unpivoted AS (
|
||||
SELECT * FROM precalc2
|
||||
UNPIVOT (
|
||||
BYTES
|
||||
FOR metric
|
||||
IN (
|
||||
phyrd_optim_BYTES
|
||||
, phyrd_disk_and_flash_BYTES
|
||||
, phyrd_flash_rd_BYTES
|
||||
, phyrd_storidx_saved_BYTES
|
||||
, spin_disk_rd_BYTES
|
||||
, spin_disk_wr_BYTES
|
||||
, spin_disk_io_BYTES
|
||||
, db_physrd_BYTES
|
||||
, db_physwr_BYTES
|
||||
, db_physio_BYTES
|
||||
, scanned_uncomp_BYTES
|
||||
, est_full_uncomp_BYTES
|
||||
, non_smart_scan_BYTES
|
||||
, smart_scan_ret_BYTES
|
||||
, total_ic_BYTES
|
||||
, pred_offloadable_BYTES
|
||||
, cell_proc_cache_BYTES
|
||||
, cell_proc_txn_BYTES
|
||||
, cell_proc_data_BYTES
|
||||
, cell_proc_index_BYTES
|
||||
, cell_bal_cpu_BYTES
|
||||
, curr_gets_cache_BYTES
|
||||
, cons_gets_cache_BYTES
|
||||
, curr_gets_direct_BYTES
|
||||
, cons_gets_direct_BYTES
|
||||
, net_to_client_BYTES
|
||||
, net_from_client_BYTES
|
||||
, chain_fetch_cont_row
|
||||
, chain_rows_skipped
|
||||
, chain_rows_processed
|
||||
, chain_rows_rejected
|
||||
, chain_blocks_skipped
|
||||
, chain_blocks_processed
|
||||
, chain_blocks_rejected
|
||||
)
|
||||
)
|
||||
),
|
||||
metric AS (
|
||||
SELECT 'BASIC' type, 'DB_LAYER_IO' category, 'DB_PHYSIO_BYTES' name FROM dual UNION ALL
|
||||
SELECT 'BASIC', 'DB_LAYER_IO', 'DB_PHYSRD_BYTES' FROM dual UNION ALL
|
||||
SELECT 'BASIC', 'DB_LAYER_IO', 'DB_PHYSWR_BYTES' FROM dual UNION ALL
|
||||
SELECT 'ADVANCED', 'AVOID_DISK_IO', 'PHYRD_OPTIM_BYTES' FROM dual UNION ALL
|
||||
SELECT 'ADVANCED', 'AVOID_DISK_IO', 'PHYRD_DISK_AND_FLASH_BYTES' FROM dual UNION ALL
|
||||
SELECT 'BASIC', 'AVOID_DISK_IO', 'PHYRD_FLASH_RD_BYTES' FROM dual UNION ALL
|
||||
SELECT 'BASIC', 'AVOID_DISK_IO', 'PHYRD_STORIDX_SAVED_BYTES' FROM dual UNION ALL
|
||||
SELECT 'BASIC', 'REAL_DISK_IO', 'SPIN_DISK_IO_BYTES' FROM dual UNION ALL
|
||||
SELECT 'BASIC', 'REAL_DISK_IO', 'SPIN_DISK_RD_BYTES' FROM dual UNION ALL
|
||||
SELECT 'BASIC', 'REAL_DISK_IO', 'SPIN_DISK_WR_BYTES' FROM dual UNION ALL
|
||||
SELECT 'ADVANCED', 'COMPRESS', 'SCANNED_UNCOMP_BYTES' FROM dual UNION ALL
|
||||
SELECT 'ADVANCED', 'COMPRESS', 'EST_FULL_UNCOMP_BYTES' FROM dual UNION ALL
|
||||
SELECT 'BASIC', 'REDUCE_INTERCONNECT', 'PRED_OFFLOADABLE_BYTES' FROM dual UNION ALL
|
||||
SELECT 'BASIC', 'REDUCE_INTERCONNECT', 'TOTAL_IC_BYTES' FROM dual UNION ALL
|
||||
SELECT 'BASIC', 'REDUCE_INTERCONNECT', 'SMART_SCAN_RET_BYTES' FROM dual UNION ALL
|
||||
SELECT 'BASIC', 'REDUCE_INTERCONNECT', 'NON_SMART_SCAN_BYTES' FROM dual UNION ALL
|
||||
SELECT 'ADVANCED', 'CELL_PROC_DEPTH', 'CELL_PROC_CACHE_BYTES' FROM DUAL UNION ALL
|
||||
SELECT 'ADVANCED', 'CELL_PROC_DEPTH', 'CELL_PROC_TXN_BYTES' FROM DUAL UNION ALL
|
||||
SELECT 'BASIC', 'CELL_PROC_DEPTH', 'CELL_PROC_DATA_BYTES' FROM DUAL UNION ALL
|
||||
SELECT 'BASIC', 'CELL_PROC_DEPTH', 'CELL_PROC_INDEX_BYTES' FROM DUAL UNION ALL
|
||||
SELECT 'ADVANCED', 'CELL_PROC_DEPTH', 'CELL_BAL_CPU_BYTES' FROM DUAL UNION ALL
|
||||
SELECT 'ADVANCED', 'IN_DB_PROCESSING', 'CURR_GETS_CACHE_BYTES' FROM DUAL UNION ALL
|
||||
SELECT 'ADVANCED', 'IN_DB_PROCESSING', 'CONS_GETS_CACHE_BYTES' FROM DUAL UNION ALL
|
||||
SELECT 'ADVANCED', 'IN_DB_PROCESSING', 'CURR_GETS_DIRECT_BYTES' FROM DUAL UNION ALL
|
||||
SELECT 'ADVANCED', 'IN_DB_PROCESSING', 'CONS_GETS_DIRECT_BYTES' FROM DUAL UNION ALL
|
||||
SELECT 'BASIC', 'CLIENT_COMMUNICATION', 'NET_TO_CLIENT_BYTES' FROM DUAL UNION ALL
|
||||
SELECT 'BASIC', 'CLIENT_COMMUNICATION', 'NET_FROM_CLIENT_BYTES' FROM DUAL UNION ALL
|
||||
SELECT 'ADVANCED', 'FALLBACK_TO_BLOCK_IO', 'CHAIN_FETCH_CONT_ROW' FROM DUAL UNION ALL
|
||||
SELECT 'ADVANCED', 'FALLBACK_TO_BLOCK_IO', 'CHAIN_ROWS_SKIPPED' FROM DUAL UNION ALL
|
||||
SELECT 'ADVANCED', 'FALLBACK_TO_BLOCK_IO', 'CHAIN_ROWS_PROCESSED' FROM DUAL UNION ALL
|
||||
SELECT 'ADVANCED', 'FALLBACK_TO_BLOCK_IO', 'CHAIN_ROWS_REJECTED' FROM DUAL UNION ALL
|
||||
SELECT 'ADVANCED', 'FALLBACK_TO_BLOCK_IO', 'CHAIN_BLOCKS_SKIPPED' FROM DUAL UNION ALL
|
||||
SELECT 'ADVANCED', 'FALLBACK_TO_BLOCK_IO', 'CHAIN_BLOCKS_PROCESSED' FROM DUAL UNION ALL
|
||||
SELECT 'ADVANCED', 'FALLBACK_TO_BLOCK_IO', 'CHAIN_BLOCKS_REJECTED' FROM DUAL
|
||||
)
|
||||
SELECT
|
||||
exastat_metrics_r (
|
||||
inst_id
|
||||
, sid
|
||||
, type
|
||||
, category
|
||||
, metric
|
||||
, bytes
|
||||
, bytes_sec
|
||||
, seconds_in_snap
|
||||
)
|
||||
BULK COLLECT INTO lv_m
|
||||
FROM (
|
||||
SELECT
|
||||
inst_id
|
||||
, sid
|
||||
, type
|
||||
, category
|
||||
, metric
|
||||
, bytes
|
||||
, BYTES / (SELECT snap_seconds FROM stats WHERE rownum = 1) bytes_sec
|
||||
, (SELECT snap_seconds FROM stats WHERE rownum = 1) seconds_in_snap
|
||||
FROM
|
||||
unpivoted u
|
||||
, metric m
|
||||
WHERE
|
||||
u.metric = m.name
|
||||
)
|
||||
;
|
||||
|
||||
RETURN lv_m;
|
||||
|
||||
END get_delta_metrics;
|
||||
|
||||
FUNCTION gen_lookuptab(p_metrics IN exastat_metrics_t) RETURN m_lookuptab_t IS
|
||||
lv_m m_lookuptab_t;
|
||||
lv_m_id VARCHAR2(100);
|
||||
BEGIN
|
||||
FOR i IN 1 .. p_metrics.COUNT LOOP
|
||||
lv_m_id := TRIM(TO_CHAR(p_metrics(i).inst_id))||','
|
||||
|| TRIM(TO_CHAR(p_metrics(i).sid ))||','
|
||||
|| TRIM( p_metrics(i).name );
|
||||
lv_m(lv_m_id) := p_metrics(i);
|
||||
END LOOP;
|
||||
RETURN lv_m;
|
||||
END;
|
||||
|
||||
FUNCTION display_snap(p_begin_snap IN NUMBER DEFAULT NULL, p_end_snap IN NUMBER DEFAULT NULL, p_detail IN VARCHAR2 DEFAULT 'BASIC' ) RETURN exastat_result_t PIPELINED IS
|
||||
ml m_lookuptab_t;
|
||||
m exastat_metrics_t;
|
||||
str VARCHAR2(200);
|
||||
max_bytes NUMBER;
|
||||
BEGIN
|
||||
ml := gen_lookuptab(get_delta_metrics(p_begin_snap, p_end_snap));
|
||||
m := get_delta_metrics(p_begin_snap, p_end_snap);
|
||||
|
||||
SELECT MAX(delta_value) INTO max_bytes FROM TABLE(CAST(m AS exastat_metrics_t)) WHERE type LIKE p_detail;
|
||||
|
||||
str := '-- ExaSnapper v0.81 BETA by Tanel Poder @ Enkitec - The Exadata Experts ( http://www.enkitec.com )';
|
||||
PIPE ROW(exastat_result_r(str));
|
||||
str := LPAD('-',153,'-');
|
||||
PIPE ROW(exastat_result_r(str));
|
||||
|
||||
FOR i IN 1..m.COUNT LOOP
|
||||
IF m(i).type LIKE p_detail THEN
|
||||
str := RPAD(m(i).category, 30)||' '||RPAD(m(i).name, 30)||'|'|| RPAD(NVL(RPAD('#', ROUND(m(i).delta_value / NULLIF(max_bytes , 0) * 50 ), '#'), ' '), 50, ' ')||'|';
|
||||
str := str || LPAD(ROUND(m(i).delta_value/1048576), 15) ||' MB';
|
||||
str := str || LPAD(ROUND(m(i).delta_value_per_sec/1048576), 15) ||' MB/sec';
|
||||
PIPE ROW(exastat_result_r(str));
|
||||
END IF;
|
||||
END LOOP;
|
||||
END display_snap;
|
||||
|
||||
FUNCTION get_sid(p_sid IN VARCHAR2, p_interval IN NUMBER DEFAULT 5) RETURN exastat_metrics_t IS
|
||||
lv_begin NUMBER;
|
||||
lv_end NUMBER;
|
||||
BEGIN
|
||||
lv_begin := BEGIN_SNAP(p_sid);
|
||||
DBMS_LOCK.SLEEP(p_interval);
|
||||
lv_end := END_SNAP(p_sid);
|
||||
RETURN get_delta_metrics(lv_begin, lv_end);
|
||||
END get_sid;
|
||||
|
||||
FUNCTION display_sid(p_sid IN VARCHAR2, p_interval IN NUMBER DEFAULT 5, p_detail IN VARCHAR2 DEFAULT 'BASIC') RETURN exastat_result_t PIPELINED IS
|
||||
m exastat_metrics_t;
|
||||
str VARCHAR2(200);
|
||||
max_bytes NUMBER;
|
||||
BEGIN
|
||||
m := get_sid(p_sid, p_interval);
|
||||
|
||||
SELECT MAX(delta_value) INTO max_bytes FROM TABLE(CAST(m AS exastat_metrics_t)) WHERE type LIKE p_detail;
|
||||
|
||||
str := '-- ExaSnapper v0.81 BETA by Tanel Poder @ Enkitec - The Exadata Experts ( http://www.enkitec.com )';
|
||||
PIPE ROW(exastat_result_r(str));
|
||||
str := LPAD('-',153,'-');
|
||||
PIPE ROW(exastat_result_r(str));
|
||||
|
||||
FOR i IN 1..m.COUNT LOOP
|
||||
IF m(i).type LIKE p_detail THEN
|
||||
str := RPAD(m(i).category, 30)||' '||RPAD(m(i).name, 30)||'|'|| RPAD(NVL(RPAD('#', ROUND(m(i).delta_value / NULLIF(max_bytes , 0) * 50 ), '#'), ' '), 50, ' ')||'|';
|
||||
str := str || LPAD(ROUND(m(i).delta_value/1048576), 15) ||' MB';
|
||||
str := str || LPAD(ROUND(m(i).delta_value_per_sec/1048576), 15) ||' MB/sec';
|
||||
PIPE ROW(exastat_result_r(str));
|
||||
END IF;
|
||||
END LOOP;
|
||||
END display_sid;
|
||||
|
||||
-- experimental. set arraysize 64. TODO requires in-mem sampling
|
||||
FUNCTION monitor_sid(p_sid IN VARCHAR2, p_interval IN NUMBER DEFAULT 5, p_detail IN VARCHAR2 DEFAULT 'BASIC') RETURN exastat_result_t PIPELINED IS
|
||||
BEGIN
|
||||
WHILE TRUE LOOP
|
||||
FOR c IN 1..30 LOOP PIPE ROW (exastat_result_r('')); END LOOP;
|
||||
PIPE ROW (exastat_result_r('INST='||SYS_CONTEXT('userenv', 'instance_name')||' TIME='||TO_CHAR(SYSDATE,'YYYY-MM-DD HH24:MI:SS')));
|
||||
FOR r IN (SELECT name FROM TABLE(display_sid(p_sid, p_interval, p_detail))) LOOP
|
||||
PIPE ROW(exastat_result_r(r.name));
|
||||
END LOOP;
|
||||
END LOOP;
|
||||
|
||||
END monitor_sid;
|
||||
|
||||
END exasnap;
|
||||
/
|
||||
|
||||
SHOW ERR;
|
||||
|
||||
Reference in New Issue
Block a user