2026-03-12 20:23:15

This commit is contained in:
root
2026-03-12 21:23:47 +01:00
parent eab4b36eca
commit 93039b8489
3332 changed files with 699614 additions and 0 deletions

View File

@@ -0,0 +1,17 @@
-- 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.
-- @alter_all_indexes_degree.sql <SCHEMA> NOPARALLEL
-- @alter_all_indexes_degree.sql <SCHEMA> "PARALLEL 4"
DECLARE
cmd VARCHAR2(1000);
BEGIN
FOR i IN (SELECT owner,index_name FROM dba_indexes WHERE table_owner = '&1' AND table_owner NOT IN('SYS', 'SYSTEM') AND index_type NOT IN ('LOB', 'IOT - TOP')) LOOP
cmd := 'ALTER INDEX '||i.owner||'.'||i.index_name||' &2';
DBMS_OUTPUT.PUT_LINE(cmd);
EXECUTE IMMEDIATE cmd;
END LOOP;
END;
/

View File

@@ -0,0 +1,35 @@
-- 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.
COL wait_event FOR A45 TRUNCATE
COL ash_storage_graph HEAD "GRAPHIC" JUST CENTER FOR A12
SELECT
CASE WHEN sql_plan_options LIKE '%STORAGE%' THEN sql_plan_operation ELSE 'not storage-aware' END sql_plan_operation
, CASE WHEN sql_plan_options LIKE '%STORAGE%' THEN sql_plan_options ELSE 'not storage-aware' END sql_plan_options
, CASE WHEN sql_plan_options LIKE '%STORAGE%' THEN
CASE WHEN session_state = 'WAITING' THEN event ELSE 'ON CPU' END
ELSE
'not storage-aware'
END wait_event
, COUNT(*)
, ROUND(RATIO_TO_REPORT(COUNT(*)) OVER() * 100 ,1) pct
, '|'||RPAD(NVL(RPAD('#', ROUND (10 * RATIO_TO_REPORT(COUNT(*)) OVER()), '#'),' '), 10)||'|' ash_storage_graph
FROM
v$active_session_history
WHERE
1=1
AND sample_time BETWEEN sysdate-1/24/12 AND sysdate
-- AND sql_plan_options LIKE '%STORAGE%'
GROUP BY
CASE WHEN sql_plan_options LIKE '%STORAGE%' THEN sql_plan_operation ELSE 'not storage-aware' END
, CASE WHEN sql_plan_options LIKE '%STORAGE%' THEN sql_plan_options ELSE 'not storage-aware' END
, CASE WHEN sql_plan_options LIKE '%STORAGE%' THEN
CASE WHEN session_state = 'WAITING' THEN event ELSE 'ON CPU' END
ELSE
'not storage-aware'
END
ORDER BY
COUNT(*) DESC
/

5
tpt/exadata/badfetch.sql Normal file
View File

@@ -0,0 +1,5 @@
-- 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.
SELECT /*+ MONITOR */ * FROM tanel.sales;

12
tpt/exadata/cell.sql Normal file
View File

@@ -0,0 +1,12 @@
-- 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.
COL cell_cell_path HEAD CELL_PATH FOR A30
SELECT
c.cell_path cell_cell_path
, c.cell_hashval
FROM
v$cell c
/

View File

@@ -0,0 +1,274 @@
-- 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.
--DROP TABLE t_intrablock_chained ;
CREATE TABLE t_intrablock_chained
TABLESPACE tanel_bigfile
AS SELECT
CAST('x' AS CHAR(100)) padding
, 0 col_1
, 0 col_2
, 0 col_3
, 0 col_4
, 0 col_5
, 0 col_6
, 0 col_7
, 0 col_8
, 0 col_9
, 0 col_10
, 0 col_11
, 0 col_12
, 0 col_13
, 0 col_14
, 0 col_15
, 0 col_16
, 0 col_17
, 0 col_18
, 0 col_19
, 0 col_20
, 0 col_21
, 0 col_22
, 0 col_23
, 0 col_24
, 0 col_25
, 0 col_26
, 0 col_27
, 0 col_28
, 0 col_29
, 0 col_30
, 0 col_31
, 0 col_32
, 0 col_33
, 0 col_34
, 0 col_35
, 0 col_36
, 0 col_37
, 0 col_38
, 0 col_39
, 0 col_40
, 0 col_41
, 0 col_42
, 0 col_43
, 0 col_44
, 0 col_45
, 0 col_46
, 0 col_47
, 0 col_48
, 0 col_49
, 0 col_50
, 0 col_51
, 0 col_52
, 0 col_53
, 0 col_54
, 0 col_55
, 0 col_56
, 0 col_57
, 0 col_58
, 0 col_59
, 0 col_60
, 0 col_61
, 0 col_62
, 0 col_63
, 0 col_64
, 0 col_65
, 0 col_66
, 0 col_67
, 0 col_68
, 0 col_69
, 0 col_70
, 0 col_71
, 0 col_72
, 0 col_73
, 0 col_74
, 0 col_75
, 0 col_76
, 0 col_77
, 0 col_78
, 0 col_79
, 0 col_80
, 0 col_81
, 0 col_82
, 0 col_83
, 0 col_84
, 0 col_85
, 0 col_86
, 0 col_87
, 0 col_88
, 0 col_89
, 0 col_90
, 0 col_91
, 0 col_92
, 0 col_93
, 0 col_94
, 0 col_95
, 0 col_96
, 0 col_97
, 0 col_98
, 0 col_99
, 0 col_100
, 0 col_101
, 0 col_102
, 0 col_103
, 0 col_104
, 0 col_105
, 0 col_106
, 0 col_107
, 0 col_108
, 0 col_109
, 0 col_110
, 0 col_111
, 0 col_112
, 0 col_113
, 0 col_114
, 0 col_115
, 0 col_116
, 0 col_117
, 0 col_118
, 0 col_119
, 0 col_120
, 0 col_121
, 0 col_122
, 0 col_123
, 0 col_124
, 0 col_125
, 0 col_126
, 0 col_127
, 0 col_128
, 0 col_129
, 0 col_130
, 0 col_131
, 0 col_132
, 0 col_133
, 0 col_134
, 0 col_135
, 0 col_136
, 0 col_137
, 0 col_138
, 0 col_139
, 0 col_140
, 0 col_141
, 0 col_142
, 0 col_143
, 0 col_144
, 0 col_145
, 0 col_146
, 0 col_147
, 0 col_148
, 0 col_149
, 0 col_150
, 0 col_151
, 0 col_152
, 0 col_153
, 0 col_154
, 0 col_155
, 0 col_156
, 0 col_157
, 0 col_158
, 0 col_159
, 0 col_160
, 0 col_161
, 0 col_162
, 0 col_163
, 0 col_164
, 0 col_165
, 0 col_166
, 0 col_167
, 0 col_168
, 0 col_169
, 0 col_170
, 0 col_171
, 0 col_172
, 0 col_173
, 0 col_174
, 0 col_175
, 0 col_176
, 0 col_177
, 0 col_178
, 0 col_179
, 0 col_180
, 0 col_181
, 0 col_182
, 0 col_183
, 0 col_184
, 0 col_185
, 0 col_186
, 0 col_187
, 0 col_188
, 0 col_189
, 0 col_190
, 0 col_191
, 0 col_192
, 0 col_193
, 0 col_194
, 0 col_195
, 0 col_196
, 0 col_197
, 0 col_198
, 0 col_199
, 0 col_200
, 0 col_201
, 0 col_202
, 0 col_203
, 0 col_204
, 0 col_205
, 0 col_206
, 0 col_207
, 0 col_208
, 0 col_209
, 0 col_210
, 0 col_211
, 0 col_212
, 0 col_213
, 0 col_214
, 0 col_215
, 0 col_216
, 0 col_217
, 0 col_218
, 0 col_219
, 0 col_220
, 0 col_221
, 0 col_222
, 0 col_223
, 0 col_224
, 0 col_225
, 0 col_226
, 0 col_227
, 0 col_228
, 0 col_229
, 0 col_230
, 0 col_231
, 0 col_232
, 0 col_233
, 0 col_234
, 0 col_235
, 0 col_236
, 0 col_237
, 0 col_238
, 0 col_239
, 0 col_240
, 0 col_241
, 0 col_242
, 0 col_243
, 0 col_244
, 0 col_245
, 0 col_246
, 0 col_247
, 0 col_248
, 0 col_249
, 0 col_250
, 0 col_251
, 0 col_252
, 0 col_253
, 0 col_254
, 0 col_255
, 0 col_256
, 0 col_257
, 0 col_258
, 0 col_259
, 0 col_260
FROM
DUAL
CONNECT BY LEVEL <= 1000000
/

View File

@@ -0,0 +1,19 @@
-- 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.
DROP TABLE cell_traffic_test;
CREATE TABLE cell_traffic_test
PARALLEL 8
AS
SELECT 'TANEL_TEST' col, a.*, b.* FROM
(SELECT ROWNUM r FROM dual CONNECT BY LEVEL <= 100) a
, dba_objects b
ORDER BY
DBMS_RANDOM.VALUE
-- b.owner, b.object_type
/
@gts cell_traffic_test
ALTER TABLE cell_traffic_test NOPARALLEL;
CREATE TABLE

16
tpt/exadata/cellash.sh Normal file
View File

@@ -0,0 +1,16 @@
#!/bin/bash
CMD="LIST ACTIVEREQUEST ATTRIBUTES name,asmDiskGroupNumber,asmFileIncarnation,asmFileNumber\
,consumerGroupID,consumerGroupName,dbID,dbName,dbRequestID,fileType,id,instanceNumber\
,ioBytes,ioBytesSofar,ioGridDisk,ioOffset,ioReason,ioType,objectNumber,parentID\
,requestState,sessionID,sessionSerNumber,sqlID,tableSpaceNumber"
CMD2="LIST ACTIVEREQUEST DETAIL"
echo set echo on
while true ; do
echo REM TIME `date +"%Y-%m-%d %H:%M:%S"`
echo $CMD2
sleep 1
done

55
tpt/exadata/cellio.sql Normal file
View File

@@ -0,0 +1,55 @@
-- 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.
COL cell_cell_path HEAD CELL_PATH FOR A20
COL cell_event HEAD IO_TYPE FOR A35
COL disk_name HEAD DISK_NAME FOR A30
BREAK ON cell_event SKIP 1
--WITH cc AS (
-- SELECT /*+ MATERIALIZE */
-- CAST(extract(xmltype(confval), '/cli-output/cell/name/text()') AS VARCHAR2(20)) cell_name
-- FROM
-- v$cell_config
-- WHERE
--)
SELECT /*+ CARDINALITY(a 100000) */ /* LEADING(c cc d) USE_HASH(d) USE_HASH(cc) USE_HASH(a) */
a.event cell_event
, current_obj#
, CAST(extract(xmltype(confval), '/cli-output/cell/name/text()') AS VARCHAR2(20)) cell_name
, c.cell_path cell_cell_path
-- , sql_id
, nvl(substr(d.name,1,30),'-') disk_name
--, substr(d.path,1,30) disk_path
, c.cell_hashval
, COUNT(*)
FROM
v$cell c
, v$cell_config cc
, v$asm_disk d
, v$active_session_history a
WHERE
a.p1 = c.cell_hashval
AND c.cell_path = cc.cellname
--AND c.cell_path = replace(regexp_substr(d.path,'/(.*)/'),'/')
AND cc.conftype = 'CELL'
AND a.p2 = d.hash_value(+)
AND &1
--AND a.event LIKE 'cell%'
AND sample_time BETWEEN &2 AND &3
GROUP BY
a.event
, nvl(substr(d.name,1,30),'-')
--, substr(d.path,1,30)
, CAST(extract(xmltype(confval), '/cli-output/cell/name/text()') AS VARCHAR2(20))
, c.cell_path
, c.cell_hashval
, a.current_obj#
-- , sql_id
--HAVING COUNT(*) > 1000
ORDER BY
a.event
, COUNT(*) DESC
/

41
tpt/exadata/celliorm.sql Normal file
View File

@@ -0,0 +1,41 @@
-- 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: celliorm.sql (v1.0)
--
-- Purpose: Report Exadata cell IORM status from V$CELL_CONFIG
--
-- Author: Tanel Poder
--
-- Copyright: (c) http://blog.tanelpoder.com - All rights reserved.
--
-- Disclaimer: This script is provided "as is", no warranties nor guarantees are
-- made. Use at your own risk :)
--
-- Usage: @celliorm.sql
--
------------------------------------------------------------------------------------------------------------------------
COL cv_cellname HEAD CELLNAME FOR A20
COL cv_cellversion HEAD CELLSRV_VERSION FOR A20
COL cv_flashcachemode HEAD FLASH_CACHE_MODE FOR A20
PROMPT Show Exadata cell versions from V$CELL_CONFIG....
SELECT
cellname cv_cellname
, CAST(extract(xmltype(confval), '/cli-output/interdatabaseplan/objective/text()') AS VARCHAR2(20)) objective
, CAST(extract(xmltype(confval), '/cli-output/interdatabaseplan/status/text()') AS VARCHAR2(15)) status
, CAST(extract(xmltype(confval), '/cli-output/interdatabaseplan/name/text()') AS VARCHAR2(30)) interdb_plan
, CAST(extract(xmltype(confval), '/cli-output/interdatabaseplan/catPlan/text()') AS VARCHAR2(30)) cat_plan
, CAST(extract(xmltype(confval), '/cli-output/interdatabaseplan/dbPlan/text()') AS VARCHAR2(30)) db_plan
FROM
v$cell_config -- gv$ isn't needed, all cells should be visible in all instances
WHERE
conftype = 'IORM'
ORDER BY
cv_cellname
/

80
tpt/exadata/cellpd.sql Normal file
View File

@@ -0,0 +1,80 @@
-- 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: cellpd.sql (v1.0)
--
-- Purpose: Report physical disk summary from V$CELL_CONFIG
--
-- Author: Tanel Poder (tanel@tanelpoder.com)
--
-- Copyright: (c) http://blog.tanelpoder.com - All rights reserved.
--
-- Disclaimer: This script is provided "as is", no warranties nor guarantees are
-- made. Use at your own risk :)
--
-- Usage: @cellpd.sql
--
------------------------------------------------------------------------------------------------------------------------
COL cv_cellname HEAD CELLNAME FOR A20
COL cv_cellversion HEAD CELLSRV_VERSION FOR A20
COL cv_flashcachemode HEAD FLASH_CACHE_MODE FOR A20
PROMPT Show Exadata cell versions from V$CELL_CONFIG....
SELECT
disktype
, cv_cellname
, status
, ROUND(SUM(physicalsize/1024/1024/1024)) total_gb
, ROUND(AVG(physicalsize/1024/1024/1024)) avg_gb
, COUNT(*) num_disks
, SUM(CASE WHEN predfailStatus = 'TRUE' THEN 1 END) predfail
, SUM(CASE WHEN poorPerfStatus = 'TRUE' THEN 1 END) poorperf
, SUM(CASE WHEN wtCachingStatus = 'TRUE' THEN 1 END) wtcacheprob
, SUM(CASE WHEN peerFailStatus = 'TRUE' THEN 1 END) peerfail
, SUM(CASE WHEN criticalStatus = 'TRUE' THEN 1 END) critical
FROM (
SELECT /*+ NO_MERGE */
c.cellname cv_cellname
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/name/text()') AS VARCHAR2(20)) diskname
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/diskType/text()') AS VARCHAR2(20)) diskType
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/luns/text()') AS VARCHAR2(20)) luns
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/makeModel/text()') AS VARCHAR2(50)) makeModel
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/physicalFirmware/text()') AS VARCHAR2(20)) physicalFirmware
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/physicalInsertTime/text()') AS VARCHAR2(30)) physicalInsertTime
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/physicalSerial/text()') AS VARCHAR2(20)) physicalSerial
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/physicalSize/text()') AS VARCHAR2(20)) physicalSize
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/slotNumber/text()') AS VARCHAR2(30)) slotNumber
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/status/text()') AS VARCHAR2(20)) status
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/id/text()') AS VARCHAR2(20)) id
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/key_500/text()') AS VARCHAR2(20)) key_500
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/predfailStatus/text()') AS VARCHAR2(20)) predfailStatus
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/poorPerfStatus/text()') AS VARCHAR2(20)) poorPerfStatus
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/wtCachingStatus/text()') AS VARCHAR2(20)) wtCachingStatus
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/peerFailStatus/text()') AS VARCHAR2(20)) peerFailStatus
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/criticalStatus/text()') AS VARCHAR2(20)) criticalStatus
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/errCmdTimeoutCount/text()') AS VARCHAR2(20)) errCmdTimeoutCount
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/errHardReadCount/text()') AS VARCHAR2(20)) errHardReadCount
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/errHardWriteCount/text()') AS VARCHAR2(20)) errHardWriteCount
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/errMediaCount/text()') AS VARCHAR2(20)) errMediaCount
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/errOtherCount/text()') AS VARCHAR2(20)) errOtherCount
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/errSeekCount/text()') AS VARCHAR2(20)) errSeekCount
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/sectorRemapCount/text()') AS VARCHAR2(20)) sectorRemapCount
FROM
v$cell_config c
, TABLE(XMLSEQUENCE(EXTRACT(XMLTYPE(c.confval), '/cli-output/physicaldisk'))) v -- gv$ isn't needed, all cells should be visible in all instances
WHERE
c.conftype = 'PHYSICALDISKS'
)
GROUP BY
cv_cellname
, disktype
, status
ORDER BY
disktype
, cv_cellname
/

91
tpt/exadata/cellpdx.sql Normal file
View File

@@ -0,0 +1,91 @@
-- 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: cellpdx.sql (v1.0)
--
-- Purpose: Report detailed physical disk info from V$CELL_CONFIG
--
-- Author: Tanel Poder (tanel@tanelpoder.com)
--
-- Copyright: (c) http://blog.tanelpoder.com - All rights reserved.
--
-- Disclaimer: This script is provided "as is", no warranties nor guarantees are
-- made. Use at your own risk :)
--
-- Usage: @cellpd.sql
--
------------------------------------------------------------------------------------------------------------------------
COL cv_cellname HEAD CELLNAME FOR A20
COL cv_cellversion HEAD CELLSRV_VERSION FOR A20
COL cv_flashcachemode HEAD FLASH_CACHE_MODE FOR A20
PROMPT Show Exadata cell versions from V$CELL_CONFIG....
SELECT * FROM (
SELECT
c.cellname cv_cellname
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/name/text()') AS VARCHAR2(20)) diskname
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/diskType/text()') AS VARCHAR2(20)) diskType
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/luns/text()') AS VARCHAR2(20)) luns
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/makeModel/text()') AS VARCHAR2(40)) makeModel
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/physicalFirmware/text()') AS VARCHAR2(20)) physicalFirmware
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/physicalInsertTime/text()') AS VARCHAR2(30)) physicalInsertTime
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/physicalSerial/text()') AS VARCHAR2(20)) physicalSerial
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/physicalSize/text()') AS VARCHAR2(20)) physicalSize
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/sectorRemapCount/text()') AS VARCHAR2(20)) sectorRemapCount
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/slotNumber/text()') AS VARCHAR2(30)) slotNumber
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/status/text()') AS VARCHAR2(20)) status
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/id/text()') AS VARCHAR2(20)) id
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/key_500/text()') AS VARCHAR2(20)) key_500
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/predfailStatus/text()') AS VARCHAR2(20)) predfailStatus
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/poorPerfStatus/text()') AS VARCHAR2(20)) poorPerfStatus
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/wtCachingStatus/text()') AS VARCHAR2(20)) wtCachingStatus
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/peerFailStatus/text()') AS VARCHAR2(20)) peerFailStatus
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/criticalStatus/text()') AS VARCHAR2(20)) criticalStatus
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/errCmdTimeoutCount/text()') AS VARCHAR2(20)) errCmdTimeoutCount
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/errHardReadCount/text()') AS VARCHAR2(20)) errHardReadCount
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/errHardWriteCount/text()') AS VARCHAR2(20)) errHardWriteCount
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/errMediaCount/text()') AS VARCHAR2(20)) errMediaCount
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/errOtherCount/text()') AS VARCHAR2(20)) errOtherCount
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/errSeekCount/text()') AS VARCHAR2(20)) errSeekCount
FROM
v$cell_config c
, TABLE(XMLSEQUENCE(EXTRACT(XMLTYPE(c.confval), '/cli-output/physicaldisk'))) v -- gv$ isn't needed, all cells should be visible in all instances
WHERE
c.conftype = 'PHYSICALDISKS'
)
ORDER BY
cv_cellname
, diskname
/

View File

@@ -0,0 +1,135 @@
> cellsrvstat -list
Statistic Groups:
io Input/Output related stats
mem Memory related stats
exec Execution related stats
net Network related stats
smartio SmartIO related stats
Statistics:
[ * - Absolute values. Indicates no delta computation in tabular format]
io_nbiorr_hdd Number of hard disk block IO read requests
io_nbiowr_hdd Number of hard disk block IO write requests
io_nbiorb_hdd Hard disk block IO reads (KB)
io_nbiowb_hdd Hard disk block IO writes (KB)
io_nbiorr_flash Number of flash disk block IO read requests
io_nbiowr_flash Number of flash disk block IO write requests
io_nbiorb_flash Flash disk block IO reads (KB)
io_nbiowb_flash Flash disk block IO writes (KB)
io_ndioerr Number of disk IO errors
io_nrfc Number of reads from flash cache
io_nwfc Number of writes to flash cache
io_fcrb Flash cache reads (KB)
io_fcwb Flash cache writes (KB)
io_nfioerr Number of flash cache IO errors
io_nbpfce Size of eviction from flash cache (KB)
io_nolfio Number of outstanding large flash IOs
io_ltow Number of latency threshold warnings during job
io_ltcw Number of latency threshold warnings by checker
io_ltsiow Number of latency threshold warnings for smart IO
io_ltrlw Number of latency threshold warnings for redo log writes
io_bcrti Current read block IO to be issued (KB) *
io_btrti Total read block IO to be issued (KB)
io_bcwti Current write block IO to be issued (KB) *
io_btwti Total write block IO to be issued (KB)
io_bcrii Current read blocks in IO (KB) *
io_btrii Total read block IO issued (KB)
io_bcwii Current write blocks in IO (KB) *
io_btwii Total write block IO issued (KB)
io_bcrsi Current read block IO in network send (KB) *
io_btrsi Total read block IO in network send (KB)
io_bcwsi Current write block IO in network send (KB) *
io_btwsi Total write block IO in network send (KB)
io_bcfp Current block IO being populated in flash (KB) *
io_btfp Total block IO KB populated in flash (KB)
mem_sgahu SGA heap used - kgh statistics (KB)
mem_sgahf SGA heap free - cellsrv statistics (KB)
mem_sgaos OS memory allocated to SGA (KB)
mem_sgahuc SGA heap used - cellsrv statistics - KB
mem_pgaos OS memory allocated to PGA (KB)
mem_pgahuc PGA heap used - cellsrv statistics (KB)
mem_allos OS memory allocated to cellsrv (KB)
mem_sgatop Top 5 SGA consumers (KB) *
mem_sgasubtop Top 5 SGA subheap consumers (KB) *
mem_halfkaf Number of allocation failures in 512 bytes pool
mem_2kaf Number of allocation failures in 2KB pool
mem_4kaf Number of allocation failures in 4KB pool
mem_8kaf Number of allocation failures in 8KB pool
mem_16kaf Number of allocation failures in 16KB pool
mem_32kaf Number of allocation failures in 32KB pool
mem_64kaf Number of allocation failures in 64KB pool
mem_1maf Number of allocation failures in 1MB pool
mem_halfkhwm Allocation hwm in 512 bytes pool
mem_2khwm Allocation hwm in 2KB pool
mem_4khwm Allocation hwm in 4KB pool
mem_8khwm Allocation hwm in 8KB pool
mem_16khwm Allocation hwm in 16KB pool
mem_32khwm Allocation hwm in 32KB pool
mem_64khwm Allocation hwm in 64KB pool
mem_1mhwm Allocation hwm in 1MB pool
mem_lmtf Number of low memory threshold failures
mem_nmtf Number of no memory threshold failures
mem_dynar Dynamic buffer allocation requests
mem_dynaf Dynamic buffer allocation failures
mem_dynafl Dynamic buffer allocation failures due to low mem
mem_dynam Dynamic buffer allocated size (KB)
mem_dynamh Dynamic buffer allocation hwm (KB)
exec_incno Incarnation number *
exec_versf Number of module version failures *
exec_ntwork Number of threads working *
exec_ntnetwait Number of threads waiting for network *
exec_ntreswait Number of threads waiting for resource *
exec_ntmutexwait Number of threads waiting for a mutex *
exec_njx Number of Jobs executed for each job type
exec_topcpusqlid SQL ids consuming the most CPU
net_rxb Total bytes received from the network
net_txb Total bytes transmitted to the network
net_rtxb Total bytes retransmitted to the network
net_sps Number of active sendports
net_sph Hwm of active sendports
net_rois Number of active remote open infos
net_roih HWM of remote open infos
sio_ns Number of active smart IO sessions *
sio_hs High water mark of smart IO sessions *
sio_ncs Number of completed smart IO sessions
sio_oe Smart IO offload efficiency (percentage) *
sio_sis Size of IO avoided due to storage index (KB)
sio_ctb Current smart IO to be issued (KB) *
sio_ttb Total smart IO to be issued (KB)
sio_cii Current smart IO in IO (KB) *
sio_tii Total smart IO in IO (KB)
sio_cfp Current smart IO being cached in flash (KB) *
sio_tfp Total smart IO being cached in flash (KB)
sio_cic Current smart IO with IO completed (KB) *
sio_tic Total smart IO with IO completed (KB)
sio_cif Current smart IO being filtered (KB) *
sio_tif Total smart IO being filtered (KB)
sio_cfc Current smart IO filtering completed (KB) *
sio_tfc Total smart IO filtering completed (KB)
sio_cfo Current smart IO filtered size (KB) *
sio_tfo Total smart IO filtered (KB)
sio_tcpo Total cpu passthru output IO size (KB)
sio_tpo Total passthru output IO size (KB)
sio_cis Current smart IO with results in send (KB) *
sio_tis Total smart IO with results in send (KB)
sio_ciso Current smart IO filtered in send (KB) *
sio_tiso Total smart IO filtered in send (KB)
sio_fcr Total smart IO read from flash (KB)
sio_fcw Total smart IO initiated flash population (KB)
sio_hdr Total smart IO read from hard disk (KB)
sio_hdw Total smart IO writes (fcre) to hard disk (KB)
sio_n512kb Number of smart IO requests < 512KB
sio_n1mb Number of smart IO requests >= 512KB and < 1MB
sio_n2mb Number of smart IO requests >= 1MB and < 2MB
sio_n4mb Number of smart IO requests >= 2MB and < 4MB
sio_n8mb Number of smart IO requests >= 4MB and < 8MB
sio_ngt8mb Number of smart IO requests >= 8MB
sio_nbrf Number of times smart IO buffer reserve failures
sio_nrm Number of times smart IO request misses
sio_ncio Number of times IO for smart IO not allowed to be issued
sio_nplr Number of times smart IO prefetch limit was reached
sio_nssuo Number of times smart scan used unoptimized mode
sio_nfcuo Number of times smart fcre used unoptimized mode
sio_nsbuo Number of times smart backup used unoptimized mode

44
tpt/exadata/cellver.sql Normal file
View File

@@ -0,0 +1,44 @@
-- 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: cellver.sql (v1.01)
--
-- Purpose: Report Exadata cell details from V$CELL_CONFIG
--
-- Author: Tanel Poder (tanel@tanelpoder.com)
--
-- Copyright: (c) http://blog.tanelpoder.com - All rights reserved.
--
-- Disclaimer: This script is provided "as is", no warranties nor guarantees are
-- made. Use at your own risk :)
--
-- Usage: @cellver.sql
--
------------------------------------------------------------------------------------------------------------------------
COL cv_cellname HEAD CELL_NAME FOR A20
COL cv_cell_path HEAD CELL_PATH FOR A30
COL cv_cellversion HEAD CELLSRV_VERSION FOR A20
COL cv_flashcachemode HEAD FLASH_CACHE_MODE FOR A20
PROMPT Show Exadata cell versions from V$CELL_CONFIG....
SELECT
cellname cv_cell_path
, CAST(extract(xmltype(confval), '/cli-output/cell/name/text()') AS VARCHAR2(20)) cv_cellname
, CAST(extract(xmltype(confval), '/cli-output/cell/releaseVersion/text()') AS VARCHAR2(20)) cv_cellVersion
, CAST(extract(xmltype(confval), '/cli-output/cell/flashCacheMode/text()') AS VARCHAR2(20)) cv_flashcachemode
, CAST(extract(xmltype(confval), '/cli-output/cell/cpuCount/text()') AS VARCHAR2(10)) cpu_count
, CAST(extract(xmltype(confval), '/cli-output/cell/upTime/text()') AS VARCHAR2(20)) uptime
, CAST(extract(xmltype(confval), '/cli-output/cell/kernelVersion/text()') AS VARCHAR2(30)) kernel_version
, CAST(extract(xmltype(confval), '/cli-output/cell/makeModel/text()') AS VARCHAR2(50)) make_model
FROM
v$cell_config -- gv$ isn't needed, all cells should be visible in all instances
WHERE
conftype = 'CELL'
ORDER BY
cv_cellname
/

33
tpt/exadata/comptype.sql Normal file
View File

@@ -0,0 +1,33 @@
-- 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.
-- get_compression_type runs recursive queries for every row analyzed, so it is extremely inefficient to run for analyzing many rows
SELECT
COUNT(*)
, DECODE( SYS.DBMS_COMPRESSION.GET_COMPRESSION_TYPE(USER, UPPER('&1'), ROWID),
1, 'No Compression',
2, 'Basic/OLTP Compression',
4, 'HCC Query High',
8, 'HCC Query Low',
16, 'HCC Archive High',
32, 'HCC Archive Low',
64, 'COMP_BLOCK ZFS?',
'Unknown Compression Level'
) AS comp_type
FROM
&1
WHERE rownum <= &2
GROUP BY
DECODE( SYS.DBMS_COMPRESSION.GET_COMPRESSION_TYPE(USER, UPPER('&1'), ROWID),
1, 'No Compression',
2, 'Basic/OLTP Compression',
4, 'HCC Query High',
8, 'HCC Query Low',
16, 'HCC Archive High',
32, 'HCC Archive Low',
64, 'COMP_BLOCK ZFS?',
'Unknown Compression Level'
)
/

67
tpt/exadata/cth.sql Normal file
View File

@@ -0,0 +1,67 @@
-- 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: cth.sql (v1.01)
--
-- Purpose: Display the "ASH for Storage Cells" info from V$CELL_THREAD_HISTORY
--
-- Author: Tanel Poder (tanel@tanelpoder.com)
--
-- Copyright: (c) http://blog.tanelpoder.com - All rights reserved.
--
-- Disclaimer: This script is provided "as is", no warranties nor guarantees are
-- made. Use at your own risk :)
--
-- Usage: @cth <grouping_columns> <sid> <from_date> <to_date>
--
-- @cth job_type,wait_state,wait_object_name,sql_id,database_id session_id=1234 sysdate-1/24 sysdate
-- @cth job_type,wait_state,wait_object_name,sql_id,database_id sql_id='5huy4dwv57qmt' sysdate-1/24 sysdate
--
-- Notes: The v$cell_thread_history is pretty limited compared to the database ASH, so don't get
-- your hopes too up :)
-- Also, the snapshot_time is the cell OS time, so if your DB and cells have clock drift,
-- you may end up matching the wrong time range from cell with the DB performance data.
--
------------------------------------------------------------------------------------------------------------------------
PROMPT Querying V$CELL_THREAD_HISTORY ("ASH" for Storage Cells) ...
SELECT * FROM (
SELECT
COUNT(*) seconds
, ROUND(COUNT(*) / LEAST((CAST(&4 AS DATE)-CAST(&3 AS DATE))*86400, 600),1) avg_threads -- V$CELL_THREAD_HISTORY doesn't usually keep more than 10 minutes of history
, &1
, MIN(snapshot_time), MAX(snapshot_time)
FROM (
SELECT
substr(cell_name,1,20) cell_name
, thread_id
, job_type
, wait_state
, wait_object_name
, sql_id
, database_id
, instance_id
, session_id
, session_serial_num
, snapshot_time
FROM
v$cell_thread_history
WHERE
snapshot_time BETWEEN &3 AND &4
AND &2
AND wait_state NOT IN ( -- "idle" thread states
'waiting_for_SKGXP_receive'
, 'waiting_for_connect'
, 'waiting_for_SKGXP_receive'
, 'looking_for_job'
)
)
GROUP BY &1
ORDER BY COUNT(*) DESC
)
WHERE ROWNUM <= 20
/

View File

@@ -0,0 +1,20 @@
-- 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.
DECLARE
cmd VARCHAR2(1000);
BEGIN
FOR i IN (SELECT owner,table_name FROM dba_tables WHERE owner = '&1') LOOP
cmd := 'ALTER TABLE '||i.owner||'.'||i.table_name||' STORAGE (CELL_FLASH_CACHE DEFAULT)';
DBMS_OUTPUT.PUT_LINE(cmd);
EXECUTE IMMEDIATE cmd;
END LOOP;
FOR i IN (SELECT owner,index_name FROM dba_indexes WHERE owner = '&1') LOOP
cmd := 'ALTER INDEX '||i.owner||'.'||i.index_name||' STORAGE (CELL_FLASH_CACHE DEFAULT)';
DBMS_OUTPUT.PUT_LINE(cmd);
EXECUTE IMMEDIATE cmd;
END LOOP;
END;
/

View File

@@ -0,0 +1,27 @@
-- 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.
SET ECHO ON
-- ALTER SESSION SET "_serial_direct_read"=ALWAYS;
-- ALTER SESSION SET "_cell_storidx_mode"=EVA;
SELECT
/*+ LEADING(c)
NO_SWAP_JOIN_INPUTS(o)
INDEX_RS_ASC(c(cust_email))
FULL(o)
MONITOR
*/
*
FROM
soe.customers c
, soe.orders o
WHERE
o.customer_id = c.customer_id
AND c.cust_email = 'bill.jones@yahoo.com'
--AND c.cust_email = 'anthony.pena@bellsouth.com'
/
SET ECHO OFF

View File

@@ -0,0 +1,24 @@
-- 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.
SET ECHO ON
ALTER SESSION SET "_serial_direct_read"=ALWAYS;
ALTER SESSION SET "_cell_storidx_mode"=EVA;
SELECT
/*+ LEADING(c)
NO_SWAP_JOIN_INPUTS(o)
FULL(o)
PARALLEL(2)
MONITOR
*/
*
FROM
soe.customers2 c
, soe.orders2 o
WHERE
o.customer_id = c.customer_id
AND c.cust_email = 'rico@mbtuhkbv.com'
/
SET ECHO OFF

View File

@@ -0,0 +1,28 @@
-- 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.
SET ECHO ON
-- ALTER SESSION SET "_serial_direct_read"=ALWAYS;
-- ALTER SESSION SET "_cell_storidx_mode"=EVA;
SELECT
/*+ LEADING(c)
NO_SWAP_JOIN_INPUTS(o)
FULL(c)
FULL(o)
MONITOR
*/
*
FROM
soe.customers c
, soe.orders o
WHERE
o.customer_id = c.customer_id
--AND c.cust_email = 'florencio@ivtboge.com'
AND c.cust_email = 'anthony.pena@bellsouth.com'
/
SET ECHO OFF
-- 11.2.0.4 estrella@socxankh.com

View File

@@ -0,0 +1,62 @@
CellCLI> ALTER CELL SHUTDOWN SERVICES CELLSRV;
Stopping CELLSRV services...
The SHUTDOWN of CELLSRV services was successful.
CellCLI>
CellCLI>
CellCLI> CALIBRATE;
Calibration will take a few minutes...
Aggregate random read throughput across all hard disk LUNs: 1103 MBPS
Aggregate random read throughput across all flash disk LUNs: 3964.55 MBPS
Aggregate random read IOs per second (IOPS) across all hard disk LUNs: 1716
Aggregate random read IOs per second (IOPS) across all flash disk LUNs: 98216
Controller read throughput: 1259.65 MBPS
Calibrating hard disks (read only) ...
LUN 0_0 on drive [16:0 ] random read throughput: 94.26 MBPS, and 145 IOPS
LUN 0_1 on drive [16:1 ] random read throughput: 100.10 MBPS, and 142 IOPS
LUN 0_10 on drive [16:10 ] random read throughput: 99.80 MBPS, and 155 IOPS
LUN 0_11 on drive [16:11 ] random read throughput: 96.93 MBPS, and 149 IOPS
LUN 0_2 on drive [16:2 ] random read throughput: 99.18 MBPS, and 146 IOPS
LUN 0_3 on drive [16:3 ] random read throughput: 100.45 MBPS, and 149 IOPS
LUN 0_4 on drive [16:4 ] random read throughput: 98.50 MBPS, and 148 IOPS
LUN 0_5 on drive [16:5 ] random read throughput: 98.20 MBPS, and 147 IOPS
LUN 0_6 on drive [16:6 ] random read throughput: 99.69 MBPS, and 147 IOPS
LUN 0_7 on drive [16:7 ] random read throughput: 102.36 MBPS, and 145 IOPS
LUN 0_8 on drive [16:8 ] random read throughput: 97.97 MBPS, and 147 IOPS
LUN 0_9 on drive [16:9 ] random read throughput: 99.56 MBPS, and 140 IOPS
Calibrating flash disks (read only, note that writes will be significantly slower) ...
LUN 1_0 on drive [FLASH_1_0] random read throughput: 266.07 MBPS, and 18278 IOPS
LUN 1_1 on drive [FLASH_1_1] random read throughput: 262.56 MBPS, and 18235 IOPS
LUN 1_2 on drive [FLASH_1_2] random read throughput: 260.15 MBPS, and 18227 IOPS
LUN 1_3 on drive [FLASH_1_3] random read throughput: 69.84 MBPS, and 17997 IOPS
LUN 2_0 on drive [FLASH_2_0] random read throughput: 186.16 MBPS, and 18737 IOPS
LUN 2_1 on drive [FLASH_2_1] random read throughput: 181.72 MBPS, and 18360 IOPS
LUN 2_2 on drive [FLASH_2_2] random read throughput: 265.29 MBPS, and 19061 IOPS
LUN 2_3 on drive [FLASH_2_3] random read throughput: 265.49 MBPS, and 19221 IOPS
LUN 4_0 on drive [FLASH_4_0] random read throughput: 264.22 MBPS, and 18885 IOPS
LUN 4_1 on drive [FLASH_4_1] random read throughput: 261.84 MBPS, and 18654 IOPS
LUN 4_2 on drive [FLASH_4_2] random read throughput: 264.88 MBPS, and 18800 IOPS
LUN 4_3 on drive [FLASH_4_3] random read throughput: 263.07 MBPS, and 18798 IOPS
LUN 5_0 on drive [FLASH_5_0] random read throughput: 264.07 MBPS, and 19350 IOPS
LUN 5_1 on drive [FLASH_5_1] random read throughput: 261.01 MBPS, and 19313 IOPS
LUN 5_2 on drive [FLASH_5_2] random read throughput: 261.74 MBPS, and 19395 IOPS
LUN 5_3 on drive [FLASH_5_3] random read throughput: 262.30 MBPS, and 19361 IOPS
Found some bad LUNs, running tests sequentially to identify the bad LUNs...
LUN 1_3 on drive [FLASH_1_3] random read throughput: 262.25 MBPS, and 20076 IOPS
LUN 2_0 on drive [FLASH_2_0] random read throughput: 265.61 MBPS, and 20085 IOPS
LUN 2_1 on drive [FLASH_2_1] random read throughput: 262.68 MBPS, and 20174 IOPS
CALIBRATE results are within an acceptable range.
CALIBRATE stress test is now running...
Calibration has finished.
CellCLI>
CellCLI> ALTER CELL STARTUP SERVICES CELLSRV;
Starting CELLSRV services...
The STARTUP of CELLSRV services was successful.

View File

@@ -0,0 +1,34 @@
SQL> @asm/asm_imbalance
Percent Minimum
Percent Disk Size Percent Disk Diskgroup
Diskgroup Imbalance Variance Free Count Redundancy
------------------------------ --------- --------- ------- ----- ----------
DATA 8.2 .0 90.9 32 NORMAL
DBFS_DG 10.9 .0 48.8 28 NORMAL
RECO .5 .0 91.7 33 NORMAL
SQL>
metalink script:
SYS:+ASM1>@asm_imbalance
Columns Described in Script Percent Minimum
Percent Disk Size Percent Disk Diskgroup
Diskgroup Name Imbalance Varience Free Count Redundancy
------------------------------ --------- --------- ------- ----- ----------
DATA 8.2 .0 90.9 32 NORMAL
RECO .5 .0 91.7 33 NORMAL
DBFS_DG 10.9 .0 48.8 28 NORMAL
Columns Described in Script Partner Partner Inactive
Count Space % Failgroup Partnership
Diskgroup Name Imbalance Imbalance Count Count
------------------------------ --------- --------- --------- -----------
DATA 1 12.5 3 0
DBFS_DG 1 12.5 3 0
RECO 0 .0 3 0

View File

@@ -0,0 +1,76 @@
-- 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.
--CREATE BIGFILE TABLESPACE tanel_demo_auto DATAFILE SIZE 100M AUTOEXTEND ON EXTENT MANAGEMENT LOCAL AUTOALLOCATE SEGMENT SPACE MANAGEMENT AUTO;
--CREATE BIGFILE TABLESPACE tanel_demo_small DATAFILE SIZE 100M AUTOEXTEND ON EXTENT MANAGEMENT LOCAL UNIFORM SIZE 64K SEGMENT SPACE MANAGEMENT AUTO;
--CREATE BIGFILE TABLESPACE tanel_demo_medium DATAFILE SIZE 100M AUTOEXTEND ON EXTENT MANAGEMENT LOCAL UNIFORM SIZE 8M SEGMENT SPACE MANAGEMENT AUTO;
--CREATE BIGFILE TABLESPACE tanel_demo_large DATAFILE SIZE 100M AUTOEXTEND ON EXTENT MANAGEMENT LOCAL UNIFORM SIZE 64M SEGMENT SPACE MANAGEMENT AUTO;
ALTER SESSION SET parallel_force_local = TRUE;
DROP TABLE t_fc_insert PURGE;
ALTER TABLESPACE tanel_demo_auto RESIZE 100M;
CREATE TABLE t_fc_insert TABLESPACE tanel_demo_auto STORAGE (CELL_FLASH_CACHE KEEP) AS
SELECT * FROM tanel.sales
WHERE 1=0;
ALTER SESSION ENABLE PARALLEL DML; -- otherwise the INSERT part will be serial, done by QC
VAR snapper REFCURSOR
VAR begin_snap_id NUMBER
VAR end_snap_id NUMBER
EXEC :begin_snap_id := exasnap.begin_snap;
@snapper4 all,begin 1 1 &mysid
INSERT /*+ APPEND MONITOR PARALLEL(8) */ INTO t_fc_insert SELECT * FROM tanel.sales;
COMMIT;
@snapper4 all,end 1 1 &mysid
EXEC :end_snap_id := exasnap.end_snap;
@xp &mysid
SELECT * FROM TABLE(exasnap.display_snap(:begin_snap_id, :end_snap_id, '%'));
-- different caching options
DROP TABLE t_cached PURGE;
DROP TABLE t_default_cached PURGE;
DROP TABLE t_not_cached PURGE;
DROP TABLE t_small_extents;
CREATE TABLE t_cached NOPARALLEL TABLESPACE tanel_demo_auto STORAGE (cell_flash_cache KEEP) AS SELECT * FROM sales;
CREATE TABLE t_default_cached NOPARALLEL TABLESPACE tanel_demo_auto STORAGE (cell_flash_cache DEFAULT) AS SELECT * FROM sales;
CREATE TABLE t_not_cached PARALLEL 16 TABLESPACE tanel_demo_auto STORAGE (cell_flash_cache NONE) AS SELECT * FROM sales;
CREATE TABLE t_small_extents PARALLEL 16 TABLESPACE tanel_demo_small STORAGE (CELL_FLASH_CACHE DEFAULT) AS SELECT * FROM sales;
-- cell commands
-- iostat -xm 5 | egrep -v "sd.[0-9]|^md"
-- lsscsi
-- DESCRIBE FLASHCACHECONTENT
-- cachedKeepSize
-- cachedSize
-- dbID
-- dbUniqueName
-- hitCount
-- hoursToExpiration
-- missCount
-- objectNumber
-- tableSpaceNumber
-- LIST FLASHCACHECONTENT ATTRIBUTES ALL;
-- dcli -l root -g ~/x2cells "cellcli -e 'LIST FLASHCACHECONTENT ATTRIBUTES cachedKeepSize,cachedSize,dbID,dbUniqueName,hitCount,missCount,objectNumber,tableSpaceNumber'" | sed 's/:/ /' > fc.xls
-- cachedKeepSize: 0
-- cachedSize: 1048576
-- dbID: 1538629110
-- dbUniqueName: DEMO
-- hitCount: 103840
-- missCount: 4
-- objectNumber: 4294967294
-- tableSpaceNumber: 0

View File

@@ -0,0 +1,15 @@
-- 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.
CREATE OR REPLACE FUNCTION get_cust_name (id IN NUMBER) RETURN VARCHAR2
AUTHID CURRENT_USER
AS
n VARCHAR2(1000);
BEGIN
SELECT /*+ FULL(c) */ cust_first_name||' '||cust_last_name INTO n
FROM soe.customers c
WHERE customer_id = id;
RETURN n;
END;
/

View File

@@ -0,0 +1,68 @@
-- 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.
CREATE TABLE sales_part
PARTITION BY RANGE (time_id) (
PARTITION Y1998 VALUES LESS THAN (DATE'1999-01-01')
, PARTITION Y1999 VALUES LESS THAN (DATE'2000-01-01')
, PARTITION Y2000 VALUES LESS THAN (DATE'2001-01-01')
, PARTITION Y2001 VALUES LESS THAN (MAXVALUE)
)
TABLESPACE tanel_large
PARALLEL 32
AS SELECT * FROM sales_100g
/
ALTER TABLE sales_part NOPARALLEL;
EXEC DBMS_STATS.GATHER_TABLE_STATS(user, 'SALES_PART', degree=>16);
CREATE TABLE sales_part_query_high
PARTITION BY RANGE (time_id) (
PARTITION Y1998 VALUES LESS THAN (DATE'1999-01-01')
, PARTITION Y1999 VALUES LESS THAN (DATE'2000-01-01')
, PARTITION Y2000 VALUES LESS THAN (DATE'2001-01-01')
, PARTITION Y2001 VALUES LESS THAN (MAXVALUE)
)
TABLESPACE tanel_large
COMPRESS FOR QUERY HIGH
PARALLEL 32
AS SELECT * FROM sales_100g
/
ALTER TABLE sales_part_query_high NOPARALLEL;
EXEC DBMS_STATS.GATHER_TABLE_STATS(user, 'SALES_PART_QUERY_HIGH', degree=>16);
alter session set "_fix_control"='6941515:ON';
CREATE TABLE sales_part_fix_6941515
PARTITION BY RANGE (time_id) (
PARTITION Y1998 VALUES LESS THAN (DATE'1999-01-01')
, PARTITION Y1999 VALUES LESS THAN (DATE'2000-01-01')
, PARTITION Y2000 VALUES LESS THAN (DATE'2001-01-01')
, PARTITION Y2001 VALUES LESS THAN (MAXVALUE)
)
TABLESPACE tanel_large
PARALLEL 32
AS SELECT * FROM sales_100g
/
ALTER TABLE sales_part_fix_6941515 NOPARALLEL;
CREATE TABLE sales_part_query_high_fix
PARTITION BY RANGE (time_id) (
PARTITION Y1998 VALUES LESS THAN (DATE'1999-01-01')
, PARTITION Y1999 VALUES LESS THAN (DATE'2000-01-01')
, PARTITION Y2000 VALUES LESS THAN (DATE'2001-01-01')
, PARTITION Y2001 VALUES LESS THAN (MAXVALUE)
)
TABLESPACE tanel_large
COMPRESS FOR QUERY HIGH
PARALLEL 32
AS SELECT * FROM sales_100g
/
ALTER TABLE sales_part_query_high_fix NOPARALLEL;
EXEC DBMS_STATS.GATHER_TABLE_STATS(user, 'SALES_PART_QUERY_HIGH_FIX', degree=>16);

View File

@@ -0,0 +1,44 @@
-- 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.
CREATE TABLE row_filtering_test (id NUMBER, c CHAR(1000), vc VARCHAR2(1000));
INSERT /*+ APPEND */ INTO row_filtering_test
SELECT rownum, TO_CHAR(rownum), TO_CHAR(rownum)
FROM
(SELECT 1 FROM dual CONNECT BY LEVEL <= 1000)
, (SELECT 1 FROM dual CONNECT BY LEVEL <= 1000)
/
-- CREATE TABLE row_filtering_test AS
-- SELECT rownum r, LPAD('x',1000,'x') c1
-- FROM
-- (SELECT 1 FROM dual CONNECT BY LEVEL <= 1000)
-- , (SELECT 1 FROM dual CONNECT BY LEVEL <= 1000)
-- /
--
@gts row_filtering_test
ALTER SESSION SET "_serial_direct_read"=ALWAYS;
--VAR snapper REFCURSOR
--@snapper4 stats,begin 1 1 &mysid
SELECT /*+ MONITOR */ COUNT(*) FROM row_filtering_test WHERE id <= 500000;
SELECT /*+ MONITOR */ COUNT(*) FROM row_filtering_test WHERE id <= (SELECT 500000 FROM dual);
--@snapper4 stats,end 1 1 &mysid
@xp &mysid
CREATE TABLE row_filtering_helper (v NUMBER);
INSERT INTO row_filtering_helper VALUES (500000);
COMMIT;
SELECT /*+ MONITOR */ COUNT(*) FROM row_filtering_test WHERE r <= (SELECT v FROM row_filtering_helper);
SELECT /*+ MONITOR */ COUNT(*) FROM row_filtering_test WHERE id <= 500000 AND c = vc;

View File

@@ -0,0 +1,28 @@
-- 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.
SELECT /*+ MONITOR FULL(o) FULL(oi) FULL(c) NO_PARALLEL PX_JOIN_FILTER(oi) t2 */
c.customer_id
, c.cust_first_name ||' '||c.cust_last_name
, c.credit_limit
, MAX(oi.unit_price * oi.quantity) avg_order_total
FROM
soe.orders o
, soe.order_items oi
, soe.customers c
WHERE
-- join conditions
c.customer_id = o.customer_id
AND o.order_id = oi.order_id
-- constant filter conditions
AND c.nls_territory LIKE 'aaaa%'
AND o.order_mode = 'online'
AND o.order_status = 5
GROUP BY
c.customer_id
, c.cust_first_name ||' '||c.cust_last_name
, c.credit_limit
HAVING
MAX(oi.unit_price * oi.quantity) > c.credit_limit * 3
/

View File

@@ -0,0 +1,24 @@
-- 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.
-- the small_orders table below is a table with one order only (for demo purposes,
-- so that scanning the large orders_table wouldn't affect measurements). The idea
-- is to demonstrate that even without any direct filter predicates against the "fact"
-- table ORDER_ITEMS, the bloom filter min/max values can also be used for avoiding IO
-- with storage indexes.
--
-- You can create your SMALL_ORDERS table (from SwingBench Order Entry SOE schema):
-- CREATE TABLE soe.small_orders AS SELECT * FROM soe.orders WHERE rownum = 1;
--
SELECT /*+ MONITOR LEADING(o) FULL(o) FULL(oi) PARALLEL(4) PX_JOIN_FILTER(oi) */
o.*
, oi.*
FROM
soe.small_orders o -- one row only
, soe.order_items oi
WHERE
-- join conditions
o.order_id = oi.order_id
/

View File

@@ -0,0 +1,28 @@
-- 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.
SELECT /*+ MONITOR LEADING(c,o,oi) FULL(c) INDEX(o) */
c.customer_id
, c.cust_first_name ||' '||c.cust_last_name
, c.credit_limit
, MAX(oi.unit_price * oi.quantity) avg_order_total
FROM
soe.orders o
, soe.order_items oi
, soe.customers c
WHERE
-- join conditions
c.customer_id = o.customer_id
AND o.order_id = oi.order_id
-- constant filter conditions
AND c.nls_territory LIKE 'a%'
AND o.order_mode = 'online'
AND o.order_status = 5
GROUP BY
c.customer_id
, c.cust_first_name ||' '||c.cust_last_name
, c.credit_limit
HAVING
MAX(oi.unit_price * oi.quantity) > c.credit_limit * 2
/

View File

@@ -0,0 +1,20 @@
-- 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.
DECLARE
cmd VARCHAR2(1000);
BEGIN
FOR i IN (SELECT owner,table_name FROM dba_tables WHERE owner = '&1') LOOP
cmd := 'ALTER TABLE '||i.owner||'.'||i.table_name||' STORAGE (CELL_FLASH_CACHE NONE)';
DBMS_OUTPUT.PUT_LINE(cmd);
EXECUTE IMMEDIATE cmd;
END LOOP;
FOR i IN (SELECT owner,index_name FROM dba_indexes WHERE owner = '&1') LOOP
cmd := 'ALTER INDEX '||i.owner||'.'||i.index_name||' STORAGE (CELL_FLASH_CACHE NONE)';
DBMS_OUTPUT.PUT_LINE(cmd);
EXECUTE IMMEDIATE cmd;
END LOOP;
END;
/

View File

@@ -0,0 +1,20 @@
-- 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.
DECLARE
cmd VARCHAR2(1000);
BEGIN
FOR i IN (SELECT owner,table_name FROM dba_tables WHERE owner = '&1') LOOP
cmd := 'ALTER TABLE '||i.owner||'.'||i.table_name||' STORAGE (CELL_FLASH_CACHE KEEP)';
DBMS_OUTPUT.PUT_LINE(cmd);
EXECUTE IMMEDIATE cmd;
END LOOP;
FOR i IN (SELECT owner,index_name FROM dba_indexes WHERE owner = '&1') LOOP
cmd := 'ALTER INDEX '||i.owner||'.'||i.index_name||' STORAGE (CELL_FLASH_CACHE KEEP)';
DBMS_OUTPUT.PUT_LINE(cmd);
EXECUTE IMMEDIATE cmd;
END LOOP;
END;
/

19
tpt/exadata/esql.sql Normal file
View File

@@ -0,0 +1,19 @@
-- 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.
SELECT
child_number chld
, ROUND( physical_read_bytes / 1048576 ) phyrd_mb
, ROUND( physical_write_bytes / 1048576 ) phywr_mb
, ROUND( io_cell_offload_eligible_bytes / 1048576 ) phyrd_offl_elig_mb
, ROUND( io_cell_offload_returned_bytes / 1048576 ) phyrd_offl_ret_mb
, ROUND( io_interconnect_bytes / 1048576 ) ic_total_traffic_mb
, ROUND( io_cell_uncompressed_bytes / 1048576 ) total_uncomp_mb
, optimized_phy_read_requests phyrd_optim_rq
FROM
v$sql
WHERE
sql_id = '&1'
AND child_number LIKE '&2'
@pr

179
tpt/exadata/exadisktopo.sql Normal file
View File

@@ -0,0 +1,179 @@
-- 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: exadisktopo.sql (v1.0)
--
-- Purpose: Report Exadata disk topology from ASM Diskgroup all the way to cell LUNs and Physical disks
-- (from top of the stack downwards)
--
-- Author: Tanel Poder (tanel@tanelpoder.com)
--
-- Copyright: (c) http://blog.tanelpoder.com - All rights reserved.
--
-- Disclaimer: This script is provided "as is", no warranties nor guarantees are
-- made. Use at your own risk :)
--
-- Usage: @exadisktopo.sql
--
------------------------------------------------------------------------------------------------------------------------
COL cellname HEAD CELLNAME FOR A20
COL celldisk_name HEAD CELLDISK FOR A30
COL physdisk_name HEAD PHYSDISK FOR A30
COL griddisk_name HEAD GRIDDISK FOR A30
COL asmdisk_name HEAD ASMDISK FOR A30
BREAK ON asm_diskgroup SKIP 1 ON asm_disk
PROMPT Showing Exadata disk topology from V$ASM_DISK and V$CELL_CONFIG....
WITH
pd AS (
SELECT /*+ MATERIALIZE */
c.cellname
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/name/text()') AS VARCHAR2(100)) name
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/diskType/text()') AS VARCHAR2(100)) diskType
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/luns/text()') AS VARCHAR2(100)) luns
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/makeModel/text()') AS VARCHAR2(100)) makeModel
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/physicalFirmware/text()') AS VARCHAR2(100)) physicalFirmware
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/physicalInsertTime/text()') AS VARCHAR2(100)) physicalInsertTime
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/physicalSerial/text()') AS VARCHAR2(100)) physicalSerial
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/physicalSize/text()') AS VARCHAR2(100)) physicalSize
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/slotNumber/text()') AS VARCHAR2(100)) slotNumber
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/status/text()') AS VARCHAR2(100)) status
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/id/text()') AS VARCHAR2(100)) id
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/key_500/text()') AS VARCHAR2(100)) key_500
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/predfailStatus/text()') AS VARCHAR2(100)) predfailStatus
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/poorPerfStatus/text()') AS VARCHAR2(100)) poorPerfStatus
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/wtCachingStatus/text()') AS VARCHAR2(100)) wtCachingStatus
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/peerFailStatus/text()') AS VARCHAR2(100)) peerFailStatus
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/criticalStatus/text()') AS VARCHAR2(100)) criticalStatus
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/errCmdTimeoutCount/text()') AS VARCHAR2(100)) errCmdTimeoutCount
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/errHardReadCount/text()') AS VARCHAR2(100)) errHardReadCount
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/errHardWriteCount/text()') AS VARCHAR2(100)) errHardWriteCount
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/errMediaCount/text()') AS VARCHAR2(100)) errMediaCount
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/errOtherCount/text()') AS VARCHAR2(100)) errOtherCount
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/errSeekCount/text()') AS VARCHAR2(100)) errSeekCount
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/sectorRemapCount/text()') AS VARCHAR2(100)) sectorRemapCount
FROM
v$cell_config c
, TABLE(XMLSEQUENCE(EXTRACT(XMLTYPE(c.confval), '/cli-output/physicaldisk'))) v -- gv$ isn't needed, all cells should be visible in all instances
WHERE
c.conftype = 'PHYSICALDISKS'
),
cd AS (
SELECT /*+ MATERIALIZE */
c.cellname
, CAST(EXTRACTVALUE(VALUE(v), '/celldisk/name/text()') AS VARCHAR2(100)) name
, CAST(EXTRACTVALUE(VALUE(v), '/celldisk/comment /text()') AS VARCHAR2(100)) disk_comment
, CAST(EXTRACTVALUE(VALUE(v), '/celldisk/creationTime /text()') AS VARCHAR2(100)) creationTime
, CAST(EXTRACTVALUE(VALUE(v), '/celldisk/deviceName /text()') AS VARCHAR2(100)) deviceName
, CAST(EXTRACTVALUE(VALUE(v), '/celldisk/devicePartition/text()') AS VARCHAR2(100)) devicePartition
, CAST(EXTRACTVALUE(VALUE(v), '/celldisk/diskType /text()') AS VARCHAR2(100)) diskType
, CAST(EXTRACTVALUE(VALUE(v), '/celldisk/errorCount /text()') AS VARCHAR2(100)) errorCount
, CAST(EXTRACTVALUE(VALUE(v), '/celldisk/freeSpace /text()') AS VARCHAR2(100)) freeSpace
, CAST(EXTRACTVALUE(VALUE(v), '/celldisk/id /text()') AS VARCHAR2(100)) id
, CAST(EXTRACTVALUE(VALUE(v), '/celldisk/interleaving /text()') AS VARCHAR2(100)) interleaving
, CAST(EXTRACTVALUE(VALUE(v), '/celldisk/lun /text()') AS VARCHAR2(100)) lun
, CAST(EXTRACTVALUE(VALUE(v), '/celldisk/physicalDisk /text()') AS VARCHAR2(100)) physicalDisk
, CAST(EXTRACTVALUE(VALUE(v), '/celldisk/size /text()') AS VARCHAR2(100)) disk_size
, CAST(EXTRACTVALUE(VALUE(v), '/celldisk/status /text()') AS VARCHAR2(100)) status
FROM
v$cell_config c
, TABLE(XMLSEQUENCE(EXTRACT(XMLTYPE(c.confval), '/cli-output/celldisk'))) v -- gv$ isn't needed, all cells should be visible in all instances
WHERE
c.conftype = 'CELLDISKS'
),
gd AS (
SELECT /*+ MATERIALIZE */
c.cellname
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/name/text()') AS VARCHAR2(100)) name
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/asmDiskgroupName/text()') AS VARCHAR2(100)) asmDiskgroupName
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/asmDiskName /text()') AS VARCHAR2(100)) asmDiskName
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/asmFailGroupName/text()') AS VARCHAR2(100)) asmFailGroupName
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/availableTo /text()') AS VARCHAR2(100)) availableTo
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/cachingPolicy /text()') AS VARCHAR2(100)) cachingPolicy
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/cellDisk /text()') AS VARCHAR2(100)) cellDisk
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/comment /text()') AS VARCHAR2(100)) disk_comment
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/creationTime /text()') AS VARCHAR2(100)) creationTime
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/diskType /text()') AS VARCHAR2(100)) diskType
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/errorCount /text()') AS VARCHAR2(100)) errorCount
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/id /text()') AS VARCHAR2(100)) id
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/offset /text()') AS VARCHAR2(100)) offset
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/size /text()') AS VARCHAR2(100)) disk_size
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/status /text()') AS VARCHAR2(100)) status
FROM
v$cell_config c
, TABLE(XMLSEQUENCE(EXTRACT(XMLTYPE(c.confval), '/cli-output/griddisk'))) v -- gv$ isn't needed, all cells should be visible in all instances
WHERE
c.conftype = 'GRIDDISKS'
),
lun AS (
SELECT /*+ MATERIALIZE */
c.cellname
, CAST(EXTRACTVALUE(VALUE(v), '/lun/cellDisk /text()') AS VARCHAR2(100)) cellDisk
, CAST(EXTRACTVALUE(VALUE(v), '/lun/deviceName /text()') AS VARCHAR2(100)) deviceName
, CAST(EXTRACTVALUE(VALUE(v), '/lun/diskType /text()') AS VARCHAR2(100)) diskType
, CAST(EXTRACTVALUE(VALUE(v), '/lun/id /text()') AS VARCHAR2(100)) id
, CAST(EXTRACTVALUE(VALUE(v), '/lun/isSystemLun /text()') AS VARCHAR2(100)) isSystemLun
, CAST(EXTRACTVALUE(VALUE(v), '/lun/lunAutoCreate /text()') AS VARCHAR2(100)) lunAutoCreate
, CAST(EXTRACTVALUE(VALUE(v), '/lun/lunSize /text()') AS VARCHAR2(100)) lunSize
, CAST(EXTRACTVALUE(VALUE(v), '/lun/physicalDrives /text()') AS VARCHAR2(100)) physicalDrives
, CAST(EXTRACTVALUE(VALUE(v), '/lun/raidLevel /text()') AS VARCHAR2(100)) raidLevel
, CAST(EXTRACTVALUE(VALUE(v), '/lun/lunWriteCacheMode/text()') AS VARCHAR2(100)) lunWriteCacheMode
, CAST(EXTRACTVALUE(VALUE(v), '/lun/status /text()') AS VARCHAR2(100)) status
FROM
v$cell_config c
, TABLE(XMLSEQUENCE(EXTRACT(XMLTYPE(c.confval), '/cli-output/lun'))) v -- gv$ isn't needed, all cells should be visible in all instances
WHERE
c.conftype = 'LUNS'
)
, ad AS (SELECT /*+ MATERIALIZE */ * FROM v$asm_disk)
, adg AS (SELECT /*+ MATERIALIZE */ * FROM v$asm_diskgroup)
SELECT
adg.name asm_diskgroup
, ad.name asm_disk
, gd.name griddisk_name
, cd.name celldisk_name
, pd.cellname
, SUBSTR(cd.devicepartition,1,20) cd_devicepart
, pd.name physdisk_name
, SUBSTR(pd.status,1,20) physdisk_status
, lun.lunWriteCacheMode
-- , SUBSTR(cd.devicename,1,20) cd_devicename
-- , SUBSTR(lun.devicename,1,20) lun_devicename
-- disktype
FROM
gd
, cd
, pd
, lun
, ad
, adg
WHERE
ad.group_number = adg.group_number (+)
AND gd.asmdiskname = ad.name (+)
AND cd.name = gd.cellDisk (+)
AND pd.id = cd.physicalDisk (+)
AND cd.name = lun.celldisk (+)
--GROUP BY
-- cellname
-- , disktype
-- , status
ORDER BY
-- disktype
asm_diskgroup
, asm_disk
, griddisk_name
, celldisk_name
, physdisk_name
, cellname
/

View File

@@ -0,0 +1,171 @@
-- 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: exadisktopo2.sql (v1.0)
--
-- Purpose: Report Exadata disk topology from cell LUNs and Physical disks all the way to ASM diskgroups
-- (from bottom of the IO stack upwards)
--
-- Author: Tanel Poder (tanel@tanelpoder.com)
--
-- Copyright: Tanel Poder (c) http://blog.tanelpoder.com - All rights reserved.
--
-- Disclaimer: This script is provided "as is", no warranties nor guarantees are
-- made. Use at your own risk :)
--
-- Usage: @exadatadisktopo2
--
------------------------------------------------------------------------------------------------------------------------
COL cellname HEAD CELLNAME FOR A20
COL celldisk_name HEAD CELLDISK FOR A30
COL physdisk_name HEAD PHYSDISK FOR A30
COL griddisk_name HEAD GRIDDISK FOR A30
COL asmdisk_name HEAD ASMDISK FOR A30
BREAK ON cellname SKIP 1
PROMPT Showing Exadata disk topology from V$ASM_DISK and V$CELL_CONFIG....
WITH
pd AS (
SELECT /*+ MATERIALIZE */
c.cellname
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/name/text()') AS VARCHAR2(100)) name
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/diskType/text()') AS VARCHAR2(100)) diskType
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/luns/text()') AS VARCHAR2(100)) luns
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/makeModel/text()') AS VARCHAR2(100)) makeModel
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/physicalFirmware/text()') AS VARCHAR2(100)) physicalFirmware
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/physicalInsertTime/text()') AS VARCHAR2(100)) physicalInsertTime
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/physicalSerial/text()') AS VARCHAR2(100)) physicalSerial
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/physicalSize/text()') AS VARCHAR2(100)) physicalSize
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/slotNumber/text()') AS VARCHAR2(100)) slotNumber
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/status/text()') AS VARCHAR2(100)) status
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/id/text()') AS VARCHAR2(100)) id
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/key_500/text()') AS VARCHAR2(100)) key_500
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/predfailStatus/text()') AS VARCHAR2(100)) predfailStatus
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/poorPerfStatus/text()') AS VARCHAR2(100)) poorPerfStatus
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/wtCachingStatus/text()') AS VARCHAR2(100)) wtCachingStatus
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/peerFailStatus/text()') AS VARCHAR2(100)) peerFailStatus
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/criticalStatus/text()') AS VARCHAR2(100)) criticalStatus
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/errCmdTimeoutCount/text()') AS VARCHAR2(100)) errCmdTimeoutCount
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/errHardReadCount/text()') AS VARCHAR2(100)) errHardReadCount
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/errHardWriteCount/text()') AS VARCHAR2(100)) errHardWriteCount
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/errMediaCount/text()') AS VARCHAR2(100)) errMediaCount
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/errOtherCount/text()') AS VARCHAR2(100)) errOtherCount
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/errSeekCount/text()') AS VARCHAR2(100)) errSeekCount
, CAST(EXTRACTVALUE(VALUE(v), '/physicaldisk/sectorRemapCount/text()') AS VARCHAR2(100)) sectorRemapCount
FROM
v$cell_config c
, TABLE(XMLSEQUENCE(EXTRACT(XMLTYPE(c.confval), '/cli-output/physicaldisk'))) v -- gv$ isn't needed, all cells should be visible in all instances
WHERE
c.conftype = 'PHYSICALDISKS'
),
cd AS (
SELECT /*+ MATERIALIZE */
c.cellname
, CAST(EXTRACTVALUE(VALUE(v), '/celldisk/name/text()') AS VARCHAR2(100)) name
, CAST(EXTRACTVALUE(VALUE(v), '/celldisk/comment /text()') AS VARCHAR2(100)) disk_comment
, CAST(EXTRACTVALUE(VALUE(v), '/celldisk/creationTime /text()') AS VARCHAR2(100)) creationTime
, CAST(EXTRACTVALUE(VALUE(v), '/celldisk/deviceName /text()') AS VARCHAR2(100)) deviceName
, CAST(EXTRACTVALUE(VALUE(v), '/celldisk/devicePartition/text()') AS VARCHAR2(100)) devicePartition
, CAST(EXTRACTVALUE(VALUE(v), '/celldisk/diskType /text()') AS VARCHAR2(100)) diskType
, CAST(EXTRACTVALUE(VALUE(v), '/celldisk/errorCount /text()') AS VARCHAR2(100)) errorCount
, CAST(EXTRACTVALUE(VALUE(v), '/celldisk/freeSpace /text()') AS VARCHAR2(100)) freeSpace
, CAST(EXTRACTVALUE(VALUE(v), '/celldisk/id /text()') AS VARCHAR2(100)) id
, CAST(EXTRACTVALUE(VALUE(v), '/celldisk/interleaving /text()') AS VARCHAR2(100)) interleaving
, CAST(EXTRACTVALUE(VALUE(v), '/celldisk/lun /text()') AS VARCHAR2(100)) lun
, CAST(EXTRACTVALUE(VALUE(v), '/celldisk/physicalDisk /text()') AS VARCHAR2(100)) physicalDisk
, CAST(EXTRACTVALUE(VALUE(v), '/celldisk/size /text()') AS VARCHAR2(100)) disk_size
, CAST(EXTRACTVALUE(VALUE(v), '/celldisk/status /text()') AS VARCHAR2(100)) status
FROM
v$cell_config c
, TABLE(XMLSEQUENCE(EXTRACT(XMLTYPE(c.confval), '/cli-output/celldisk'))) v -- gv$ isn't needed, all cells should be visible in all instances
WHERE
c.conftype = 'CELLDISKS'
),
gd AS (
SELECT /*+ MATERIALIZE */
c.cellname
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/name/text()') AS VARCHAR2(100)) name
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/asmDiskgroupName/text()') AS VARCHAR2(100)) asmDiskgroupName
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/asmDiskName /text()') AS VARCHAR2(100)) asmDiskName
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/asmFailGroupName/text()') AS VARCHAR2(100)) asmFailGroupName
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/availableTo /text()') AS VARCHAR2(100)) availableTo
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/cachingPolicy /text()') AS VARCHAR2(100)) cachingPolicy
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/cellDisk /text()') AS VARCHAR2(100)) cellDisk
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/comment /text()') AS VARCHAR2(100)) disk_comment
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/creationTime /text()') AS VARCHAR2(100)) creationTime
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/diskType /text()') AS VARCHAR2(100)) diskType
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/errorCount /text()') AS VARCHAR2(100)) errorCount
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/id /text()') AS VARCHAR2(100)) id
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/offset /text()') AS VARCHAR2(100)) offset
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/size /text()') AS VARCHAR2(100)) disk_size
, CAST(EXTRACTVALUE(VALUE(v), '/griddisk/status /text()') AS VARCHAR2(100)) status
FROM
v$cell_config c
, TABLE(XMLSEQUENCE(EXTRACT(XMLTYPE(c.confval), '/cli-output/griddisk'))) v -- gv$ isn't needed, all cells should be visible in all instances
WHERE
c.conftype = 'GRIDDISKS'
),
lun AS (
SELECT /*+ MATERIALIZE */
c.cellname
, CAST(EXTRACTVALUE(VALUE(v), '/lun/cellDisk /text()') AS VARCHAR2(100)) cellDisk
, CAST(EXTRACTVALUE(VALUE(v), '/lun/deviceName /text()') AS VARCHAR2(100)) deviceName
, CAST(EXTRACTVALUE(VALUE(v), '/lun/diskType /text()') AS VARCHAR2(100)) diskType
, CAST(EXTRACTVALUE(VALUE(v), '/lun/id /text()') AS VARCHAR2(100)) id
, CAST(EXTRACTVALUE(VALUE(v), '/lun/isSystemLun /text()') AS VARCHAR2(100)) isSystemLun
, CAST(EXTRACTVALUE(VALUE(v), '/lun/lunAutoCreate /text()') AS VARCHAR2(100)) lunAutoCreate
, CAST(EXTRACTVALUE(VALUE(v), '/lun/lunSize /text()') AS VARCHAR2(100)) lunSize
, CAST(EXTRACTVALUE(VALUE(v), '/lun/physicalDrives /text()') AS VARCHAR2(100)) physicalDrives
, CAST(EXTRACTVALUE(VALUE(v), '/lun/raidLevel /text()') AS VARCHAR2(100)) raidLevel
, CAST(EXTRACTVALUE(VALUE(v), '/lun/lunWriteCacheMode/text()') AS VARCHAR2(100)) lunWriteCacheMode
, CAST(EXTRACTVALUE(VALUE(v), '/lun/status /text()') AS VARCHAR2(100)) status
FROM
v$cell_config c
, TABLE(XMLSEQUENCE(EXTRACT(XMLTYPE(c.confval), '/cli-output/lun'))) v -- gv$ isn't needed, all cells should be visible in all instances
WHERE
c.conftype = 'LUNS'
)
, ad AS (SELECT /*+ MATERIALIZE */ * FROM v$asm_disk)
, adg AS (SELECT /*+ MATERIALIZE */ * FROM v$asm_diskgroup)
SELECT
pd.cellname
, SUBSTR(lun.deviceName,1,20) lun_devicename
, pd.name physdisk_name
, SUBSTR(pd.status,1,20) physdisk_status
, cd.name celldisk_name
, SUBSTR(cd.devicepartition,1,20) cd_devicepart
, gd.name griddisk_name
, ad.name asm_disk
, adg.name asm_diskgroup
, lun.lunWriteCacheMode
-- , SUBSTR(cd.devicename,1,20) cd_devicename
-- , SUBSTR(lun.devicename,1,20) lun_devicename
FROM
gd
, cd
, pd
, lun
, ad
, adg
WHERE
ad.group_number = adg.group_number (+)
AND gd.asmdiskname = ad.name (+)
AND cd.name = gd.cellDisk (+)
AND pd.id = cd.physicalDisk (+)
AND cd.name = lun.celldisk (+)
ORDER BY
--disktype
cellname
, celldisk_name
, griddisk_name
, asm_disk
, asm_diskgroup
/
CLEAR BREAKS

342
tpt/exadata/exafriendly.sql Normal file
View File

@@ -0,0 +1,342 @@
-- 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: exafriendly.sql (report non-exadata-friendly SQL and their stats)
--
-- Purpose: This script is a collection of queries against ASH, which will
-- report and drill down into workloads which don't use Exadata smart
-- scanning and are doing buffered full table scans or random single
-- block reads instead. It uses the 11g new ASH columns
-- (SQL_PLAN_OPERATION, SQL_PLAN_OPTIONS) which give SQL plan line
-- level activity breakdown.
--
-- Note that this script is not a single SQL performance diagnosis tool,
-- for looking into a single SQL, use the SQL Monitoring report. This
-- exafriendly.sql script is aimed for giving you a high-level
-- bird's-eye view of "exadata-friendiness" of your workloads, so you'd
-- detect systemic problems and drill down where needed.
--
-- Usage: @exafriendly.sql <ash_data_source>
--
-- Examples: @exafriendly.sql gv$active_session_history
--
-- @exafriendly.sql "dba_hist_active_sess_history WHERE snap_time > SYSDATE-1"
--
-- Author: Tanel Poder ( http://blog.tanelpoder.com | tanel@tanelpoder.com )
--
-- Copyright: (c) 2012 All Rights Reserved
--
--
-- Other: I strongly recommend you to read through the script to understand
-- what it's doing and how the drilldown happens. You likely need
-- to customize things (or at least adjust filters) when you diagnose
-- stuff in your environment.
--
--------------------------------------------------------------------------------
set timing on tab off verify off linesize 999 pagesize 5000 trimspool on trimout on null ""
COL wait_class FOR A20
COL event FOR A40
COL plan_line FOR A40
COL command_name FOR A15
COL pct FOR 999.9
define ash=&1
SELECT MAX(sample_time) - MIN(sample_time)
FROM &ash
/
PROMPT Report the top active SQL statements regardless of their CPU usage/wait event breakdown
SELECT * FROM (
SELECT
sql_id
, SUM(1) seconds
, ROUND(RATIO_TO_REPORT(COUNT(*)) OVER () * 100, 1) pct
FROM &ash
WHERE
session_type = 'FOREGROUND'
GROUP BY
sql_id
ORDER BY
seconds DESC
)
WHERE
rownum <= 10
/
PROMPT Report the top session state/wait class breakdown
SELECT * FROM (
SELECT
session_state,wait_class
, SUM(1) seconds
, ROUND(RATIO_TO_REPORT(COUNT(*)) OVER () * 100, 1) pct
FROM &ash
GROUP BY
session_state,wait_class
ORDER BY
seconds DESC
)
WHERE
rownum <= 10
/
PROMPT Report the top session state/wait event breakdown (just like TOP-5 Timed Events in AWR)
SELECT * FROM (
SELECT
session_state,wait_class,event
, SUM(1) seconds
, ROUND(RATIO_TO_REPORT(COUNT(*)) OVER () * 100, 1) pct
FROM &ash
GROUP BY
session_state,wait_class,event
ORDER BY
seconds DESC
)
WHERE
rownum <= 10
/
PROMPT Report the top SQL waiting for buffered single block reads
SELECT * FROM (
SELECT
session_state,wait_class,event,sql_id
, SUM(1) seconds
, ROUND(RATIO_TO_REPORT(COUNT(*)) OVER () * 100, 1) pct
FROM &ash
WHERE
session_state = 'WAITING'
AND event = 'cell single block physical read'
GROUP BY
session_state,wait_class,event,sql_id
ORDER BY
seconds DESC
)
WHERE
rownum <= 10
/
PROMPT Report the top SQL waiting for buffered single block reads the most (with sampled execution count)
SELECT * FROM (
SELECT
sql_plan_operation||' '||sql_plan_options plan_line,event,sql_id
, COUNT(DISTINCT(sql_exec_id)) noticed_executions
, SUM(1) seconds
, ROUND(RATIO_TO_REPORT(COUNT(*)) OVER () * 100, 1) pct
FROM &ash
WHERE
session_state = 'WAITING'
AND event = 'cell single block physical read'
GROUP BY
sql_plan_operation||' '||sql_plan_options,event,sql_id
ORDER BY
seconds DESC
)
WHERE
rownum <= 10
/
PROMPT Report what kind of SQL execution plan operations, executed by which user wait for buffered single block reads the most
SELECT * FROM (
SELECT
sql_plan_operation||' '||sql_plan_options plan_line,u.username,event
, SUM(1) seconds
, ROUND(RATIO_TO_REPORT(COUNT(*)) OVER () * 100, 1) pct
FROM &ash a
, dba_users u
WHERE
a.user_id = u.user_id
AND session_state = 'WAITING'
AND event = 'cell single block physical read'
GROUP BY
sql_plan_operation||' '||sql_plan_options,event,u.username
ORDER BY
seconds DESC
)
WHERE
rownum <= 10
/
PROMPT Report what kind of execution plan operations wait for buffered single block reads
SELECT * FROM (
SELECT
sql_plan_operation||' '||sql_plan_options plan_line,event
, SUM(1) seconds
, ROUND(RATIO_TO_REPORT(COUNT(*)) OVER () * 100, 1) pct
FROM &ash
WHERE
session_state = 'WAITING'
AND event = 'cell single block physical read'
GROUP BY
sql_plan_operation||' '||sql_plan_options,event
ORDER BY
seconds DESC
)
WHERE
rownum <= 10
/
PROMPT Report what kind of execution plan operations wait for buffered single block reads - against which schemas
SELECT * FROM (
SELECT
sql_plan_operation||' '||sql_plan_options plan_line,p.object_owner,event
, SUM(1) seconds
, ROUND(RATIO_TO_REPORT(COUNT(*)) OVER () * 100, 1) pct
FROM
v$active_session_history a
, v$sql_plan p
WHERE
a.sql_id = p.sql_id
AND a.sql_child_number = p.child_number
AND a.sql_plan_line_id = p.id
AND session_state = 'WAITING'
AND event = 'cell single block physical read'
GROUP BY
sql_plan_operation||' '||sql_plan_options,p.object_owner,event
ORDER BY
seconds DESC
)
WHERE
rownum <= 10
/
PROMPT Report what kind of execution plan operations wait for buffered single block reads - against which objects
SELECT * FROM (
SELECT
sql_plan_operation||' '||sql_plan_options plan_line,p.object_owner,p.object_name,event
, SUM(1) seconds
, ROUND(RATIO_TO_REPORT(COUNT(*)) OVER () * 100, 1) pct
FROM
v$active_session_history a
, v$sql_plan p
WHERE
a.sql_id = p.sql_id
AND a.sql_child_number = p.child_number
AND a.sql_plan_line_id = p.id
AND session_state = 'WAITING'
AND event = 'cell single block physical read'
GROUP BY
sql_plan_operation||' '||sql_plan_options,p.object_owner,p.object_name,event
ORDER BY
seconds DESC
)
WHERE
rownum <= 10
/
PROMPT Report which SQL command type consumes the most time (broken down by wait class)
SELECT * FROM (
SELECT
command_name,session_state,wait_class
, SUM(1) seconds
, ROUND(RATIO_TO_REPORT(COUNT(*)) OVER () * 100, 1) pct
FROM &ash, v$sqlcommand
WHERE &ash..sql_opcode = v$sqlcommand.command_type
GROUP BY
command_name,session_state,wait_class
ORDER BY
seconds DESC
)
WHERE
rownum <= 10
/
PROMPT Report what kind of execution plan operations wait for buffered multiblock reads the most
SELECT * FROM (
SELECT
sql_plan_operation||' '||sql_plan_options plan_line,event
, SUM(1) seconds
, ROUND(RATIO_TO_REPORT(COUNT(*)) OVER () * 100, 1) pct
FROM
&ash
WHERE
session_state = 'WAITING'
AND event = 'cell multiblock physical read'
GROUP BY
sql_plan_operation||' '||sql_plan_options,event
ORDER BY
seconds DESC
)
WHERE
rownum <= 10
/
PROMPT Report what kind of execution plan operations wait for buffered multiblock reads - against which objects
SELECT * FROM (
SELECT
sql_plan_operation||' '||sql_plan_options plan_line,p.object_owner,p.object_name,event
, SUM(1) seconds
, ROUND(RATIO_TO_REPORT(COUNT(*)) OVER () * 100, 1) pct
FROM
v$active_session_history a
, v$sql_plan p
WHERE
a.sql_id = p.sql_id
AND a.sql_child_number = p.child_number
AND a.sql_plan_line_id = p.id
AND session_state = 'WAITING'
AND event = 'cell multiblock physical read'
GROUP BY
sql_plan_operation||' '||sql_plan_options,p.object_owner,p.object_name,event
ORDER BY
seconds DESC
)
WHERE
rownum <= 10
/
PROMPT Report any PARALLEL full table scans which use buffered reads (in-memory PX)
SELECT * FROM (
SELECT
sql_id
, sql_plan_operation||' '||sql_plan_options plan_line
, CASE WHEN qc_session_id IS NULL THEN 'SERIAL' ELSE 'PARALLEL' END is_parallel
-- , px_flags
, session_state
, wait_class
, event
, COUNT(*)
, ROUND(RATIO_TO_REPORT(COUNT(*)) OVER () * 100, 1) pct
FROM &ash
WHERE
sql_plan_operation = 'TABLE ACCESS'
AND sql_plan_options = 'STORAGE FULL'
AND session_state = 'WAITING'
AND event IN ('cell single block physical read', 'cell multiblock physical read', 'cell list of blocks physical read')
AND qc_session_id IS NOT NULL -- is a px session
GROUP BY
sql_id
, sql_plan_operation||' '||sql_plan_options
, CASE WHEN qc_session_id IS NULL THEN 'SERIAL' ELSE 'PARALLEL' END --is_parallel
-- , px_flags
, session_state
, wait_class
, event
ORDER BY COUNT(*) DESC
)
WHERE rownum <= 20
/
DEF sqlid=4mpjt2rhwd1p4
PROMPT Report a single SQL_ID &sqlid
SELECT * FROM (
SELECT
sql_plan_operation||' '||sql_plan_options plan_line,session_state,event
, SUM(1) seconds
, ROUND(RATIO_TO_REPORT(COUNT(*)) OVER () * 100, 1) pct
FROM &ash
WHERE
sql_id = '&sqlid'
GROUP BY
sql_plan_operation||' '||sql_plan_options,session_state,event
ORDER BY
seconds DESC
)
WHERE
rownum <= 10
/

389
tpt/exadata/exasnap.sql Normal file
View File

@@ -0,0 +1,389 @@
-- 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: exasnap.sql (Exadata Snapper) BETA
--
-- Purpose: Display various Exadata IO efficiency metrics of a session
-- from V$SESSTAT.
--
-- Author: Tanel Poder ( http://blog.tanelpoder.com | tanel@tanelpoder.com )
--
-- Copyright: (c) 2012 All Rights Reserved
--
-- Usage:
-- 1) TAKE A SNAPSHOT
--
-- SELECT exasnap.begin_snap(<sid>) FROM dual;
-- or
-- SELECT exasnap.begin_snap('<sid>[@<instance#>]') FROM dual;
--
-- 2) Run the measured query in the session you snapshotted
-- (or just wait for it to run a while)
--
-- 3) TAKE A 2ND SNAPSHOT
--
-- SELECT exasnap.begin_snap(<sid>) FROM dual;
-- or
-- SELECT exasnap.begin_snap('<sid>[@<instance#>]') FROM dual;
--
-- 4) REPORT SESSION METRICS
--
-- @exasnap.sql basic <begin_snap> <end_snap>
-- or
-- @exasnap.sql % <begin_snap> <end_snap>
--
-- The latter script gives you more output.
--
-- Other: This is still a pretty raw script in development and will
-- probably change a lot once it reaches v1.0.
--
-- The PX slaves aggregate their metrics back to the QC session
-- once the query completes, so querying the QC session only is
-- ok if you wait for the query to finish (or cancel it) before
-- taking a snapshot.
-- To measure a query still running,
--
--------------------------------------------------------------------------------
SET LINES 999 PAGES 5000 TRIMOUT ON TRIMSPOOL ON TAB OFF
COL ioeff_percentage FOR A52
BREAK ON inst_id SKIP 1 ON SID ON CATEGORY SKIP 1 DUP
-- keep in capital (MB or GB)
DEF unit=MB
-- adjust for MB or GB
DEF divisor=1024*1024
DEF blocksize=8192
DEF asm_mirrors=2
DEFINE nothing =""
PROMPT
PROMPT ---------------------------------------------------------------------------------------------------------------------------------------------&nothing
PROMPT -- Exadata Snapper v0.5 BETA by Tanel Poder @ Enkitec - The Exadata Experts ( http://www.enkitec.com )
PROMPT ---------------------------------------------------------------------------------------------------------------------------------------------&nothing
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 +
-- TODO this is not needed
TO_NUMBER(TO_CHAR(esn2.snap_time,'xFF')) -
TO_NUMBER(TO_CHAR(esn1.snap_time,'xFF')) snap_seconds -- looks like the last part is buggy but it's too late to figure this out!
, 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 = &2
AND esn2.snap_id = &3
--
-- 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
, ROUND((phyrd_bytes)/(&divisor)) db_physrd_&unit
, ROUND((phywr_bytes)/(&divisor)) db_physwr_&unit
, ROUND((phyrd_bytes+phywr_bytes)/(&divisor)) db_physio_&unit
, ROUND(pred_offloadable_bytes/(&divisor)) pred_offloadable_&unit
, ROUND(phyrd_optim_bytes/(&divisor)) phyrd_optim_&unit
, ROUND((phyrd_optim_bytes-storidx_saved_bytes)/(&divisor)) phyrd_flash_rd_&unit
, ROUND(storidx_saved_bytes/(&divisor)) phyrd_storidx_saved_&unit
, ROUND((phyrd_bytes-phyrd_optim_bytes)/(&divisor)) spin_disk_rd_&unit
, ROUND((phyrd_bytes-phyrd_optim_bytes+(phywr_bytes*&asm_mirrors))/(&divisor)) spin_disk_io_&unit
, ROUND(uncompressed_bytes/(&divisor)) scanned_uncomp_&unit
, ROUND(interconnect_bytes/(&divisor)) total_ic_&unit
, ROUND(smart_scan_ret_bytes/(&divisor)) smart_scan_ret_&unit
, ROUND((interconnect_bytes-smart_scan_ret_bytes)/(&divisor)) non_smart_scan_&unit
, ROUND(cell_proc_cache_blk * &blocksize / (&divisor)) cell_proc_cache_&unit
, ROUND(cell_proc_txn_blk * &blocksize / (&divisor)) cell_proc_txn_&unit
, ROUND(cell_proc_data_blk * &blocksize / (&divisor)) cell_proc_data_&unit
, ROUND(cell_proc_index_blk * &blocksize / (&divisor)) cell_proc_index_&unit
, ROUND(curr_gets_cache_blk * &blocksize / (&divisor)) curr_gets_cache_&unit
, ROUND(cons_gets_cache_blk * &blocksize / (&divisor)) cons_gets_cache_&unit
, ROUND(curr_gets_direct_blk * &blocksize / (&divisor)) curr_gets_direct_&unit
, ROUND(cons_gets_direct_blk * &blocksize / (&divisor)) cons_gets_direct_&unit
, ROUND(cell_bal_cpu_bytes / (&divisor)) cell_bal_cpu_&unit
, ROUND(net_to_client_bytes / (&divisor)) net_to_client_&unit
, ROUND(net_from_client_bytes / (&divisor)) net_from_client_&unit
, chain_fetch_cont_row
, chain_rows_skipped
, chain_rows_processed
, chain_rows_rejected
FROM sq
),
precalc2 AS (
SELECT
inst_id
, sid
, db_physio_&unit
, db_physrd_&unit
, db_physwr_&unit
, pred_offloadable_&unit
, phyrd_optim_&unit
, phyrd_flash_rd_&unit + spin_disk_rd_&unit phyrd_disk_and_flash_&unit
, phyrd_flash_rd_&unit
, phyrd_storidx_saved_&unit
, spin_disk_io_&unit
, spin_disk_rd_&unit
, ((spin_disk_io_&unit - spin_disk_rd_&unit)) AS spin_disk_wr_&unit
, scanned_uncomp_&unit
, ROUND((scanned_uncomp_&unit/NULLIF(spin_disk_rd_&unit + phyrd_flash_rd_&unit, 0))*db_physrd_&unit) est_full_uncomp_&unit
, total_ic_&unit
, smart_scan_ret_&unit
, non_smart_scan_&unit
, cell_proc_cache_&unit
, cell_proc_txn_&unit
, cell_proc_data_&unit
, cell_proc_index_&unit
, cell_bal_cpu_&unit
, curr_gets_cache_&unit
, cons_gets_cache_&unit
, curr_gets_direct_&unit
, cons_gets_direct_&unit
, net_to_client_&unit
, net_from_client_&unit
, chain_fetch_cont_row
, chain_rows_skipped
, chain_rows_processed
, chain_rows_rejected
FROM
precalc
),
--SELECT
-- inst_id
-- , SUM(db_physio_&unit)
-- , SUM(db_physrd_&unit)
-- , SUM(db_physwr_&unit)
-- , SUM(pred_offloadable_&unit)
-- , SUM(phyrd_optim_&unit)
-- , SUM(spin_disk_io_&unit)
-- , SUM(spin_disk_rd_&unit)
-- , SUM(spin_disk_io_&unit - spin_disk_rd_&unit) AS spin_disk_wr_&unit
-- , SUM(scanned_uncomp_&unit)
-- , ROUND(SUM((scanned_uncomp_&unit/spin_disk_rd_&unit)*db_physrd_&unit)) AS est_full_uncomp_&unit
-- , SUM(total_ic_&unit)
-- , SUM(smart_scan_ret_&unit)
-- , SUM(non_smart_scan_&unit)
--FROM
-- precalc2
--GROUP BY ROLLUP
-- (inst_id)
--/
unpivoted AS (
SELECT * FROM precalc2
UNPIVOT (
&unit
FOR metric
IN (
phyrd_optim_&unit
, phyrd_disk_and_flash_&unit
, phyrd_flash_rd_&unit
, phyrd_storidx_saved_&unit
, spin_disk_rd_&unit
, spin_disk_wr_&unit
, spin_disk_io_&unit
, db_physrd_&unit
, db_physwr_&unit
, db_physio_&unit
, scanned_uncomp_&unit
, est_full_uncomp_&unit
, non_smart_scan_&unit
, smart_scan_ret_&unit
, total_ic_&unit
, pred_offloadable_&unit
, cell_proc_cache_&unit
, cell_proc_txn_&unit
, cell_proc_data_&unit
, cell_proc_index_&unit
, cell_bal_cpu_&unit
, curr_gets_cache_&unit
, cons_gets_cache_&unit
, curr_gets_direct_&unit
, cons_gets_direct_&unit
, net_to_client_&unit
, net_from_client_&unit
, chain_fetch_cont_row
, chain_rows_skipped
, chain_rows_processed
, chain_rows_rejected
)
)
),
metric AS (
SELECT 'BASIC' type, 'DB_LAYER_IO' category, 'DB_PHYSIO_&unit' name FROM dual UNION ALL
SELECT 'BASIC', 'DB_LAYER_IO', 'DB_PHYSRD_&unit' FROM dual UNION ALL
SELECT 'BASIC', 'DB_LAYER_IO', 'DB_PHYSWR_&unit' FROM dual UNION ALL
SELECT 'ADVANCED', 'AVOID_DISK_IO', 'PHYRD_OPTIM_&unit' FROM dual UNION ALL
SELECT 'ADVANCED', 'AVOID_DISK_IO', 'PHYRD_DISK_AND_FLASH_&unit' FROM dual UNION ALL
SELECT 'BASIC', 'AVOID_DISK_IO', 'PHYRD_FLASH_RD_&unit' FROM dual UNION ALL
SELECT 'BASIC', 'AVOID_DISK_IO', 'PHYRD_STORIDX_SAVED_&unit' FROM dual UNION ALL
SELECT 'BASIC', 'REAL_DISK_IO', 'SPIN_DISK_IO_&unit' FROM dual UNION ALL
SELECT 'BASIC', 'REAL_DISK_IO', 'SPIN_DISK_RD_&unit' FROM dual UNION ALL
SELECT 'BASIC', 'REAL_DISK_IO', 'SPIN_DISK_WR_&unit' FROM dual UNION ALL
SELECT 'ADVANCED', 'COMPRESS', 'SCANNED_UNCOMP_&unit' FROM dual UNION ALL
SELECT 'ADVANCED', 'COMPRESS', 'EST_FULL_UNCOMP_&unit' FROM dual UNION ALL
SELECT 'BASIC', 'REDUCE_INTERCONNECT', 'PRED_OFFLOADABLE_&unit' FROM dual UNION ALL
SELECT 'BASIC', 'REDUCE_INTERCONNECT', 'TOTAL_IC_&unit' FROM dual UNION ALL
SELECT 'BASIC', 'REDUCE_INTERCONNECT', 'SMART_SCAN_RET_&unit' FROM dual UNION ALL
SELECT 'BASIC', 'REDUCE_INTERCONNECT', 'NON_SMART_SCAN_&unit' FROM dual UNION ALL
SELECT 'ADVANCED', 'CELL_PROC_DEPTH', 'CELL_PROC_CACHE_&unit' FROM DUAL UNION ALL
SELECT 'ADVANCED', 'CELL_PROC_DEPTH', 'CELL_PROC_TXN_&unit' FROM DUAL UNION ALL
SELECT 'BASIC', 'CELL_PROC_DEPTH', 'CELL_PROC_DATA_&unit' FROM DUAL UNION ALL
SELECT 'BASIC', 'CELL_PROC_DEPTH', 'CELL_PROC_INDEX_&unit' FROM DUAL UNION ALL
SELECT 'ADVANCED', 'CELL_PROC_DEPTH', 'CELL_BAL_CPU_&unit' FROM DUAL UNION ALL
SELECT 'ADVANCED', 'IN_DB_PROCESSING', 'CURR_GETS_CACHE_&unit' FROM DUAL UNION ALL
SELECT 'ADVANCED', 'IN_DB_PROCESSING', 'CONS_GETS_CACHE_&unit' FROM DUAL UNION ALL
SELECT 'ADVANCED', 'IN_DB_PROCESSING', 'CURR_GETS_DIRECT_&unit' FROM DUAL UNION ALL
SELECT 'ADVANCED', 'IN_DB_PROCESSING', 'CONS_GETS_DIRECT_&unit' FROM DUAL UNION ALL
SELECT 'BASIC', 'CLIENT_COMMUNICATION', 'NET_TO_CLIENT_&unit' FROM DUAL UNION ALL
SELECT 'BASIC', 'CLIENT_COMMUNICATION', 'NET_FROM_CLIENT_&unit' 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
)
SELECT
-- inst_id
-- , sid
category
-- , type
, metric
, '|'||RPAD(NVL(RPAD('#', ROUND(&unit / NULLIF( (SELECT MAX(&unit) FROM unpivoted u, metric m WHERE u.metric = m.name AND m.type LIKE UPPER('&1')), 0) * 50 ), '#'), ' '), 50, ' ')||'|' ioeff_percentage
, &unit
, TO_CHAR(ROUND(&unit / (SELECT snap_seconds FROM stats WHERE rownum = 1),1), '9999999.9') AS " &unit/sec"
FROM
unpivoted u
, metric m
WHERE
u.metric = m.name
AND m.type LIKE UPPER('&1')
/

View 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;

123
tpt/exadata/exastat.py Normal file
View File

@@ -0,0 +1,123 @@
#!/usr/bin/env python
################################################################################
##
## File name: exastat.py (v1.0)
## Purpose: Show cumulative exadata metrics from CELLCLI and their deltas
## in multicolumn format
##
## Author: Tanel Poder ( tanel@tanelpoder.com | @tanelpoder | blog.tanelpoder.com )
## Copyright: Tanel Poder. All Rights Reserved.
##
## Usage: Save LIST METRICHISTORY into a file or pipe directly to exastat
##
## Example: cellcli -e "LIST METRICHISTORY WHERE name LIKE 'FL_.*' AND collectionTime > '"`date --date \
## '1 day ago' "+%Y-%m-%dT%H:%M:%S%:z"`"'" | ./exastat FL_DISK_FIRST FL_FLASH_FIRST
##
## The above example lists you two metrics FL_DISK_FIRST and FL_FLASH_FIRST in columnar format
## You can list any number of metrics (you're not restricted to only two)
##
##
################################################################################
import fileinput, re, datetime, time, sys
DEBUG=False
rawmetrics = {} # main metric array
errors = [] # unparsable lines
timestamps = []
cell_pattern = re.compile(r"^\s*(?P<name>\w+)\s+(?P<obj>\w+)\s+(?P<value>[\w,]+)\s(?P<unit>.*)\s+(?P<timestamp>.{25})$")
def extract_metric_value(s, pattern):
match = pattern.match(s)
if match:
name = match.group("name").strip()
obj = match.group("obj").strip()
value = int(match.group("value").strip().replace(',',''))
unit = match.group("unit").strip()
timestamp = datetime.datetime.fromtimestamp(time.mktime(time.strptime(match.group("timestamp").strip()[:-6], "%Y-%m-%dT%H:%M:%S")))
return {"METRIC_NAME":name, "METRIC_OBJECT":obj, "METRIC_VALUE":value, "METRIC_UNIT":unit, "TIMESTAMP":timestamp}
def get_timestamps(m):
t = []
for i in (key for key in sorted(m.keys(), key=lambda x: x[1])):
if not t.__contains__(i[1]):
t.append( i[1] )
return t
def get_ordered_metric_values(m, metric_name):
r = []
for i in (key for key in sorted(m.keys(), key=lambda x: x[1]) if key[0]==metric_name):
if DEBUG: print "key = %s value = %s" % (i, m[i])
r.append({ "METRIC_NAME":i[0], "TIMESTAMP":i[1], "METRIC_OBJECT":i[2], "METRIC_VALUE":m[i]["METRIC_VALUE"], "METRIC_UNIT":m[i]["METRIC_UNIT"] })
return r
def get_delta_metric_values(m, metric_name):
r = {}
prev_metric_value = None
# requires ordered input
for i in (key for key in (get_ordered_metric_values(m, metric_name))):
if prev_metric_value:
if DEBUG: print "%s delta %s = %s (%s - %s)" % ( i["TIMESTAMP"], i["METRIC_NAME"], i["METRIC_VALUE"] - prev_metric_value, i["METRIC_VALUE"], prev_metric_value )
r[i["TIMESTAMP"]] = ( i["TIMESTAMP"], i["METRIC_NAME"], i["METRIC_VALUE"] - prev_metric_value, i["METRIC_VALUE"], prev_metric_value )
prev_metric_value = i["METRIC_VALUE"]
else:
prev_metric_value = i["METRIC_VALUE"]
return r
# main()
metric_list = sys.argv[1:]
for line in sys.stdin.readlines():
e = extract_metric_value(line, cell_pattern)
if e:
if e["METRIC_NAME"] in metric_list:
rawmetrics[e["METRIC_NAME"], e["TIMESTAMP"], e["METRIC_OBJECT"]] = { "METRIC_VALUE":e["METRIC_VALUE"], "METRIC_UNIT":e["METRIC_UNIT"] }
else:
errors.append(line)
if DEBUG: print "len(rawmetrics) = %s len(errors) = %s" % (len(rawmetrics), len(errors))
m = {}
for mn in metric_list:
m[mn] = get_delta_metric_values(rawmetrics, mn)
timestamps = get_timestamps(rawmetrics)
if DEBUG: print timestamps.pop(0) # 0-th sample doesn't have delta
output_header = ("%-26s %10s" % ("TIMESTAMP", "SECONDS"))
output_separator = "%-26s %10s" % ("-" * 26, "-" * 10)
for x in metric_list:
output_header += ("%" + str(len(x)+1) +"s") % x
output_separator += ' ' + '-' * len(x)
print ""
print output_header
print output_separator
prev_ts = None
for ts in iter(timestamps):
if prev_ts:
out = "%-26s %10s" % (ts, (ts - prev_ts).seconds)
prev_ts = ts
else:
out = "%-26s %10s" % (ts, "")
prev_ts = ts
for mn in metric_list:
if ts in m[mn]:
v = m[mn][ts][2]
else:
v = 0
out += (" %"+str(len(mn)) +"d") % v
print out
print ""

68
tpt/exadata/exatest.sql Normal file
View File

@@ -0,0 +1,68 @@
-- 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.
DROP TYPE mystats_t;
DROP TYPE mystats_r;
DROP PACKAGE exatest;
DROP TYPE mystats_t;
CREATE OR REPLACE VIEW mys AS
SELECT sn.name, my.value
FROM v$statname sn, v$mystat my
WHERE sn.statistic# = my.statistic#
/
CREATE OR REPLACE TYPE mystats_r AS OBJECT (name VARCHAR2(64), value NUMBER);
/
CREATE OR REPLACE TYPE mystats_t AS TABLE OF mystats_r
/
-- DROP PACKAGE exatest;
CREATE OR REPLACE PACKAGE exatest AS
PROCEDURE snap;
FUNCTION diff(filter IN VARCHAR2 DEFAULT NULL) RETURN mystats_t PIPELINED;
stats mystats_t;
END;
/
CREATE OR REPLACE PACKAGE BODY exatest AS
prev_stats mystats_t;
PROCEDURE SNAP AS
BEGIN
prev_stats := exatest.stats;
SELECT mystats_r(name,value) BULK COLLECT INTO exatest.stats FROM mys;
END snap;
FUNCTION diff(filter IN VARCHAR2 DEFAULT NULL) RETURN mystats_t PIPELINED AS
BEGIN
snap;
FOR i IN (SELECT
now.name
, now.value - prev.value diff
FROM
TABLE(CAST(exatest.stats AS mystats_t)) now
, TABLE(CAST(prev_stats AS mystats_t)) prev
WHERE prev.name = now.name
) LOOP
IF FILTER IS NULL THEN
IF i.diff != 0 THEN
PIPE ROW (mystats_r(i.name,i.diff));
END IF;
ELSE
IF REGEXP_LIKE(i.name, filter, 'i') THEN
PIPE ROW (mystats_r(i.name,i.diff));
END IF;
END IF; -- if filter is null
END LOOP;
END diff;
BEGIN
snap;
END;
/
SHOW ERR

View File

@@ -0,0 +1,45 @@
-- 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.
-- small tables
-- EXEC EXECUTE IMMEDIATE 'drop table t_hcc_query_low'; EXCEPTION WHEN OTHERS THEN NULL;
-- EXEC EXECUTE IMMEDIATE 'drop table t_hcc_query_high'; EXCEPTION WHEN OTHERS THEN NULL;
-- EXEC EXECUTE IMMEDIATE 'drop table t_hcc_archive_low'; EXCEPTION WHEN OTHERS THEN NULL;
-- EXEC EXECUTE IMMEDIATE 'drop table t_hcc_archive_high'; EXCEPTION WHEN OTHERS THEN NULL;
--
-- CREATE TABLE t_hcc_query_low COMPRESS FOR QUERY LOW AS SELECT * FROM dba_source;
-- CREATE TABLE t_hcc_query_high COMPRESS FOR QUERY HIGH AS SELECT * FROM dba_source;
-- CREATE TABLE t_hcc_archive_low COMPRESS FOR ARCHIVE LOW AS SELECT * FROM dba_source;
-- CREATE TABLE t_hcc_archive_high COMPRESS FOR ARCHIVE HIGH AS SELECT * FROM dba_source;
-- large tables
-- EXEC EXECUTE IMMEDIATE 'drop table t_hcc_query_low'; EXCEPTION WHEN OTHERS THEN NULL;
-- EXEC EXECUTE IMMEDIATE 'drop table t_hcc_query_high'; EXCEPTION WHEN OTHERS THEN NULL;
-- EXEC EXECUTE IMMEDIATE 'drop table t_hcc_archive_low'; EXCEPTION WHEN OTHERS THEN NULL;
-- EXEC EXECUTE IMMEDIATE 'drop table t_hcc_archive_high'; EXCEPTION WHEN OTHERS THEN NULL;
--
-- CREATE TABLE t_hcc_query_low COMPRESS FOR QUERY LOW AS SELECT * FROM dba_objects, (SELECT 'x' text FROM dual CONNECT BY LEVEL <=10);
-- CREATE TABLE t_hcc_query_high COMPRESS FOR QUERY HIGH AS SELECT * FROM dba_objects, (SELECT 'x' text FROM dual CONNECT BY LEVEL <=10);
-- CREATE TABLE t_hcc_archive_low COMPRESS FOR ARCHIVE LOW AS SELECT * FROM dba_objects, (SELECT 'x' text FROM dual CONNECT BY LEVEL <=10);
-- CREATE TABLE t_hcc_archive_high COMPRESS FOR ARCHIVE HIGH AS SELECT * FROM dba_objects, (SELECT 'x' text FROM dual CONNECT BY LEVEL <=10);
EXEC exatest.snap
SELECT SUM(LENGTH(text)) query_low FROM t_hcc_query_low;
SELECT * FROM TABLE(exatest.diff('EHCC.*'));
--SELECT * FROM TABLE(exatest.diff('EHCC CUs Decompressed|EHCC.*Length Decompressed'));
SELECT SUM(LENGTH(text)) query_high FROM t_hcc_query_high;
SELECT * FROM TABLE(exatest.diff('EHCC.*'));
--SELECT * FROM TABLE(exatest.diff('EHCC CUs Decompressed|EHCC.*Length Decompressed'));
SELECT SUM(LENGTH(text)) archive_low FROM t_hcc_archive_low;
SELECT * FROM TABLE(exatest.diff('EHCC.*'));
--SELECT * FROM TABLE(exatest.diff('EHCC CUs Decompressed|EHCC.*Length Decompressed'));
SELECT SUM(LENGTH(text)) archive_high FROM t_hcc_archive_high;
SELECT * FROM TABLE(exatest.diff('EHCC.*'));
--SELECT * FROM TABLE(exatest.diff('EHCC CUs Decompressed|EHCC.*Length Decompressed'));

View File

@@ -0,0 +1,45 @@
-- 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.
-- small tables
-- EXEC EXECUTE IMMEDIATE 'drop table t_hcc_query_low'; EXCEPTION WHEN OTHERS THEN NULL;
-- EXEC EXECUTE IMMEDIATE 'drop table t_hcc_query_high'; EXCEPTION WHEN OTHERS THEN NULL;
-- EXEC EXECUTE IMMEDIATE 'drop table t_hcc_archive_low'; EXCEPTION WHEN OTHERS THEN NULL;
-- EXEC EXECUTE IMMEDIATE 'drop table t_hcc_archive_high'; EXCEPTION WHEN OTHERS THEN NULL;
--
-- CREATE TABLE t_hcc_query_low COMPRESS FOR QUERY LOW AS SELECT * FROM dba_source;
-- CREATE TABLE t_hcc_query_high COMPRESS FOR QUERY HIGH AS SELECT * FROM dba_source;
-- CREATE TABLE t_hcc_archive_low COMPRESS FOR ARCHIVE LOW AS SELECT * FROM dba_source;
-- CREATE TABLE t_hcc_archive_high COMPRESS FOR ARCHIVE HIGH AS SELECT * FROM dba_source;
-- large tables
-- EXEC EXECUTE IMMEDIATE 'drop table t_hcc_query_low'; EXCEPTION WHEN OTHERS THEN NULL;
-- EXEC EXECUTE IMMEDIATE 'drop table t_hcc_query_high'; EXCEPTION WHEN OTHERS THEN NULL;
-- EXEC EXECUTE IMMEDIATE 'drop table t_hcc_archive_low'; EXCEPTION WHEN OTHERS THEN NULL;
-- EXEC EXECUTE IMMEDIATE 'drop table t_hcc_archive_high'; EXCEPTION WHEN OTHERS THEN NULL;
--
-- CREATE TABLE t_hcc_query_low COMPRESS FOR QUERY LOW AS SELECT * FROM dba_objects, (SELECT 'x' text FROM dual CONNECT BY LEVEL <=10);
-- CREATE TABLE t_hcc_query_high COMPRESS FOR QUERY HIGH AS SELECT * FROM dba_objects, (SELECT 'x' text FROM dual CONNECT BY LEVEL <=10);
-- CREATE TABLE t_hcc_archive_low COMPRESS FOR ARCHIVE LOW AS SELECT * FROM dba_objects, (SELECT 'x' text FROM dual CONNECT BY LEVEL <=10);
-- CREATE TABLE t_hcc_archive_high COMPRESS FOR ARCHIVE HIGH AS SELECT * FROM dba_objects, (SELECT 'x' text FROM dual CONNECT BY LEVEL <=10);
EXEC exatest.snap
SELECT SUM(LENGTH(text)) query_low FROM t_hcc_query_low WHERE owner LIKE '%S%';
SELECT * FROM TABLE(exatest.diff('cell.*'));
--SELECT * FROM TABLE(exatest.diff('EHCC CUs Decompressed|EHCC.*Length Decompressed'));
SELECT SUM(LENGTH(text)) query_high FROM t_hcc_query_high WHERE owner LIKE '%S%';
SELECT * FROM TABLE(exatest.diff('cell.*'));
--SELECT * FROM TABLE(exatest.diff('EHCC CUs Decompressed|EHCC.*Length Decompressed'));
SELECT SUM(LENGTH(text)) archive_low FROM t_hcc_archive_low WHERE owner LIKE '%S%';
SELECT * FROM TABLE(exatest.diff('cell.*'));
--SELECT * FROM TABLE(exatest.diff('EHCC CUs Decompressed|EHCC.*Length Decompressed'));
SELECT SUM(LENGTH(text)) archive_high FROM t_hcc_archive_high WHERE owner LIKE '%S%';
SELECT * FROM TABLE(exatest.diff('cell.*'));
--SELECT * FROM TABLE(exatest.diff('EHCC CUs Decompressed|EHCC.*Length Decompressed'));

View File

@@ -0,0 +1,38 @@
-- 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.
DROP TABLE test_impx;
CREATE TABLE test_impx (
id NUMBER NOT NULL
, owner VARCHAR2(30)
, object_name VARCHAR2(128)
, subobject_name VARCHAR2(30)
, object_id NUMBER
, data_object_id NUMBER
, object_type VARCHAR2(19)
, created DATE
, last_ddl_time DATE
, timestamp VARCHAR2(19)
, status VARCHAR2(7)
, temporary VARCHAR2(1)
, generated VARCHAR2(1)
, secondary VARCHAR2(1)
, namespace NUMBER
, edition_name VARCHAR2(30)
)
PARTITION BY RANGE (id) (
PARTITION id_05m VALUES LESS THAN (6000000)
, PARTITION id_09m VALUES LESS THAN (MAXVALUE)
)
/
INSERT
/*+ APPEND */ INTO test_impx
SELECT
ROWNUM id, t.*
FROM
dba_objects t
, (SELECT 1 FROM dual CONNECT BY LEVEL <= 100) u -- cartesian join for generating lots of rows
/
@gts test_impx

View File

@@ -0,0 +1,25 @@
-- 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.
SELECT * FROM (
SELECT
sql_id
, executions
, px_servers_executions px_execs
, physical_read_requests phyrd_rq
, ROUND(physical_read_bytes/1048576) physrd_mb
, ROUND((physical_read_bytes / physical_read_requests) / 1024) avg_read_kb
, optimized_phy_read_requests opt_phyrd_rq
, ROUND(((physical_read_bytes / physical_read_requests) * optimized_phy_read_requests) / 1048576) est_optim_mb
, ROUND(optimized_phy_read_requests / physical_read_requests * 100) opt_rq_pct
FROM
v$sql
WHERE
optimized_phy_read_requests > 0
ORDER BY
optimized_phy_read_requests DESC
)
WHERE
rownum <= 20
/

160
tpt/exadata/ioeff.sql Normal file
View File

@@ -0,0 +1,160 @@
-- 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: ioeff.sql
-- Purpose: Display various Exadata IO efficiency metrics
-- from all Exadata RAC cluster nodes
--
-- Author: Tanel Poder
-- Copyright: (c) 2012 http://blog.tanelpoder.com
--
-- Usage: Run ioeff.sql
--
-- Other: This is still a raw experimental script and doesn't do a good
-- job with explaining these metrics well yet
--
--------------------------------------------------------------------------------
SET LINES 999 PAGES 5000 TRIMOUT ON TRIMSPOOL ON TAB OFF
COL ioeff_percentage FOR A52
BREAK ON inst_id SKIP 1
WITH sq AS (
SELECT
*
FROM (
SELECT inst_id, name, value
FROM gv$sysstat
WHERE
name LIKE 'cell%bytes%'
OR name LIKE 'physical%bytes%'
)
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_offload_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
)
)
),
precalc AS (
SELECT
inst_id
, ROUND((phyrd_bytes)/(1024*1024*1024)) db_physrd_gb
, ROUND((phywr_bytes)/(1024*1024*1024)) db_physwr_gb
, ROUND((phyrd_bytes+phywr_bytes)/(1024*1024*1024)) db_physio_gb
, ROUND(pred_offload_bytes/(1024*1024*1024)) pred_offload_gb
, ROUND(phyrd_optim_bytes/(1024*1024*1024)) phyrd_optim_gb
, ROUND((phyrd_optim_bytes-storidx_saved_bytes)/(1024*1024*1024)) phyrd_flash_rd_gb
, ROUND((phyrd_bytes-phyrd_optim_bytes)/(1024*1024*1024)) spin_disk_rd_gb
, ROUND((phyrd_bytes+phywr_bytes-phyrd_optim_bytes)/(1024*1024*1024)) spin_disk_io_gb
, ROUND(uncompressed_bytes/(1024*1024*1024)) scanned_uncomp_gb
, ROUND(interconnect_bytes/(1024*1024*1024)) total_ic_gb
, ROUND(smart_scan_ret_bytes/(1024*1024*1024)) smart_scan_gb
, ROUND((interconnect_bytes-smart_scan_ret_bytes)/(1024*1024*1024)) non_smart_scan_gb
FROM sq
),
precalc2 AS (
SELECT
inst_id
, db_physio_gb
, db_physrd_gb
, db_physwr_gb
, pred_offload_gb
, phyrd_optim_gb
, phyrd_flash_rd_gb + spin_disk_rd_gb phyrd_disk_and_flash_gb
, phyrd_flash_rd_gb
, spin_disk_io_gb
, spin_disk_rd_gb
, spin_disk_io_gb - spin_disk_rd_gb AS spin_disk_wr_gb
, scanned_uncomp_gb
, ROUND((scanned_uncomp_gb/spin_disk_rd_gb)*db_physrd_gb) est_full_uncomp_gb
, total_ic_gb
, smart_scan_gb
, non_smart_scan_gb
FROM
precalc
),
--SELECT
-- inst_id
-- , SUM(db_physio_gb)
-- , SUM(db_physrd_gb)
-- , SUM(db_physwr_gb)
-- , SUM(pred_offload_gb)
-- , SUM(phyrd_optim_gb)
-- , SUM(spin_disk_io_gb)
-- , SUM(spin_disk_rd_gb)
-- , SUM(spin_disk_io_gb - spin_disk_rd_gb) AS spin_disk_wr_gb
-- , SUM(scanned_uncomp_gb)
-- , ROUND(SUM((scanned_uncomp_gb/spin_disk_rd_gb)*db_physrd_gb)) AS est_full_uncomp_gb
-- , SUM(total_ic_gb)
-- , SUM(smart_scan_gb)
-- , SUM(non_smart_scan_gb)
--FROM
-- precalc2
--GROUP BY ROLLUP
-- (inst_id)
--/
unpivoted AS (
SELECT * FROM precalc2
UNPIVOT (
gb
FOR metric
IN (
phyrd_optim_gb
, phyrd_disk_and_flash_gb
, phyrd_flash_rd_gb
, scanned_uncomp_gb
, est_full_uncomp_gb
, non_smart_scan_gb
, smart_scan_gb
, total_ic_gb
, pred_offload_gb
, spin_disk_rd_gb
, spin_disk_wr_gb
, spin_disk_io_gb
, db_physrd_gb
, db_physwr_gb
, db_physio_gb
)
)
),
metric AS (
SELECT 'ADVANCED' type, 'AVOID_DISK_IO' category, 'PHYRD_OPTIM_GB' name FROM dual UNION ALL
SELECT 'ADVANCED', 'AVOID_DISK_IO', 'PHYRD_DISK_AND_FLASH_GB' FROM dual UNION ALL
SELECT 'ADVANCED', 'AVOID_DISK_IO', 'PHYRD_FLASH_RD_GB' FROM dual UNION ALL
SELECT 'ADVANCED', 'COMPRESS', 'SCANNED_UNCOMP_GB' FROM dual UNION ALL
SELECT 'ADVANCED', 'COMPRESS', 'EST_FULL_UNCOMP_GB' FROM dual UNION ALL
SELECT 'ADVANCED', 'REDUCE_INTERCONNECT', 'TOTAL_IC_GB' FROM dual UNION ALL
SELECT 'ADVANCED', 'REDUCE_INTERCONNECT', 'NON_SMART_SCAN_GB' FROM dual UNION ALL
SELECT 'ADVANCED', 'REDUCE_INTERCONNECT', 'SMART_SCAN_GB' FROM dual UNION ALL
SELECT 'ADVANCED', 'REDUCE_INTERCONNECT', 'PRED_OFFLOAD_GB' FROM dual UNION ALL
SELECT 'ADVANCED', 'DISK_IO', 'SPIN_DISK_RD_GB' FROM dual UNION ALL
SELECT 'ADVANCED', 'DISK_IO', 'SPIN_DISK_WR_GB' FROM dual UNION ALL
SELECT 'ADVANCED', 'DISK_IO', 'SPIN_DISK_IO_GB' FROM dual UNION ALL
SELECT 'ADVANCED', 'DISK_IO', 'DB_PHYSRD_GB' FROM dual UNION ALL
SELECT 'ADVANCED', 'DISK_IO', 'DB_PHYSWR_GB' FROM dual UNION ALL
SELECT 'ADVANCED', 'DISK_IO', 'DB_PHYSIO_GB' FROM dual
)
SELECT
inst_id
, type
, category
, metric
, '|'||RPAD(NVL(RPAD('#', ROUND(gb / (SELECT MAX(GB) FROM unpivoted) * 50 ), '#'), ' '), 50, ' ')||'|' ioeff_percentage
, gb
FROM
unpivoted u
, metric m
WHERE
u.metric = m.name
/

View File

@@ -0,0 +1,14 @@
-- 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.
DECLARE
cmd VARCHAR2(1000);
BEGIN
FOR i IN (SELECT owner,index_name FROM dba_indexes WHERE table_owner = '&1' AND table_owner NOT IN('SYS', 'SYSTEM') AND index_type NOT IN ('LOB', 'IOT - TOP')) LOOP
cmd := 'ALTER INDEX '||i.owner||'.'||i.index_name||' INVISIBLE';
DBMS_OUTPUT.PUT_LINE(cmd);
EXECUTE IMMEDIATE cmd;
END LOOP;
END;
/

View File

@@ -0,0 +1,14 @@
-- 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.
DECLARE
cmd VARCHAR2(1000);
BEGIN
FOR i IN (SELECT owner,index_name FROM dba_indexes WHERE table_owner = '&1' AND table_owner NOT IN('SYS', 'SYSTEM')) LOOP
cmd := 'ALTER INDEX '||i.owner||'.'||i.index_name||' VISIBLE';
DBMS_OUTPUT.PUT_LINE(cmd);
EXECUTE IMMEDIATE cmd;
END LOOP;
END;
/

152
tpt/exadata/mon_topsql.sql Normal file
View File

@@ -0,0 +1,152 @@
-- 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: mon_topsql.sql (Daily TOP SQL reporting for Exadata)
--
-- Purpose: This script can be used for getting an overview of your most
-- time-consuming SQL statements along with important IO and execution
-- count metrics needed for determining whether a query would
-- benefit from Exadata Smart Scanning features.
--
-- Usage: Run @mon_topsql.sql
--
-- There's a variable called "days" in the beggining of this script
-- which controls how many days worth of history to show.
--
-- Author: Tanel Poder ( http://blog.tanelpoder.com | tanel@tanelpoder.com )
--
-- Copyright: (c) 2012 All Rights Reserved
--
--
-- Other: I recommend you to read through the script to understand what it's
-- doing and how it works.
--
--------------------------------------------------------------------------------
SET LINES 999 PAGES 5000 TRIMSPOOL ON TRIMOUT ON TAB OFF
COL pct FOR A10 JUST RIGHT
COL cpu_pct FOR 999.9
COL io_pct FOR 999.9
COL topsql_owner FOR A30
COL topsql_object_name FOR A30
COL topsql_procedure_name FOR A30
BREAK ON day SKIP 1
DEF days=7
PROMPT Displaying daily top SQL for last &days days...
WITH ash AS (
SELECT
day
, owner
, object_name
, procedure_name
, sql_id
, sql_plan_hash_value
, total_seconds
, io_seconds
, cpu_seconds
, LPAD(TRIM(TO_CHAR(RATIO_TO_REPORT(total_seconds) OVER (PARTITION BY day) * 100, '999.9'))||'%', 10) pct
, RATIO_TO_REPORT(total_seconds) OVER (PARTITION BY day) * 100 pct_num
FROM (
SELECT
TO_CHAR(sample_time, 'YYYY-MM-DD') day
, sql_id
, sql_plan_hash_value
, p.owner
, p.object_name
, p.procedure_name
, SUM(10) total_seconds
, SUM(CASE WHEN wait_class = 'User I/O' THEN 10 ELSE 0 END) io_seconds
, SUM(CASE WHEN wait_class IS NULL THEN 10 ELSE 0 END) cpu_seconds
FROM
dba_hist_active_sess_history a
, dba_procedures p
WHERE
a.plsql_entry_object_id = p.object_id (+)
AND a.plsql_entry_subprogram_id = p.subprogram_id (+)
AND sample_time > SYSDATE - &days
AND session_type != 'BACKGROUND' -- ignore for now
GROUP BY
sql_id
, sql_plan_hash_value
, p.owner
, p.object_name
, p.procedure_name
, TO_CHAR(sample_time, 'YYYY-MM-DD')
)
)
, sqlstat AS (
SELECT /*+ MATERIALIZE */
TO_CHAR(begin_interval_time, 'YYYY-MM-DD') day
, sql_id
, plan_hash_value
, SUM(executions_delta) executions
, SUM(rows_processed_delta) rows_processed
, SUM(disk_reads_delta) blocks_read
, SUM(disk_reads_delta)*8/1024 mb_read
, SUM(buffer_gets_delta) buffer_gets
, SUM(iowait_delta)/1000000 awr_iowait_seconds
, SUM(cpu_time_delta)/1000000 awr_cpu_seconds
, SUM(elapsed_time_delta)/1000000 awr_elapsed_seconds
FROM
dba_hist_snapshot
NATURAL JOIN
dba_hist_sqlstat
WHERE
begin_interval_time > SYSDATE - &days
GROUP BY
TO_CHAR(begin_interval_time, 'YYYY-MM-DD')
, sql_id
, plan_hash_value
)
SELECT /*+ MONITOR */
day
, pct
, owner topsql_owner
, object_name topsql_object_name
, procedure_name topsql_procedure_name
, sql_id
, sql_plan_hash_value plan_hash
, ROUND(total_seconds / 3600,1) total_hours
, total_seconds
, executions
, ROUND(total_seconds / NULLIF(executions,0),2) seconds_per_exec
, io_pct
, cpu_pct
, mb_read
, ROUND(mb_read / NULLIF(executions,0),2) mb_per_exec
, buffer_gets
, ROUND(buffer_gets / NULLIF(executions,0),2) bufget_per_exec
, CASE WHEN sql_id IS NOT NULL THEN
'SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_AWR('''||sql_id||''','||CASE WHEN sql_plan_hash_value = 0 THEN 'NULL' ELSE TO_CHAR(sql_plan_hash_value) END||', format=>''ADVANCED''));'
END extract_plan_from_awr
FROM (
SELECT
day
, pct
, owner
, object_name
, procedure_name
, sql_id
, sql_plan_hash_value
, total_seconds
, io_seconds/total_seconds*100 io_pct
, cpu_seconds/total_seconds*100 cpu_pct
, (SELECT executions FROM sqlstat s WHERE ash.sql_id = s.sql_id AND ash.sql_plan_hash_value = s.plan_hash_value AND ash.day = s.day) executions
, (SELECT mb_read FROM sqlstat s WHERE ash.sql_id = s.sql_id AND ash.sql_plan_hash_value = s.plan_hash_value AND ash.day = s.day) mb_read
, (SELECT buffer_gets FROM sqlstat s WHERE ash.sql_id = s.sql_id AND ash.sql_plan_hash_value = s.plan_hash_value AND ash.day = s.day) buffer_gets
FROM
ash
WHERE
ash.pct_num >= 1
)
ORDER BY
day DESC
, total_seconds DESC
/

151
tpt/exadata/mon_topsql2.sql Normal file
View File

@@ -0,0 +1,151 @@
-- 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.
-- mon_topsql.sql ver2
-- added plan_hash_value support and ordered by descending date
-- script by Tanel Poder ( http://blog.tanelpoder.com )
SET LINES 999 PAGES 5000 TRIMSPOOL ON TRIMOUT ON TAB OFF
COL pct FOR A10 JUST RIGHT
COL cpu_pct FOR 999.9
COL io_pct FOR 999.9
BREAK ON day SKIP 1
DEF days=7
DEF weekdays="mon,tue,wed,thu,fri,sat,sun"
DEF separator=","
WITH ash AS (
SELECT
day
, weekday
, owner
, object_name
, procedure_name
, sql_id
, sql_plan_hash_value
, distinct_days
, total_seconds
, io_seconds
, cpu_seconds
, LPAD(TRIM(TO_CHAR(RATIO_TO_REPORT(total_seconds) OVER (PARTITION BY day) * 100, '999.9'))||'%', 10) pct
, RATIO_TO_REPORT(total_seconds) OVER (PARTITION BY day) * 100 pct_num
FROM (
SELECT
TO_CHAR(sample_time, 'YYYY-MM-DD') day
, TO_CHAR(sample_time, 'Dy') weekday
, COUNT(DISTINCT TO_CHAR(sample_time, 'YYYY-MM-DD')) OVER (PARTITION BY sql_id) distinct_days
, sql_id
, sql_plan_hash_value
, p.owner
, p.object_name
, p.procedure_name
, SUM(10) total_seconds
, SUM(CASE WHEN wait_class = 'User I/O' THEN 10 ELSE 0 END) io_seconds
, SUM(CASE WHEN wait_class IS NULL THEN 10 ELSE 0 END) cpu_seconds
FROM
dba_hist_active_sess_history a
, dba_procedures p
WHERE
a.plsql_entry_object_id = p.object_id (+)
AND a.plsql_entry_subprogram_id = p.subprogram_id (+)
AND sample_time > SYSDATE - &days
AND session_type != 'BACKGROUND' -- ignore for now
AND LOWER(TO_CHAR(sample_time, 'Dy')) IN (
SELECT
LOWER(REGEXP_REPLACE(
REGEXP_SUBSTR( '&weekdays'||'&separator', '(.*?)&separator', 1, LEVEL )
, '&separator$'
, ''
)) TOKEN
FROM
DUAL
CONNECT BY
REGEXP_INSTR( '&weekdays'||'&separator', '(.*?)&separator', 1, LEVEL ) > 0
)
GROUP BY
sql_id
, sql_plan_hash_value
, p.owner
, p.object_name
, p.procedure_name
, TO_CHAR(sample_time, 'YYYY-MM-DD')
, TO_CHAR(sample_time, 'Dy')
)
)
, sqlstat AS (
SELECT
TO_CHAR(begin_interval_time, 'YYYY-MM-DD') day
, sql_id
, plan_hash_value
, SUM(executions_delta) executions
, SUM(rows_processed_delta) rows_processed
, SUM(disk_reads_delta) blocks_read
, SUM(disk_reads_delta)*8/1024 mb_read
, SUM(buffer_gets_delta) buffer_gets
, SUM(iowait_delta)/1000000 awr_iowait_seconds
, SUM(cpu_time_delta)/1000000 awr_cpu_seconds
, SUM(elapsed_time_delta)/1000000 awr_elapsed_seconds
FROM
dba_hist_snapshot
NATURAL JOIN
dba_hist_sqlstat
WHERE
begin_interval_time > SYSDATE - &days
GROUP BY
TO_CHAR(begin_interval_time, 'YYYY-MM-DD')
, sql_id
, plan_hash_value
)
SELECT
day
, weekday
, pct
, owner
, object_name
, procedure_name
, sql_id
, sql_plan_hash_value plan_hash
, distinct_days
, ROUND(total_seconds / 3600,1) total_hours
, total_seconds
, executions
, ROUND(total_seconds / NULLIF(executions,0),2) seconds_per_exec
, io_pct
, cpu_pct
, mb_read
, ROUND(mb_read / NULLIF(executions,0),2) mb_per_exec
, buffer_gets
, ROUND(buffer_gets / NULLIF(executions,0),2) bufget_per_exec
, CASE WHEN sql_id IS NOT NULL THEN
'SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_AWR('''||sql_id||''','||CASE WHEN sql_plan_hash_value = 0 THEN 'NULL' ELSE TO_CHAR(sql_plan_hash_value) END||', format=>''ADVANCED''));'
END extract_plan_from_awr
FROM (
SELECT
day
, weekday
, pct
, owner
, object_name
, procedure_name
, sql_id
, sql_plan_hash_value
, distinct_days
, total_seconds
, io_seconds/total_seconds*100 io_pct
, cpu_seconds/total_seconds*100 cpu_pct
, (SELECT executions FROM sqlstat s WHERE ash.sql_id = s.sql_id AND ash.sql_plan_hash_value = s.plan_hash_value AND ash.day = s.day) executions
, (SELECT mb_read FROM sqlstat s WHERE ash.sql_id = s.sql_id AND ash.sql_plan_hash_value = s.plan_hash_value AND ash.day = s.day) mb_read
, (SELECT buffer_gets FROM sqlstat s WHERE ash.sql_id = s.sql_id AND ash.sql_plan_hash_value = s.plan_hash_value AND ash.day = s.day) buffer_gets
FROM
ash
WHERE
ash.pct_num >= 1
)
ORDER BY
day DESC
, total_seconds DESC
/

View File

@@ -0,0 +1,34 @@
-- 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.
SET ECHO ON
-- DROP TABLE t;
-- CREATE TABLE t AS SELECT a.* FROM dba_objects a, dba_objects b WHERE rownum <= 10000000;
-- EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'T');
SET TIMING ON
SELECT /* test 1 */ SUM(LENGTH(owner)) FROM t WHERE owner > 'S';
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR);
ALTER SESSION SET nls_comp = LINGUISTIC;
ALTER SESSION SET nls_sort = BINARY_CI;
SELECT /* test 2 */ SUM(LENGTH(owner)) FROM t WHERE owner > 'S';
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR);
-- ALTER SESSION SET "_cursor_plan_hash_version"=2;
--
-- SELECT /* test 3 */ SUM(LENGTH(owner)) FROM t WHERE owner > 'S';
-- SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR);
--
-- ALTER SESSION SET nls_comp = BINARY;
-- ALTER SESSION SET nls_sort = BINARY;
--
-- SELECT /* test 4 */ SUM(LENGTH(owner)) FROM t WHERE owner > 'S';
-- SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR);
SET ECHO OFF

View File

@@ -0,0 +1,28 @@
#!/bin/bash
# Name: oswextract.sh
# Purpose: Extract a specific metric from OS Watcher cellsrvstat archives
#
# Usage:
# ./oswetract.sh "cellsrv metric to grep for" osw_archive_files_of_interest*.dat.bz2
#
# Example:
# ./oswextract.sh "Number of latency threshold warnings for redo log writes" \
# cell01.example.com_cellsrvstat_11.05.25.*.dat.bz2
#
METRIC=$1
shift
bzcat -q $* |
egrep "Current Time|$METRIC" |
awk '
cell01.example.com_cellsrvstat_11.05.25.*.dat.bz2
BEGIN
{ printf("%-21s %20s %20s\n", "TIME", "CURRENT_VAL", "CUMULATIVE_VAL") }
/Current/
{ printf("%s %s %s %s", $3, $4, $5, $6, $7) }
/Number of latency threshold warnings for redo log writes/
{ printf("%20d %20d\n", $10, $11) }
'
# end of script

View File

@@ -0,0 +1,4 @@
#!/bin/bash
./cellash.sh | cellcli > cellash.txt

40
tpt/exadata/smx.sql Normal file
View File

@@ -0,0 +1,40 @@
-- 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.
set echo on
SELECT
ROUND(physical_read_bytes/1048576) phyrd_mb
, ROUND(io_interconnect_bytes/1048576) ret_mb
, (1-(io_interconnect_bytes / NULLIF(physical_read_bytes,0)))*100 "SAVING%"
FROM
v$sql
WHERE
sql_id = '9n2fg7abbcfyx'
AND child_number = 1;
SELECT
plan_line_id id
, LPAD(' ',plan_depth) || plan_operation
||' '||plan_options||' '
||plan_object_name operation
, ROUND(SUM(physical_read_bytes) /1048576) phyrd_mb
, ROUND(SUM(io_interconnect_bytes) /1048576) ret_mb
, AVG(1-(io_interconnect_bytes / NULLIF(physical_read_bytes,0)))*100 "SAVING%"
FROM
v$sql_plan_monitor
WHERE
sql_id = '&1'
AND sql_exec_id = &2
GROUP BY
plan_line_id
, LPAD(' ',plan_depth) || plan_operation
||' '||plan_options||' '
||plan_object_name
ORDER BY
plan_line_id
/
set echo off

14
tpt/exadata/topsql.sql Normal file
View File

@@ -0,0 +1,14 @@
-- 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.
SELECT * FROM (
SELECT
sql_id, executions, physical_read_bytes --, sql_text
FROM
v$sqlstats
WHERE io_cell_offload_eligible_bytes = 0
ORDER BY physical_read_bytes DESC
)
WHERE
ROWNUM <= 10
/

View File

@@ -0,0 +1,96 @@
-- 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.
DEF schemaname=SOE1000G
GRANT SELECT ON sys.v_$session TO &schemaname;
-- DROP TABLE &schemaname..workload_control;
-- DROP TRIGGER &schemaname..workload_control_trigger;
CREATE TABLE &schemaname..workload_control (
username VARCHAR2(100) DEFAULT ('*') NOT NULL
, service_name VARCHAR2(100) DEFAULT '*' NOT NULL
, module VARCHAR2(100) DEFAULT '*' NOT NULL
, action VARCHAR2(100) DEFAULT '*' NOT NULL
, program VARCHAR2(100) DEFAULT '*' NOT NULL
, client_machine VARCHAR2(100) DEFAULT '*' NOT NULL
, client_osuser VARCHAR2(100) DEFAULT '*' NOT NULL
, indexes_visible VARCHAR2(100) DEFAULT 'TRUE'
, force_serial_direct_read VARCHAR2(100) DEFAULT 'FALSE'
, CONSTRAINT pk_workload_control PRIMARY KEY (username, service_name, module, action, program, client_machine, client_osuser)
, CONSTRAINT ck1_workload_control CHECK (indexes_visible IN ('TRUE','FALSE'))
, CONSTRAINT ck2_workload_control CHECK (force_serial_direct_read IN ('TRUE', 'FALSE'))
);
INSERT INTO &schemaname..workload_control (username, indexes_visible) VALUES ('&schemaname', 'TRUE');
INSERT INTO &schemaname..workload_control (username, program, indexes_visible, force_serial_direct_read)
VALUES ('&schemaname', 'sqlplus@mac02.local (TNS V1-V3)', 'FALSE', 'TRUE');
COMMIT;
CREATE OR REPLACE TRIGGER &schemaname..workload_control_trigger
AFTER LOGON ON &schemaname..SCHEMA
DECLARE
c NUMBER;
BEGIN
-- set optimizer_use_invisible_indexes
FOR s IN (SELECT * FROM v$session WHERE sid = SYS_CONTEXT('userenv', 'sid'))
LOOP -- this loop returns only 1 row
SELECT COUNT(*) INTO c
FROM &schemaname..workload_control ctl
WHERE
(ctl.username = s.username OR ctl.username = '*')
AND (ctl.service_name = s.service_name OR ctl.service_name = '*')
AND (ctl.module = s.module OR ctl.module = '*')
AND (ctl.action = s.action OR ctl.action = '*')
AND (ctl.program = s.program OR ctl.program = '*')
AND (ctl.client_machine = s.machine OR ctl.client_machine = '*')
AND (ctl.client_osuser = s.osuser OR ctl.client_osuser = '*')
AND indexes_visible = 'FALSE';
IF c > 0 THEN
EXECUTE IMMEDIATE 'alter session set optimizer_use_invisible_indexes = false';
ELSE
EXECUTE IMMEDIATE 'alter session set optimizer_use_invisible_indexes = true';
END IF;
END LOOP;
-- set _serial_direct_read
FOR s IN (SELECT * FROM v$session WHERE sid = SYS_CONTEXT('userenv', 'sid'))
LOOP -- this loop returns only 1 row
SELECT COUNT(*) INTO c
FROM &schemaname..workload_control ctl
WHERE
(ctl.username = s.username OR ctl.username = '*')
AND (ctl.service_name = s.service_name OR ctl.service_name = '*')
AND (ctl.module = s.module OR ctl.module = '*')
AND (ctl.action = s.action OR ctl.action = '*')
AND (ctl.program = s.program OR ctl.program = '*')
AND (ctl.client_machine = s.machine OR ctl.client_machine = '*')
AND (ctl.client_osuser = s.osuser OR ctl.client_osuser = '*')
AND force_serial_direct_read = 'TRUE';
IF c > 0 THEN
EXECUTE IMMEDIATE 'alter session set "_serial_direct_read" = ALWAYS';
END IF;
END LOOP;
END;
/
SHOW ERR
-- set all indexes invisible in your hybrid-workload schema
ALTER SESSION SET ddl_lock_timeout = 10;
BEGIN
FOR i IN (SELECT index_name FROM user_indexes
WHERE table_name NOT IN 'WORKLOAD_CONTROL'
AND table_owner NOT IN ('SYS', 'SYSTEM')
AND table_owner = '&schemaname'
AND visibility = 'VISIBLE')
LOOP
EXECUTE IMMEDIATE 'ALTER INDEX '||i.index_name||' INVISIBLE';
END LOOP;
END;
/

View File

@@ -0,0 +1,73 @@
-- 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.
-- DROP TABLE test_users;
-- DROP TABLE test_objects;
CREATE TABLE test_users AS SELECT * FROM all_users;
CREATE TABLE test_objects AS SELECT * FROM all_objects;
CREATE INDEX i_test_users ON test_users (username);
CREATE INDEX i_test_objects ON test_objects (owner);
EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'TEST_USERS');
EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'TEST_OBJECTS');
PROMPT ==================================================================================
PROMPT This plan should use indexes as they are visible and available:
PROMPT ==================================================================================
SELECT
SUM(u.user_id) + SUM(o.object_id)
FROM
test_users u
, test_objects o
WHERE
u.username = o.owner
AND u.username LIKE 'S%'
AND o.owner LIKE 'S%'
/
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR);
PROMPT ==================================================================================
PROMPT Making indexes invisible. The plan should use FULL TABLE scans now:
PROMPT ==================================================================================
ALTER INDEX i_test_users INVISIBLE;
ALTER INDEX i_test_objects INVISIBLE;
ALTER SESSION SET optimizer_use_invisible_indexes = false;
SELECT
SUM(u.user_id) + SUM(o.object_id)
FROM
test_users u
, test_objects o
WHERE
u.username = o.owner
AND u.username LIKE 'S%'
AND o.owner LIKE 'S%'
/
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR);
PROMPT ==================================================================================
PROMPT Setting optimizer_use_invisible_indexes = TRUE. The plan should use indexes again:
PROMPT ==================================================================================
ALTER SESSION SET optimizer_use_invisible_indexes = true;
SELECT
SUM(u.user_id) + SUM(o.object_id)
FROM
test_users u
, test_objects o
WHERE
u.username = o.owner
AND u.username LIKE 'S%'
AND o.owner LIKE 'S%'
/
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR);