Friday, May 4, 2012

HOW TO: Take a storage cell offline for maintenance.

 

A few days ago, I had to take a storage cell offline so an engineer could replace a bad flash card. Following metaling article [1188080.1], here’s what I did.
  • By default, ASM drops a disk shortly after it is taken offline; however, you can set the DISK_REPAIR_TIME attribute to prevent this operation by specifying a time interval to repair the disk and bring it back online. The default DISK_REPAIR_TIME attribute value of 3.6h should be adequate for most environments.
    • To check repair times for all mounted disk groups – log into the ASM instance and perform the following query:
SQL> select dg.name,a.value from v$asm_diskgroup dg, v$asm_attribute a where dg.group_number=a.group_number and a.name='disk_repair_time';
NAME     |VALUE
---------|-------
DATA     |3.6h
DBFS     |3.6h
RECO     |3.6h
    •  If you need to offline the ASM disks for more than the default time of 3.6 hours then adjust the parameter by issuing the command below as an example:
SQL> ALTER DISKGROUP DATA SET ATTRIBUTE 'DISK_REPAIR_TIME'='8.5H';
  • Next I checked if ASM will be OK if the grid disks go OFFLINE. The following command should return ‘Yes’ for the grid disks being listed:
cellcli -e list griddisk attributes name,asmmodestatus,asmdeactivationoutcome
DATA_CD_00_cel03 ONLINE Yes
DATA_CD_01_cel03 ONLINE Yes
DATA_CD_02_cel03 ONLINE Yes
DATA_CD_03_cel03 ONLINE Yes
  • If one or more disks return asmdeactivationoutcome=’No’, I would need to wait for some time and repeat the previous step. Since all disks returned return asmdeactivationoutcome=’Yes’, I proceeded with taking the griddisk offline in the next step.
Note: Taking the storage server offline when one or more grid disks return asmdeactivationoutcome=’No’ will cause Oracle ASM to dismount the affected disk group, causing the databases to shut down abruptly.
  • The next step was to run cellcli command to Inactivate all grid disks on the cel03 – the cell I wanted to shut down.
CellCLI> ALTER GRIDDISK ALL INACTIVE
This action could have taken 10 minutes or longer depending on activity. Luckily for me, it didn’t. It’s is very important to make sure you were able to offline all the disks successfully before shutting down the cell services. Inactivating the grid disks will automatically OFFLINE the disks in the ASM instance.
  • Next was to confirm that the griddisks are now offline by performing the following actions:
    • I had to execute the command below and the output should show asmmodestatus=UNUSED or OFFLINE and asmdeactivationoutcome=Yes for all griddisks once the disks are offline in ASM. Only then is it safe to proceed with shutting down or restarting the cell:
# cellcli -e list griddisk attributes name,asmmodestatus,asmdeactivationoutcome
DATA_CD_00_cel03 OFFLINE Yes
DATA_CD_01_cel03 OFFLINE Yes
DATA_CD_02_cel03 OFFLINE Yes
DATA_CD_03_cel03 OFFLINE Yes
    • List the griddisk to confirm that all show offline:
CellCLI> LIST GRIDDISK
  • I could now reboot the cell. Oracle Exadata Storage Servers are powered off and rebooted using the Linux shutdown command.
    • The following command will shut down Oracle Exadata Storage Server immediately: (as root):
#shutdown -h -y now
(When powering off Oracle Exadata Storage Servers, all storage services are automatically stopped.)
    • If I had to reboot, I would have used this command:
# shutdown -r -y now
  • Once the cell comes back online – I had to reactive the grid disks:
cellcli -e alter griddisk all active
  • To verify that all disks are ‘active’, I used the following command:
CellCLI> list griddisk
  • Verify grid disk status:
DATA_CD_00_cel03 SYNCING
DATA_CD_01_cel03 ONLINE
DATA_CD_02_cel03 ONLINE
DATA_CD_03_cel03 SYNCING
Oracle ASM synchronization is only complete when all grid disks show asmmodestatus=ONLINE.
This operation uses Fast Mirror Resync operation – which does not trigger an ASM rebalance. The Resync operation restores only the extents that would have been written while the disk was offline.
  • Before taking another storage server offline, Oracle ASM synchronization must complete on the restarted Oracle Exadata Storage Server. If synchronization is not complete, then the check performed on another storage server will fail. The following is an example of the output:
CellCLI> list griddisk attributes name where asmdeactivationoutcome != 'Yes'
DATA_CD_00_cel02 "Cannot de-activate due to other offline disks in the diskgroup"
DATA_CD_01_cel02 "Cannot de-activate due to other offline disks in the diskgroup"
DATA_CD_02_cel02 "Cannot de-activate due to other offline disks in the diskgroup"
DATA_CD_03_cel02 "Cannot de-activate due to other offline disks in the diskgroup"

I could then go in ASM and check on rebalance operations:


SQL> select * from gv$asm_operation;

 

Saturday, March 19, 2011

oradebug gather all impotant information for troubleshooting

If a database is hung, then we cannot even login to sqlplus using "/ as sysdba", right?

Not entirely true, atleast for 10g and above.

We can login as follows and collect vital information for analyzing the reason for the hang before bouncing the db

The prelim option allows us to connect to the SGA but does not establish a session
and hence we can perform hanganalyze commands to dump information for further review
of hang conditions and reasons. This is a sessionless SQL Plus connection to the SGA.
Same thing can be done from EM as well by having a Direct SGA connection


$sqlplus -prelim
SQL>

At this point, it will not say anything like "Connected to Database"...etc.
Now you can perform oradebug hanganalyze commands

SQL> oradebug setmypid
SQL> oradebug hanganalyze 12


===>>>>>>>>>>>>>>>>>>>>>>>


- Get the sid from the pid or vice versa:

SELECT s.sid, p.spid
FROM v$session s, v$process p
WHERE s.paddr = p.addr
AND ... < p.spid = or perhaps
s.sid = >




If certain processes get PROCESSSTATE dump.
- Trace the process from the os level (see step 4).

Get processstate dumps. Do 3 times. This generates a trace file in
your user_dump_dest (from sqlplus: show parameter user_dump_dest).

$ sqlplus "/as sysdba"
oradebug setospid
oradebug unlimit
oradebug dump processstate 10



Get errorstacks from the process. Do 3 times. This generates a
trace file in your user_dump_dest (from sqlplus: show parameter user_dump_dest).

$ sqlplus "/as sysdba"
oradebug setospid
oradebug unlimit
oradebug dump errorstack 3




====>>>>>>>>




oradebug dump treedump

Dumps the structure of an index tree. The dump file contains one line for each block in the tree,
indented to show its level, together with a count of the number of index entries in the block.



Syntax Parameter:

oradebug dump treedump object_id


Example:

select object_id from sys.dba_objects
where owner = upper('&Owner') and
object_name = upper('&IndexName');


SQL> oradebug setmypid
Statement processed.

SQL> oradebug dump treedump 40
Statement processed.

Instead of oradebug dump treedump command you can also use,
alter session set events 'immediate trace name treedump level n';

That will give you a trace file with the one line for each block in the B*-tree and a row
count for each block.If there are large numbers of empty or nearly empty blocks, then the
index is a good candidate for being rebuilt.



=============>>>>>>>>>>>==========

oradebug for oracle Background process :


oradebug procstat
Dump process Statistics.


Syntax Parameter :
oradebug procstat OS PID


Example
Dump statistics for the DBWR background process:


select pid,name
from v$process p, v$bgprocess b
where b.paddr = p.addr
SQL> /
PID NAME
---------- -----
2 PMON
3 DBW0
4 LGWR
5 CKPT
6 SMON
7 RECO

6 rows selected.

SQL> oradebug setorapid 3

Unix process pid: 15668, image: oracle@apollo (DBW0)

SQL> oradebug procstat
Statement processed.

To find out where is the trace file located run:

SQL> oradebug tracefile_name
/ora-main/app/oracle/admin/test/bdump/test_dbw0_15668.trc

Rolling Patch - OPatch Support for RAC

PURPOSE
-------

Describe the current support of OPatch for Real Application Clusters.
Before reading OPatch RAC Support, you should be familiar with
single-instance OPatch processing.

For more information about Opatch, please refer to:
Note.189489.1 Oracle9i Data Server Interim Patch Installation (OPatch)


SCOPE & APPLICATION
-------------------

This document is intended for DBAs and System Administrators that
are going to apply Oracle Interim Patches on RAC environment.


Rolling Patch - OPatch Support for RAC
--------------------------------------

1 - RAC Patching methods

OPatch supports 3 different patch methods on a RAC environment:

. Patching RAC as a single instance (All-Node Patch)

In this mode, OPatch applies the patch to the local node first, then
propagates the patch to all other nodes, and finally updates the inventory.
All instances will be down during the whole patching process.

· Patching RAC using a minimum down-time strategy (Min. Downtime Patch)

In this mode, OPatch patches the local node, asks users for a sub-set of
nodes, which will be the first nodes to be patched. After the initial
subset of nodes are patched, Opatch propagates the patch to the other nodes
and finally updates the inventory. The downtime would happen between the
shutdown of the the second subset of nodes and the startp of the initial
subset of nodes patched.

· Patching RAC using a rolling strategy - No down time (Rolling Patch)

With this method, there is no downtime. Each node would be patched and
brought up while all the other nodes are up and running, resulting in
no disruption of the system.


2 - Flow diagrams

. All-Node Patch

. Shutdown all Oracle instances on all nodes
. Apply the patch to all nodes
. Bring all nodes up

. Minimum downtime

. Shutdown the Oracle instance on node 1
. Apply the patch to the Oracle instance on node 1
. Shutdown the Oracle instance on node 2
. Apply the patch to the Oracle instance on node 2
. Shutdown the Oracle instance on node 3
. At this point, instances on nodes 1 and 2 can be brought up
. Apply the patch to the Oracle instance on node 3
. Startup the Oracle instance on node 3

. Rolling patch (no downtime)

. Shutdown the Oracle instance on node 1
. Apply the patch to the Oracle instance on node 1
. Start the Oracle instance on node 1
. Shutdown the Oracle instance on node 2
. Apply the patch to the Oracle instance on node 2
. Start the Oracle instance on node 2
. Shutdown the Oracle instance on node 3
. Apply the patch to the Oracle instance on node 3
. Start the Oracle instance on node 3


3 - How does Opatch select which method to use?

To be eligible to be applied on as a rolling patch, the patch need to meet
certain criteria, which are determined by Oracle developers. To be applied
on a "rolling fashion", the patch must be designated as a "rolling
updatable patch" or simply "rolling patch".

The algorithm used to decide which method is going to be used is the
following:

If (users specify minimize_downtime)
patching mechanism = Min. Downtime
else if (patch is a rolling patch)
patching mechanism = Rolling
else
patching mechanism = All-Node


4 - Availability of rolling patches

As patches are released they will qualified and identified as a "rolling" or
"not rolling patch". While most patches can be applied in a rolling
fashion some patches can not be applied in this fashion.
Patches that could potentially be installed on rolling fashion include:

. Patches that do not affect the contents of the database.
. Patches not related to the RAC internode communication infrastructure.
. Patches that change procedural logic and do not modify common header
definitions of kernel modules. This includes client side patches that
only affect utilities like export, import, sql*plus, sql*loader, etc.

Only individual patches -- not patch sets -- will be “rollable”. It should
also be noted that a merge patch of a “rolling patch” and an ordinary patch
will not be a “rolling patch”.

From 9.2.0.4 on, all patches released will be marked as a "rolling" or
"not rolling patch", based on defined set of rules. Patches previously
released are packaged as "not rolling".

Because the set of rules currently defined are very conservative, patches
released as "not rolling patches", either before and after 9.2.0.4, may be
eligible to be re-released as "rolling patches", after analysis from
Oracle Development.

If you plan to apply a patch that is marked as "not rolling" and want to
check if is possible to take advantage of the rolling patch strategy,
please contact Oracle Support.



5 - How to determine if a patch is a "rolling patch" or not?

- 9i or 10gR1: (run)
$ opatch query -is_rolling

Opatch will ask the patch location and then will inform if the patch is or
not a "rolling patch"

- 10gR2: (run)
$ opatch query -all | grep rolling

For Windows, the following command can be used as grep is not suitable:
opatch query -all C:\stage\10.2.0.3_Mini_Patches\5731537 | findstr rolling
Patch is a rolling patch: false

6 - Current Limitations

. Patching with Shared File System

Currently OPatch treats Shared File System, like CFS, as a single-instance
patch. It means that OPatch will blindly patch files under a given
ORACLE_HOME knowing that other nodes will pick up the changes via the
Shared File System. Unfortunately, this means that OPatch cannot take
advantage of a rolling patch on a Shared File System environment;
all nodes must be down throughout the patching process.


. Patching one node at time

The Opatch strategies discussed above (All-Node, Min. Down-Time, and Rolling)
presumes that all nodes will be patched at the same time. Additionally,
each node can be patched individually, at different times, using the "-local"
key word, which will patch only the local node.

Wednesday, February 23, 2011

Script to Report Index Fragmentation

Execution Environment:
SQL, SQL*Plus

Access Privileges:
Requires SELECT on DBA_IND_COLUMNS, DBA_INDEXES and INDEX_STATS.

Usage:
sqlplus user/

Instructions:
Copy the script to a file and execute it from SQL*Plus.


PROOFREAD THIS SCRIPT BEFORE USING IT! Due to differences in the way text
editors, e-mail packages, and operating systems handle text formatting (spaces,
tabs, and carriage returns), this script may not be in an executable state
when you first receive it. Check over the script to ensure that errors of
this type are corrected.


Description

There are 3 scripts available to report various information on indexes.


Script 1: Index Fragmentation

TFSIFRAG.SQL provides information critical in determining whether an
index is a candidate for rebuilding. An index is a candidate for
rebuilding when a relatively high number of index leaf row deletes have
occured.

Please note: This report does not indicate the actual index "balance."


Script 2: Index Statistics

TFSISTAT.SQL prints a variety of statistics about the given index.
Statistics include B*tree height, the number of distinct and repeated
keys, the number of branch rows and blocks, the number of leaf rows
and blocks and information about space utilization.

Please note: You will receive an "ORA-01476: divisor is equal to
zero" for an index on a table into which no rows have been inserted.


Script 3: Index Keys for a Table

TFSINKEY.SQL prints uniqueness, name and column information of indexes for the
given table and owner. The arguments are not case-sensitive, but may not
include wildcards. The script will behave unreliably for an index not owned
by the owner of its base table.


References


Script

==========
Script #1:
==========

SET ECHO off
REM NAME: TFSIFRAG.SQL
REM USAGE:"@path/tfsifrag schema_name index_name"
REM ------------------------------------------------------------------------
REM REQUIREMENTS:
REM SELECT on INDEX_STATS
REM ------------------------------------------------------------------------
REM PURPOSE:
REM Reports index fragmentation statistics
REM ------------------------------------------------------------------------
REM EXAMPLE:
REM Index Fragmentation Statistic
REM
REM index name S_EMP_USERID_UK
REM leaf rows deleted 0
REM leaf rows in use 25
REM index badness 0.000
REM
REM ------------------------------------------------------------------------
REM Main text of script follows:
set verify off
def ownr = &&1
def name = &&2

ttitle -
center 'Index Fragmentation Statistic' skip 2

set heading off

col name newline
col lf_blk_rows newline
col del_lf_rows newline
col ibadness newline

validate index &ownr..&name;

select
'index name '||name,
'leaf rows deleted '||to_char(del_lf_rows,'999,999,990') del_lf_rows,
'leaf rows in use '||to_char(lf_rows-del_lf_rows,'999,999,990') lf_blk_rows,
'index badness '||to_char(del_lf_rows/(lf_rows+0.00001),'999,990.999') ibadness
from
index_stats
/

undef ownr
undef name
set verify on


==============
Sample Output:
==============

Index Fragmentation Statistic


index name S_EMP_USERID_UK
leaf rows deleted 0
leaf rows in use 25
index badness 0.000




==========
Script #2:
==========

SET ECHO off
REM NAME: TFSISTAT.SQL
REM USAGE:"@path/tfsistat schema_name index_name"
REM ------------------------------------------------------------------------
REM REQUIREMENTS:
REM SELECT on INDEX_STATS
REM ------------------------------------------------------------------------
REM PURPOSE:
REM Report index statistics.
REM ------------------------------------------------------------------------
REM EXAMPLE:
REM Index Statistics
REM
REM S_EMP_USERID_UK
REM ----------------------------------------------------------
REM height 1
REM blocks 5
REM del_lf_rows 0
REM del_lf_rows_len 0
REM distinct_keys 25
REM most_repeated_key 1
REM btree_space 1,876
REM used_space 447
REM pct_used 24
REM rows_per_key 1
REM blks_gets_per_access 2
REM lf_rows 25 br_rows 0
REM lf_blks 1 br_blks 0
REM lf_rows_len 447 br_rows_len 0
REM lf_blk_len 1,876 br_blk_len 0
REM
REM ------------------------------------------------------------------------
REM Main text of script follows:
set verify off
def ownr = &&1
def name = &&2

ttitle -
center 'Index Statistics' skip 2

set heading off

col name newline
col headsep newline
col height newline
col blocks newline
col lf_rows newline
col lf_blks newline
col lf_rows_len newline
col lf_blk_len newline
col br_rows newline
col br_blks newline
col br_rows_len newline
col br_blk_len newline
col del_lf_rows newline
col del_lf_rows_len newline
col distinct_keys newline
col most_repeated_key newline
col btree_space newline
col used_space newline
col pct_used newline
col rows_per_key newline
col blks_gets_per_access newline

validate index &ownr..&name;

select
name,
'----------------------------------------------------------' headsep,
'height '||to_char(height, '999,999,990') height,
'blocks '||to_char(blocks, '999,999,990') blocks,
'del_lf_rows '||to_char(del_lf_rows,'999,999,990') del_lf_rows,
'del_lf_rows_len '||to_char(del_lf_rows_len,'999,999,990') del_lf_rows_len,
'distinct_keys '||to_char(distinct_keys,'999,999,990') distinct_keys,
'most_repeated_key '||to_char(most_repeated_key,'999,999,990') most_repeated_key,
'btree_space '||to_char(btree_space,'999,999,990') btree_space,
'used_space '||to_char(used_space,'999,999,990') used_space,
'pct_used '||to_char(pct_used,'990') pct_used,
'rows_per_key '||to_char(rows_per_key,'999,999,990') rows_per_key,
'blks_gets_per_access '||to_char(blks_gets_per_access,'999,999,990') blks_gets_per_access,
'lf_rows '||to_char(lf_rows, '999,999,990')||' '||+
'br_rows '||to_char(br_rows, '999,999,990') br_rows,
'lf_blks '||to_char(lf_blks, '999,999,990')||' '||+
'br_blks '||to_char(br_blks, '999,999,990') br_blks,
'lf_rows_len '||to_char(lf_rows_len,'999,999,990')||' '||+
'br_rows_len '||to_char(br_rows_len,'999,999,990') br_rows_len,
'lf_blk_len '||to_char(lf_blk_len, '999,999,990')||' '||+
'br_blk_len '||to_char(br_blk_len, '999,999,990') br_blk_len
from
index_stats
/

undef ownr
undef name
set verify on


==============
Sample Output:
==============

Index Statistics
S_EMP_USERID_UK
----------------------------------------------------------
height 1
blocks 5
del_lf_rows 0
del_lf_rows_len 0
distinct_keys 25
most_repeated_key 1
btree_space 1,876
used_space 447
pct_used 24
rows_per_key 1
blks_gets_per_access 2
lf_rows 25
br_rows 0
lf_blks 1
br_blks 0
lf_rows_len 447
br_rows_len 0
lf_blk_len 1,876
br_blk_len 0




==========
Script #3:
==========

SET ECHO off
REM NAME: TFSIKEYS.SQL
REM USAGE:"@path/tfsikeys idx_owner table_name"
REM ------------------------------------------------------------------------
REM REQUIREMENTS:
REM SELECT on DBA_IND_COLUMNS and DBA_INDEXES
REM ------------------------------------------------------------------------
REM PURPOSE:
REM Shows the index keys for a particular table.
REM ------------------------------------------------------------------------
REM EXAMPLE:
REM Index Keys Summary
REM
REM Uniqueness Index Name Column Name
REM ---------- ---------------------------------------- ------------------
REM UNIQUE SCOTT.S_EMP_ID_PK ID
REM
REM UNIQUE SCOTT.S_EMP_USERID_UK USERID
REM
REM ------------------------------------------------------------------------
REM Main text of script follows:
set verify off
def ixowner = &&1
def tabname = &&2

ttitle -
center 'Index Keys Summary' skip 2

col uniq format a10 heading 'Uniqueness' justify c trunc
col indname format a40 heading 'Index Name' justify c trunc
col colname format a25 heading 'Column Name' justify c trunc

break -
on indname skip 1 -
on uniq

select
ind.uniqueness uniq,
ind.owner||'.'||col.index_name indname,
col.column_name colname
from
dba_ind_columns col,
dba_indexes ind
where
ind.owner = upper('&ixowner')
and
ind.table_name = upper('&tabname')
and
col.index_owner = ind.owner
and
col.index_name = ind.index_name
order by
col.index_name,
col.column_position
/

undef ixowner
undef tabname
set verify on


==============
Sample Output:
==============


Index Keys Summary


Uniqueness Index Name Column Name
---------- ---------------------------------------- ----------------------
UNIQUE SCOTT.S_EMP_ID_PK ID

UNIQUE SCOTT.S_EMP_USERID_UK USERID



Disclaimer :

EXCEPT WHERE EXPRESSLY PROVIDED OTHERWISE, THE INFORMATION, SOFTWARE,
PROVIDED ON AN "AS IS" AND "AS AVAILABLE" BASIS. ORACLE EXPRESSLY DISCLAIMS
ALL WARRANTIES OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NON-INFRINGEMENT. ORACLE MAKES NO WARRANTY THAT: (A) THE RESULTS
THAT MAY BE OBTAINED FROM THE USE OF THE SOFTWARE WILL BE ACCURATE OR
RELIABLE; OR (B) THE INFORMATION, OR OTHER MATERIAL OBTAINED WILL MEET YOUR
EXPECTATIONS. ANY CONTENT, MATERIALS, INFORMATION OR SOFTWARE DOWNLOADED OR
OTHERWISE OBTAINED IS DONE AT YOUR OWN DISCRETION AND RISK. ORACLE SHALL HAVE
NO RESPONSIBILITY FOR ANY DAMAGE TO YOUR COMPUTER SYSTEM OR LOSS OF DATA THAT
RESULTS FROM THE DOWNLOAD OF ANY CONTENT, MATERIALS, INFORMATION OR SOFTWARE.

ORACLE RESERVES THE RIGHT TO MAKE CHANGES OR UPDATES TO THE SOFTWARE AT ANY
TIME WITHOUT NOTICE.


Limitation of Liability :

IN NO EVENT SHALL ORACLE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL OR CONSEQUENTIAL DAMAGES, OR DAMAGES FOR LOSS OF PROFITS, REVENUE,
DATA OR USE, INCURRED BY YOU OR ANY THIRD PARTY, WHETHER IN AN ACTION IN
CONTRACT OR TORT, ARISING FROM YOUR ACCESS TO, OR USE OF, THE SOFTWARE.

SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OR EXCLUSION OF LIABILITY.
ACCORDINGLY, SOME OF THE ABOVE LIMITATIONS MAY NOT APPLY TO YOU.

Script to Report Table Fragmentation

Note : We have 3 script in sequence to capture the table fragmentation , each script having there own responsibility.

First script :The first script, TFSLDTFR.SQL, gathers table fragmentation
characteristics and inserts it into the newly created TFRAG table for
subsequent reporting.


Second Script : This script displays summary table fragmentation information.

Third Script : Detailed report of table fragmentation characteristics based on the
data in the tfrag table.



*********************First Script *****************************

The first script, TFSLDTFR.SQL, gathers table fragmentation characteristics
and inserts it into the newly created TFRAG table for subsequent reporting.

TFSLDTFR performs a single "analyze table 't' compute statistics" command.
You may want to change the compute to estimate for speed and usability.

Currently the following characteristics are gathered:

- Owner of table.
- Name of table
- Number of data blocks with rows
- Number of table extents
- Number of chained rows
- Number of blocks that have ever contained a row (high water mark)

Scripts two and three display table fragmentation information. The
information is queried from the TFRAG table which is created during
script one.




******************* Script *********************************


=============
First Script:
=============

SET ECHO off
REM NAME: TFSLDTFR.SQL
REM USAGE:"@path/tfsldtr table_owner table_name"
REM ------------------------------------------------------------------------
REM REQUIREMENTS:
REM ANALYZE on table, SELECT on DBA_TABLES, DBA_SEGMENTS, DBA_EXTENTS
REM ------------------------------------------------------------------------
REM AUTHOR:
REM Craig A. Shallahamer, Oracle US
REM ------------------------------------------------------------------------
REM PURPOSE:
REM Load the tfrag table with a given table's fragmentation stats.
REM ------------------------------------------------------------------------
REM EXAMPLE:
REM N/A
REM ------------------------------------------------------------------------
REM DISCLAIMER:
REM This script is provided for educational purposes only. It is NOT
REM supported by Oracle World Wide Technical Support.
REM The script has been tested and appears to work as intended.
REM You should always run new scripts on a test instance initially.
REM ------------------------------------------------------------------------
REM Main text of script follows:

set feedback on
set echo on
set verify off

def towner=&1
def tname=&2

rem *******************************************************************
rem * Goal: Analyze table to gather statistics
rem *******************************************************************
rem Specifically we are looking for:
rem - blocks ABOVE the hwm, i.e. empty blocks (dba_tables.blocks)
rem - average row length (dba_tables.blocks)

analyze table &towner..&tname compute statistics
/
col val1 new_value blks_w_rows noprint
col val2 new_value blks_above noprint
select blocks val1,
empty_blocks val2
from dba_tables
where owner = upper('&towner') and
table_name = upper('&tname')
/
rem *******************************************************************
rem * Goal: Get the number of blocks allocated to the segment
rem *******************************************************************
rem Specifically we are looking for:
rem - allocated blocks dba_segments.blocks

col val1 new_value alloc_blocks noprint
select blocks val1
from dba_segments
where owner = upper('&towner') and
segment_name = upper('&tname')
/

rem *******************************************************************
rem * Goal: Calculate the HWM
rem *******************************************************************
rem Specifically we are looking for:
rem HWM = dba_segments.blocks - dba_tables.empty_blocks - 1
rem HWM = allocated blocks - blocks above the hwn - 1
col val1 new_value hwm noprint
select &alloc_blocks-&blks_above-1 val1
from dual
/

rem *******************************************************************
rem * Goal: Get the Number of Fragmented Rows or Chained Frows (cr)
rem *******************************************************************
col val1 new_value cr noprint
select chain_cnt val1
from dba_tables
where owner = upper('&towner') and
table_name = upper('&tname')
/

rem ***********************************************************
rem * Goal : Determine the Segment Fragmentation (sf)
rem ***********************************************************
col val1 new_val sf noprint
select count(*) val1
from dba_extents
where owner = upper('&towner') and
segment_name = upper('&tname')
/
rem ***********************************************************
rem ***********************************************************
rem * Load the TFRAG table with the just gathered information.
rem ***********************************************************
rem ***********************************************************
rem *
rem * Create the tfrag table if it does not exist.
rem *
drop table tfrag;

create table tfrag
(
owner char(30),
name char(30),
hwm number,
blks_w_rows number,
avg_row_size number,
possible_bytes_per_block number,
no_frag_rows number,
no_extents number
)
/
create unique index tfrag_u1 on tfrag (owner,name)
/
rem *
rem * Delete and insert the new stats.
rem *
delete
from tfrag
where owner='&towner' and
name='&tname'
/
insert into tfrag values
('&towner','&tname',&hwm,&blks_w_rows,0,0,&cr,&sf)
/
commit;

set echo off
set verify on



*************************Second Script*********************************


SET ECHO off
REM NAME: TFSTFRAG.SQL
REM USAGE:"@path/tfstfrag"
REM ------------------------------------------------------------------------
REM REQUIREMENTS:
REM SELECT on TFRAG
REM ------------------------------------------------------------------------
REM AUTHOR:
REM Craig A. Shallahamer, Oracle USA
REM ------------------------------------------------------------------------
REM PURPOSE:
REM This script displays summary table fragmentation information. The
REM information is queried from the tfrag table which is loaded via the
REM ldtfrag script. Once the ldtfrag script has been run for a given
REM table, this report displays the following information:
REM
REM - Table owner
REM - Table name
REM - Segment fragmentation (number of extents)
REM - Number of table rows
REM - Table block fragmentation (1.0 bad, 0.0 good)
REM - Row fragmentation (chains)
REM ------------------------------------------------------------------------
REM EXAMPLE:
REM Table Fragmentation Characteristics
REM
REM Owner Table Name Exts Omega1 Chains
REM -------- ---------------------------------------- ---- ------ -------
REM scott s_emp 1 0.000 0
REM ------------------------------------------------------------------------
REM DISCLAIMER:
REM This script is provided for educational purposes only. It is NOT
REM supported by Oracle World Wide Technical Support.
REM The script has been tested and appears to work as intended.
REM You should always run new scripts on a test instance initially.
REM ------------------------------------------------------------------------
REM Main text of script follows:

col towner heading 'Owner' format a8 trunc
col tname heading 'Table Name' format a40 trunc
col exts heading 'Exts' format 999 trunc
col omega1 heading 'Omega1' format 0.999 trunc
col chains heading 'Chains' format 99,990 trunc

ttitle -
center 'Table Fragmentation Characteristics' skip 2

select owner towner,
name tname,
no_extents exts,
(hwm - blks_w_rows)/(hwm + 0.0001) omega1,
no_frag_rows chains
from tfrag
order by 1,2
/



===========================================
Sample Output from the tfstfrag.sql script:
===========================================


Table Fragmentation Characteristics


Owner Table Name Exts Omega1 Chains
-------- ---------------------------------------- ---- ------ -------
scott s_emp1 0.000 0



*******************Third Script ************************************

SET ECHO off
REM NAME: TFSDTFRG.SQL
REM USAGE:"@path/tfsdtfrg"
REM ------------------------------------------------------------------------
REM REQUIREMENTS:
REM SELECT on TFRAG table created by TFSLDTFR.SQL
REM ------------------------------------------------------------------------
REM AUTHOR:
REM Craig A. Shallahamer, Oracle US
REM ------------------------------------------------------------------------
REM PURPOSE:
REM Detailed report of table fragmentation characteristics based on the
REM data in the tfrag table.
REM ------------------------------------------------------------------------
REM EXAMPLE:
REM Detailed Table Fragmentation Characteristics
REM
REM
REM Table Owner : scott
REM Name : s_emp
REM Extents : 1
REM High water mark : 1
REM Blocks with rows : 1
REM Block frag: Omega1 : 0
REM Migrated rows : 0
REM
REM ------------------------------------------------------------------------
REM DISCLAIMER:
REM This script is provided for educational purposes only. It is NOT
REM supported by Oracle World Wide Technical Support.
REM The script has been tested and appears to work as intended.
REM You should always run new scripts on a test instance initially.
REM ------------------------------------------------------------------------
REM Main text of script follows:

col towner format a70
col tname format a70
col exts format 999
col omega1 format 90.9999
col chains format 99,990
col rpb format 999
col hwm format 9,999,999
col bwr format 9,999,999

ttitle -
center 'Detailed Table Fragmentation Characteristics' skip 2

set heading off

select 'Table Owner : '||owner towner,
' Name : '||name tname,
'Extents : '||no_extents exts,
'High water mark : '||hwm hwm,
'Blocks with rows : '||blks_w_rows bwr,
'Block frag: Omega1 : '||(hwm - blks_w_rows)/(hwm + 0.0001) omega1,
'Migrated rows : '||no_frag_rows chains
from tfrag
order by 1,2
/

set heading on


===========================================
Sample Output from the tfsdtfrg.sql script:
===========================================


Detailed Table Fragmentation Characteristics


Table Owner : scott
Name : s_emp
Extents : 1
High water mark : 1
Blocks with rows : 1
Block frag: Omega1 : 0
Migrated rows : 0

DBAs must be aware that unused indexes:

SCOPE :

DBAs must be aware that unused indexes:

* consume storage space

* degrade performance by unnecessary overheads during DML operations


How to Identify Unused Indexes in Order to Remove Them:
=======================================================
The examples below work if the user logged is the owner of the index.

1. Set the index under MONITORING:

SQL> alter index I_EMP monitoring usage;
Index altered.

SQL> select * from v$object_usage;

INDEX_NAME TABLE_NAME MON USED START_MONITORING END_MONITORING
--------------- --------------- --- ---- ------------------- -------------------
I_EMP EMP YES NO 03/14/2001 09:17:19


2. Check if the monitored indexes are used or not through the USED column in
V$OBJECT_USAGE view:

SQL> select sal from emp where ename='SMITH';

SAL
----------
800


Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'EMP'
2 1 INDEX (RANGE SCAN) OF 'I_EMP' (NON-UNIQUE)


The explain plan indicates the index is used.


SQL> select * from v$object_usage;

INDEX_NAME TABLE_NAME MON USED START_MONITORING END_MONITORING
--------------- --------------- --- ---- ------------------- -------------------
I_EMP EMP YES YES 03/14/2001 09:17:19


If the index was not used, the DBA could drop this unused index.


3. To stop monitoring an index, use the following SQL statement:

SQL> alter index i_emp nomonitoring usage;
Index altered.

SQL> select * from v$object_usage;

INDEX_NAME TABLE_NAME MON USED START_MONITORING END_MONITORING
--------------- --------------- --- ---- ------------------- -------------------
I_EMP EMP NO YES 03/14/2001 09:17:19 03/14/2001 09:55:24


As soon as you turn monitoring on again for the index, both columns
MONITORING and USED are reset.


SQL> alter index i_emp monitoring usage;
Index altered.

SQL> select * from v$object_usage;

INDEX_NAME TABLE_NAME MON USED START_MONITORING END_MONITORING
--------------- --------------- --- ---- ------------------- -------------------
I_EMP EMP YES NO 03/14/2001 09:57:27

Sunday, February 13, 2011

The Three Sets of Data Dictionary Views: USER_,ALL_,DBA_*

Oracle doesn’t allow you to access the internal data dictionary tables directly.
It creates views on the base dictionary tables and creates public synonyms for these views so users can access them.

There are three sets of data dictionary views—USER, ALL, and DBA—with each set of views pertaining to a similar item containing similar columns.


The views in each category are prefixed by the keywords USER, ALL, or DBA.


Each of these sets of views shows only the information the user is granted privileges
to access, as follows:

*** USER: The USER views show a user only those objects that the user owns. These views are useful to users, especially developers, for viewing the owner’s objects, grants, and so on.


*** ALL: The ALL views show you information about objects for which you have been granted privileges. The views with the prefix ALL include information on the user’s objects, and all other objects on which privileges have been granted, directly or through a role.


*** DBA: The DBA views are the most powerful in their range. Users who have been assigned the DBA role can access information about any object or any user in the database.

The DBAprefixed dictionary views are the ones you use to monitor and administer the database.