Friday, February 22, 2013

Retrieve Primary Key information


Note:  Proofread any scripts before using. Always try scripts on a test instance first. This Blog is not responsible for any damage.

Retrieve primary key information with the following SQL statement:

SELECT CONS.OWNER, COLS.TABLE_NAME, COLS.COLUMN_NAME, COLS.POSITION, CONS.STATUS
FROM ALL_CONSTRAINTS CONS, ALL_CONS_COLUMNS COLS
WHERE COLS.TABLE_NAME LIKE UPPER('%&TABLENAME%')
  AND CONS.CONSTRAINT_TYPE = 'P'
  AND CONS.CONSTRAINT_NAME = COLS.CONSTRAINT_NAME
  AND CONS.OWNER = COLS.OWNER
ORDER BY COLS.TABLE_NAME, COLS.POSITION;

Let's quickly explain the output from this query.

1. OWNER indicates the schema that owns the table.
2. TABLE_NAME is the name of the table (stored in uppercase).
3. COLUMN_NAME is the name of the column that is a part of the primary key. (also stored in uppercase)
4. POSITION is the position in the primary key. A primary key can contain more than one column, so understanding the order of the columns in the primary key is

Very important.
5. STATUS indicates whether the primary key is currently enabled or disabled.

Tuesday, February 19, 2013

Tablespace Usage Script

Note:  Proofread any scripts before using. Always try scripts on a test instance first. This Blog is not responsible for any damage.

--
-- TABLESPACE INFORMATION
--

SET LINESIZE 500 PAGESIZE 26 FEEDBACK OFF HEADING ON TIMING OFF ECHO OFF
SET UNDERLINE =

VARIABLE XXX CHAR(200)

COLUMN "TABLESPACE" FORMAT A16
COLUMN "INITIAL EXTENT(MB)" FORMAT 999,999
COLUMN "STATUS" FORMAT A7
COLUMN "NEXT EXTENT(MB)" FORMAT 999,999
COLUMN "MAX EXTENTS" FORMAT 99,999,999,999
COLUMN "PCT_INCREASE" FORMAT 999
COLUMN "USED SIZE(MB)" FORMAT 9,999,999,999
COLUMN "USED BLOCKS" FORMAT 999,999,999
COLUMN "USED USAGE" FORMAT A10
COLUMN "FREE SIZE(MB)" FORMAT 9,999,999,999
COLUMN "FREE BLOCKS" FORMAT 999,999,999
COLUMN "FREE USAGE" FORMAT A10
COLUMN "TOTAL SIZE(MB)" FORMAT 99,999,999,999
COLUMN "TOTAL BLOCKS" FORMAT 9999,999,999

BREAK ON "TABLESPACE"

DECLARE
CURSOR C1 IS
   SELECT 'PRINT DATE:'||TO_CHAR(SYSDATE,'YYYY/MM/DD HH24:MI:SS')||' ***** TABLESPACE INFORMATION FROM DATABASE :'||NAME||' INSTANCE:'||INSTANCE||' *****' XXX
   FROM V$DATABASE,V$THREAD
   WHERE ROWNUM=1;

BEGIN
OPEN C1;
FETCH C1 INTO :XXX;
CLOSE C1;
END;
/

SET PAGESIZE 1
PRINT XXX
SET PAGESIZE 24

TTITLE RIGHT FORMAT 999 'PAGE:' SQL.PNO

BTITLE CENTER '================================================================================================================================================'

SELECT SUBSTR(A.TABLESPACE_NAME,1,16) "TABLESPACE",
       MAX(A.CONTENTS) "TYPE",
       MAX(A.STATUS) "STATUS",
       MAX(A.INITIAL_EXTENT)/1024 "INITIAL EXTENT(KB)",
       MAX(A.NEXT_EXTENT)/1024 "NEXT EXTENT(KB)",
       MAX(A.MAX_EXTENTS) "MAX EXTENTS",
       MAX(A.PCT_INCREASE) "PCT_INCREASE",
       (SUM(B.BYTES)*COUNT(DISTINCT B.FILE_ID)/COUNT(B.FILE_ID)/1024/1024)-(ROUND(SUM(C.BYTES)/1024/1024/COUNT(DISTINCT B.FILE_ID))) "USED SIZE(MB)",
       (SUM(B.BLOCKS)*COUNT(DISTINCT B.FILE_ID)/COUNT(B.FILE_ID))-(SUM(C.BLOCKS)/COUNT(DISTINCT B.FILE_ID)) "USED BLOCKS",
       TO_CHAR(100-(SUM(C.BLOCKS)*100*COUNT(B.FILE_ID)/(SUM(B.BLOCKS)*COUNT(DISTINCT B.FILE_ID)))/COUNT(DISTINCT B.FILE_ID),'999.99')||'%' "USED USAGE",
       ROUND(SUM(C.BYTES)/1024/1024/COUNT(DISTINCT B.FILE_ID)) "FREE SIZE(MB)",
       SUM(C.BLOCKS)/COUNT(DISTINCT B.FILE_ID) "FREE BLOCKS",
       TO_CHAR((SUM(C.BLOCKS)*100*COUNT(B.FILE_ID)/(SUM(B.BLOCKS)*COUNT(DISTINCT B.FILE_ID)))/COUNT(DISTINCT B.FILE_ID),'999.99')||'%' "FREE USAGE",
       SUM(B.BYTES)*COUNT(DISTINCT B.FILE_ID)/COUNT(B.FILE_ID)/1024/1024 "TOTAL SIZE(MB)",
       SUM(B.BLOCKS)*COUNT(DISTINCT B.FILE_ID)/COUNT(B.FILE_ID) "TOTAL BLOCKS"
FROM DBA_TABLESPACES A,
     DBA_DATA_FILES B,
     DBA_FREE_SPACE C
WHERE A.TABLESPACE_NAME=B.TABLESPACE_NAME
  AND A.TABLESPACE_NAME=C.TABLESPACE_NAME
GROUP BY A.TABLESPACE_NAME
ORDER BY 1;

TTITLE OFF
BTITLE OFF
SET FEEDBACK ON

How to change AWR snapshot settings

Note:  Proofread any scripts before using. Always try scripts on a test instance first. This Blog is not responsible for any damage.

 

Changing AWR snapshot settings like retention, interval, topnsql

Using dbms_workload_repository.modify_snapshot_settings one can modify retention, interval and topnsql.

-– Get the dbid:

SQL> select dbid from v$database;

DBID
--------------
3970683413

– retention=>value in minutes so (20 days * 24 (hours per day) * 60 minutes per hour = 28800), max value can be set by passing a value of 0 which means forever
– interval=>30min (snap at this interval), a value of 0 will turn off AWR
– topnsql – top N sql size, specify value of NULL will keep the current setting

SQL> exec dbms_workload_repository.modify_snapshot_settings(retention=>28800, interval=>30, topnsql=>100, dbid=>3970683413);
PL/SQL procedure successfully completed.

–- shows retention and interval after it was modified
SQL> select extract( day from snap_interval) *24*60+extract( hour from snap_interval) *60+extract( minute from snap_interval ) snapshot_interval,
extract( day from retention) *24*60+extract( hour from retention) *60+extract( minute from retention ) retention_interval,
topnsql
from dba_hist_wr_control;

SNAPSHOT_INTERVAL RETENTION_INTERVAL TOPNSQL
----------------- ------------------ ----------
               30              28800 100

-- Change snapshot interval to 15 minutes
SQL> EXEC dbms_workload_repository.modify_snapshot_settings(interval=>15);
PL/SQL procedure successfully completed.

Oracle has published suggested storage requirements for AWR based on the activity and complexity of your 10g database:
Active Sessions number of
CPU's (num_cpus)
number of
schema objects
Monthly
space required (gig)
Small 10 2 500 2
Medium 20 8 5,000 8
Large 100 32 50,000 20

Oracle uses a scheduled job, GATHER_STATS_JOB, to collect AWR statistics. This job is created, and enabled automatically, when you create a new Oracle database.  

To see this job, use the DBA_SCHEDULER_JOBS view as seen in this example:
SELECT a.job_name, a.enabled, c.window_name, c.schedule_name, c.start_date, c.repeat_interval
FROM dba_scheduler_jobs a, dba_scheduler_wingroup_members b, dba_scheduler_windows c
WHERE job_name='GATHER_STATS_JOB'
      And a.schedule_name=b.window_group_name
      And b.window_name=c.window_name;
You can disable this job using the dbms_scheduler.disable procedure as seen in this example:
Exec dbms_scheduler.disable('GATHER_STATS_JOB');
And you can enable the job using the dbms_scheduler.enable procedure as seen in this example:
Exec dbms_scheduler.enable('GATHER_STATS_JOB');

Useful Queries

Standard reports
The SQL*Plus scripts are located in $ORACLE_HOME/rdbms/admin directory, the output in either text or HTML (default) format

ASH report (ashrpt.sql)

Helps answer questions about "What's going on right now and who is doing it?" for a specified time period

AWR report (awrrpt.sql)

Breakdown of what was consuming “DB Time” for a specified time period

AWR "diff" report (awrddrpt.sql)

Compares and highlights what changed between two specified time periods.

Prompts for:
    - Html or text type
    - First pair of Begin and End snapshot ids
    - Report name
    - Provides a report name beginning with awrdiff…

AWR "SQL" report (awrsqrpt.sql)
Displays all recorded information about a specific SQL during a specified time period. Good when you want to focus on a particular SQL statement.

To get a quick report of any SQL statement's execution plans within the past 7 days, if you have the statement's SQL ID value:
select * from table(dbms_xplan.display_awr('sqlid'));

If you don't have the SQL statement's SQL ID, it can be found in:
- A standard AWR report or EM DB Console or Grid Control  or
- Query the V$SQL or DBA_HIST_SQLTEXT view:

select sql_id, sql_text from v$sql where lower(sql_text) like '%phrase%';
select sql_id, sql_text from dba_hist_sqltext where lower(sql_text) like '%phrase%';
 

Friday, February 15, 2013

Basic SQL


DDL


Data Definition Language (DDL) statements are used to define the database structure or schema. Some examples:
  • CREATE - to create objects in the database
  • ALTER - alters the structure of the database
  • DROP - delete objects from the database
  • TRUNCATE - remove all records from a table, including all spaces allocated for the records are removed
  • COMMENT - add comments to the data dictionary
  • RENAME - rename an object

DML


Data Manipulation Language (DML) statements are used for managing data within schema objects. Some examples:
  • SELECT - retrieve data from the a database
  • INSERT - insert data into a table
  • UPDATE - updates existing data within a table
  • DELETE - deletes all records from a table, the space for the records remain
  • MERGE - UPSERT operation (insert or update)
  • CALL - call a PL/SQL or Java subprogram
  • EXPLAIN PLAN - explain access path to data
  • LOCK TABLE - control concurrency

DCL


Data Control Language (DCL) statements. Some examples:
  • GRANT - gives user's access privileges to database
  • REVOKE - withdraw access privileges given with the GRANT command

TCL


Transaction Control (TCL) statements are used to manage the changes made by DML statements. It allows statements to be grouped together into logical transactions.
  • COMMIT - save work done
  • SAVEPOINT - identify a point in a transaction to which you can later roll back
  • ROLLBACK - restore database to original since the last COMMIT
  • SET TRANSACTION - Change transaction options like isolation level and what rollback segment to use

Wednesday, February 13, 2013

Dealing with Database Block corruption

Database Corruption:

Note:  Proofread any scripts before using. Always try scripts on a test instance first. This Blog is not responsible for any damage.


There are two instance parameters that will assist in detecting corrupted blocks
  • DB_BLOCK_CHECKSUM (default true) - This helps to detect damage introduced by the disk or I/O system. The system uses a check sum in the header of the block to detect corruption, this has minimal impact on performance. The system tablespace is always set to true regardless of this parameter, others are only set when you enable them. Oracle checks the disk not the memory.
  • DB_BLOCK_CHECKING (default off - off, low, medium, full, true and false) - Help to detect damage introduced by faulty memory. Setting this option will impact performance, the processes will check for corruption every time the buffer containing the block is accessed, this could take up to 10% cpu performance.
Both db_block_checksum (set to true) and db_block_checking (set to low) for the system tablespace.

db_block_checksum alter system set db_block_checksum = typical;
alter system set db_block_checksum = full;
Notes: additional overhead will be occurred
typical - 1-2% increase
full - 4-5% increase
db_block_checking alter system set db_block_checking = off;
alter system set db_block_checking = low;
alter system set db_block_checking = medium;
alter system set db_block_checking = full;
alter system set db_block_checking = false;    /* same as off */
alter system set db_block_checking = true;     /* same as full */

Note: additional overhead will be occurred
low - 1-3% increase
medium - 3-6% increase
full - 6-10% increase

Normally you are informed by a corrupted block from a user trying to use the block, an alert will be sent to the alert log. An ORA-01578 indicated a corrupted block and trace files will be created, use the DBA_EXTENTS table to match up the corrupted block to an object:

Example select owner, segment_name, segment_type from dba_extents where file_id=7 and 5 between block_id and block_id + blocks-1;

select segment_name, file_id, block_id from dba_extents where owner = 'TEST01';

If a table has corrupted blocks but the primary key index does not, index searches may succeed depending on what columns/rows are selected, as long as the index that has the information to complete the query and not does not read the corrupted blocks.

DBverify:

dbverify is a oracle binary that can detect corrupted blocks in a datafile, it is used when running user managed backups, rman performs its own verification. dbverify checks all blocks including the blocks above the high watermark. dbverify can check offline/online datafiles and data file image copies but nothing else. dbverify is used at the operating system level it checks the structural integrity of the datafiles.

help page $dbv help=y
test datafile $dbv file=test01.dbf
Note: you are looking for failing pages (blocks), an influx block is one that DBWn was writing while dbverify was trying to verify it, this is not an error and dbverify will try again until it gets consistent read.
test datafile with specific blocksize $dbv blocksize=8192 file=test01.dbf logfile=/tmp/dbv_13022013.log

you can also use the analyze command to check for table or index corruption, however the analyze command will only check for corruption below the high watermark, so will not check unused space, it does not identify the corrupt block but gives a ORA-01498 error.

table only analyze table <table_name> validate structure;
index only analyze index <table_name> validate structure;
table and associated indexes analyze table <table_name> validate structure cascade;

dbms_repair:

Is a set of procedures that will check objects for problems and make the object useable, note that it cannot repair the data (you are required to recover it). You must create a table that dbms_repair uses to store its output.
There are 4 procedures that will be used
  • dbms_repair.admin_tables - used to store the block address
  • dbms_repair.check_object - checks all the blocks
  • dbms_repair.fix_corrupt_object - marks the corrupted blocks (does not fix it)
  • dbms_repair.skip_corrupted_blocks - instructs oracle to ignore marked corrupted blocks
create the admin table exec dbms_repair.admin_tables ( table_name => 'REPAIR_TABLE', table_type => dbms_repair.repair_table, action => dbms_repair.create_action, tablespace => 'TEST');
select owner, object_name, object_type from dba_objects where object_name like ‘%REPAIR_TABLE’;
Note: The table REPAIR_CORRUPT_TAB will store details of any problems encountered when checking a table (must have prefix REPAIR_).
check the object declare
num_corrupt int;
begin
  num_corrupt := 0;
  exec dbms_repair.check_object(schema_name =>'TEST03',object_name      =>'TEST03',repair_table_name =>'REPAIR_TABLE',corrupt_count => num_corrupt);
end;
/
select object_name, block_id, corrupt_type, marked_corrupt, corrupt_description, repair_description from repair_table;
Note: If no rows exist in the REPAIR_TABLE then the table is ok. Referential integrity constraints on related tables can be broken, indexes can become out of sync with the table data and triggers on a table can cause logical corruption when using the DBMS_REPAIR package.
mark the block as corrupt declare fix_block_count int;
begin
  fix_block_count := 0;
  dbms_repair.fix_corrupt_blocks(schema_name =>'TEST03',object_name =>'TEST03',      object_type => dbms_repair.table_ojbects, repair_table_name => ‘REPAIR_TABLE’,      fix_count => fix_block_count);
select object_name, block_id, marked_corrupt from repair_table;
skip the corrupted blocks exec dbms_repair.skip_corrupt_blocks(schema_name =>'TEST03',object_name =>'TEST03', object_type => dbms_repair.table_ojbects, flags => dbm_repair.noskip_flag);

Recover corrupted block with RMAN
If you are using user-managed backups then restore the file in the normal way
  • take damaged file offline
  • restore file from the backup made before the corruption
  • recover the file completely
  • bring recovered file online
RMAN can be set that it can either abort a backup when corruption is detected or specify a tolerance recording any corruption with the repository. By default RMAN only checks for physical corruptions (disk problem) not logical (software corruption disk is ok but oracle does not understand the block).
BMR (block media recovery) can only be performed by RMAN and recovery either completes or fails (no incomplete recovery). It can only recover datafiles as it uses the redo log to recover. If the MAXCORRUPT setting has been set then RMAN backup will continue until this threshold, otherwise it will fail. If recovering a table while the database is up, indexes searches may succeed depending on what columns/rows are selected, if a user hits a block that is being recovered it will report an ORA-01578 error.

set corruption threshold rman> run {
   set maxcorrupt for datafile 7 to 100;
   backup datafile 7;
}
turn off block checking rman> backup nochecksum datafile 7;
check for logical corruption rman> backup check logical datafile 7;
display corruption select * from v$database_block_corruption;
display corruption in backup set select * from v$backup_corruption;
display corruption in image copy select * from v$copy_corruption;

To recover a corrupted block using RMAN:

recover one block rman> blockrecover datafile 7 block 5;
recover two datafiles and a number of blocks rman> blockrecover datafile 7 block 5,6,7 datafile 9 block 21,25;
use a specified backup rman> blockrecover datafile 7 block 5 from backupset 1093;
rman> blockrecover datafile 7 block 5 from tag monthly_whole_backup;
recover blocks using backups made a week ago rman> blockrecover corruption list until time sysdate – 7;

You can follow these steps as well:

1) Restore a backup from before this corruption occurs and recover.

STEPS TO BE Followed:

Step a. shutdown the database
Step b. restore the datafile
Step c. startup mount
Step d. recover database
        auto
Step e. alter database open
Step f. analyze table sys.source$ validate structure cascade;

2) If 1 is not an option (but 1 is the best solution) then we can try this option.

a. select obj#, rowid from sys.source$;

— When this stops/fails the last line should give you the obj# of the object affected by the corruption.

b. select OWNER#, NAME, TYPE#, STATUS from sys.obj$ where OBJ# =

— This should give you the name of the package/procedure hit be the corruption.

c. exec DBMS_REPAIR.SKIP_CORRUPT_BLOCKS('SYS','source$');

— This will skip the corrupt block, and might allow you to re-create the object hit by the corruption.

IF you are not allowed to re-create the object – then after DBMS_REPAIR.
SKIP_CORRUPT_BLOCKS you should be able to perform an full Export of the database excluding the procedure/package hit by the corruption.

d. Use the Export to re-create the database and afterwards manually re-create the object that was skipped by the Export.

BUT, this is only a last option if 1 (restore/recover) really isn't an option, and it is with no guarantee for success.
The only way to guarantee that you will not run into further problems with this block is to recreate your database or go to a backup where the problem does not exist.

Dump a block of data:

find the block data select header_file, header_block from dba_segments where segment_name = 'TEST03';
dump the block data alter system dump datafile 6 block 75;
Note: the information will be in a trace file in the user dump directory (udump)
Using dumped info comfirm its the right object select name from sys.obj$ where obj#='52716';
Note: object number objected from dumped information in trace file

Dump the tree of an index:

object object ID select object_id from user_objects where object_type = 'INDEX' & object_name = 'TEMP_INDEX';
dump the tree alter session set events 'immediate trace name treedump level <object_id>';
Note: object ID would have been obtained above, the information again is dumped into the user dump area in a trace file 

EXTENTS Details

Note:  Proofread any scripts before using. Always try scripts on a test instance first. This Blog is not responsible for any damage.
An extent is a contiguous set (side-by-side) of Oracle data blocks allocated to a segment within a tablespace.
The size of an extent is controlled by storage parameters used when you CREATE or ALTER the segment (INITIAL, NEXT and PCT_INCREASE) and tablespace parameters.

Extents are often blamed for performance problems; however, their impact on performance is minimal and can be completely avoided. In fact, careful use of extents can improve your response time by distributing your I/O operations across multiple devices. To understand the impact of extents on performance, you need to consider the two different methods of reading data from a table: by RowID and by full table scan.

Oracle's preferred method of reading records for OLTP applications is by the row's RowID value.
For example, an index range scan may generate a list of RowIDs that match a query's limiting condition.

Impact of Extent Sizes on Full Table Scans:

1. If the extents are properly sized, the number of extents has no impact on the number of reads required by table scans.
2. If the extents are not properly sized, the number and size of the extents can greatly increase the amount of work performed by the database during a full table scan.
Proper sizing of extents is a key factor in managing the performance of full table scans. To eliminate the potential impact of multiple extents on performance, you need to make sure that the size of each extent is a multiple of the number of blocks read during each multiblock read.
In many systems, 64KB or 128KB is read during each read. Therefore, size your extents.

-- Identify Indexes/Tables near to MAX EXTENTS

Step 1. Connect as System user to list the tables/indexes reaching to max extent

SELECT DS.OWNER, DS.SEGMENT_NAME, DS.SEGMENT_TYPE, DS.MAX_EXTENTS, DS.EXTENTS AS EXTENTS_FILLED
FROM DBA_SEGMENTS DS
WHERE DS.SEGMENT_TYPE IN ('TABLE','INDEX')
  AND DS.OWNER NOT IN ('SYS','SYSTEM')
  AND ( DS.MAX_EXTENTS - DS.EXTENTS ) < 50
ORDER BY 1,3

Step 2. What to do if a table reaches its MAXEXTENTS

If its EXTENTS parameter is nearing to the current MAX EXTENTS value you can increase it with the ALTER TABLE command,
For example:

ALTER TABLE <OWNER.TABLE_NAME> STORAGE (MAXEXTENTS UNLIMITED);
ALTER INDEX <OWNER.INDEX_NAME> STORAGE (MAXEXTENTS UNLIMITED);

-- Finding out table name to ALTER LOBS max extents
SELECT OWNER, TABLE_NAME, COLUMN_NAME FROM DBA_LOBS WHERE SEGMENT_NAME = '&SEGMENT_NAME';

-- Modifying LOB Segments (EXAMPLES)
ALTER TABLE <OWNER.TABLE_NAME> MODIFY LOB (<LOBCOLUMN>) (STORAGE (MAXEXTENTS UNLIMITED));

-- Allocating a new extent (EXAMPLES)
ALTER INDEX <OWNER.INDEX_NAME> ALLOCATE EXTENT;
ALTER TABLE <OWNER.TABLE_NAME> ALLOCATE EXTENT;

-- To alter tablespace max extent clause one can use:

-- To resolve the Max extents issue for tablespace one can either "1) Add a data file 2) or, resize current data file 3) or, change the storage / extent configuration".
 ALTER TABLESPACE <tablespace_name> DEFAULT STORAGE (MAXEXTENTS n);
(OR)
ALTER TABLESPACE <tablespace_name> DEFAULT STORAGE (MAXEXTENTS UNLIMITED);

-- Identify all objects in the instance that do NOT have max extents set to “UNLIMITED”
-- Applicable to all database versions:

SET LINES 120

COL SEGMENT_NAME FORMAT A30
COL OWNER FORMAT A20
COL SEGMENT_TYPE FORMAT A20

SELECT S.SEGMENT_NAME, S.OWNER, S.SEGMENT_TYPE, S.MAX_EXTENTS
FROM DBA_SEGMENTS S , DBA_TABLESPACES T
WHERE S.TABLESPACE_NAME=T.TABLESPACE_NAME AND
      T.EXTENT_MANAGEMENT <> 'LOCAL' AND
      S.SEGMENT_TYPE NOT IN ('CACHE','DEFERRED ROLLBACK','SPACE HEADER') AND
      S.OWNER NOT IN ('SYS','SYSTEM') AND
      S.MAX_EXTENTS <> 2147483645
ORDER BY S.OWNER,S.SEGMENT_TYPE
/

-- Script to generate  "alter table" and "alter index" statements to set max extents to unlimited

SET LINES 120
SET HEADING OFF

SPOOL MAXEXTENT_FIX.SQL

SELECT
'ALTER '||S.SEGMENT_TYPE||' '||S.OWNER||'.'||S.SEGMENT_NAME||' STORAGE (MAXEXTENTS UNLIMITED);' "ALTER STATEMENT"
FROM DBA_SEGMENTS S , DBA_TABLESPACES T
WHERE S.TABLESPACE_NAME=T.TABLESPACE_NAME AND
      T.EXTENT_MANAGEMENT<>'LOCAL' AND
      S.SEGMENT_TYPE IN ('TABLE','INDEX') AND
      S.OWNER NOT IN ('SYS') AND
      S.MAX_EXTENTS<>2147483645
ORDER BY S.OWNER,S.SEGMENT_TYPE
/

SPOOL OFF

--
-- List tables with less than 10 extents.
--

SET PAGESIZE 60
SET LINESIZE 300

SELECT T.TABLE_NAME,
       COUNT(E.SEGMENT_NAME) EXTENTS,
       T.MAX_EXTENTS,
       T.NUM_ROWS "ROWS",
       TRUNC(T.INITIAL_EXTENT/1024) "INITIAL K",
       TRUNC(T.NEXT_EXTENT/1024) "NEXT K"
FROM   ALL_TABLES T,
       DBA_EXTENTS E
WHERE  E.SEGMENT_NAME = T.TABLE_NAME
AND    E.OWNER        = T.OWNER
AND    T.OWNER        = UPPER('&OWNER')
GROUP BY T.TABLE_NAME,
         T.MAX_EXTENTS,
         T.NUM_ROWS,
         T.INITIAL_EXTENT,
         T.NEXT_EXTENT
HAVING COUNT(E.SEGMENT_NAME) < 10
ORDER BY COUNT(E.SEGMENT_NAME) DESC
/

--
-- List the Number of Extents for all Indexes for a Given Table.  (All Tables if 'ALL' is entered for Table_name).
--

SET PAGESIZE 60
SET LINESIZE 300
SET VERIFY OFF

SELECT I.INDEX_NAME,
       COUNT(E.SEGMENT_NAME) EXTENTS,
       I.MAX_EXTENTS,
       T.NUM_ROWS "ROWS",
       TRUNC(I.INITIAL_EXTENT/1024) "INITIAL K",
       TRUNC(I.NEXT_EXTENT/1024) "NEXT K",
       T.TABLE_NAME
FROM   ALL_TABLES T,
       ALL_INDEXES I,
       DBA_EXTENTS E
WHERE  I.TABLE_NAME   = T.TABLE_NAME
AND    I.OWNER        = T.OWNER
AND    E.SEGMENT_NAME = I.INDEX_NAME
AND    E.OWNER        = I.OWNER
AND    I.TABLE_NAME   = DECODE(UPPER('&&TABLE_NAME'),'ALL',I.TABLE_NAME,UPPER('&&TABLE_NAME'))
AND    I.OWNER        = UPPER('&&OWNER')
GROUP BY T.TABLE_NAME,
         I.INDEX_NAME,
         I.MAX_EXTENTS,
         T.NUM_ROWS,
         I.INITIAL_EXTENT,
         I.NEXT_EXTENT
HAVING   COUNT(E.SEGMENT_NAME) > 5
ORDER BY COUNT(E.SEGMENT_NAME) DESC
/

Friday, February 8, 2013

Current running sessions


Note:  Proofread any scripts before using. Always try scripts on a test instance first. This Blog is not responsible for any damage.

Every connection to the Oracle database engine is a Session. Every login requires a session. Even internal database processes (jobs) are part of the Oracle session list.

There are many types of processes in Oracle -- background processes like SMON, PMON, RECO, ARCH, CKPT, DBWR, etc..  And user processes like dedicated servers or shared server

A session is a specific connection of a user to an Oracle instance through a user process. For example, when a user starts SQL*Plus, the user must provide a valid user name and password, and then a session is established for that user. A session lasts from the time the user connects until the time the user disconnects or exits the database application.

/* TO IDENTIFY MINIMUM AND MAXIMUM PROCESSES AND SESSIONS CONNECTED COUNT FROM DATABASE STARTUP */
SET LINESIZE 132
SELECT * FROM V$RESOURCE_LIMIT WHERE RESOURCE_NAME IN ('processes','sessions');

One more thing: You normally do *not* set the sessions parameter within the init.ora file. Just the processes parameter. Sessions is auto-set and calculated as a multiplier of processes. (Default value - Derived: (1.1 * PROCESSES) + 5)

Also there are times when it is useful to be able to locate and kill Oracle sessions that are locking database resources.

/* THE FOLLOWING SQL WILL PRINT AN OVERVIEW OF SESSIONS CURRENTLY ACTIVE */
SELECT
   RPAD(D.NAME||':',11)||RPAD(' CURRENT LOGONS='||
   (TO_NUMBER(L.SESSIONS_CURRENT)),20)||'CUMULATIVE LOGONS='||
   RPAD(SUBSTR(SS.VALUE,1,10),10)||'HIGHWATER MARK='||
   L.SESSIONS_HIGHWATER INFORMATION
FROM
   V$SYSSTAT SS,
   V$LICENSE L,
   V$DATABASE D
WHERE
   SS.NAME = 'logons cumulative';

/* ACTIVE SESSIONS DETAILS SPECIFIED DB USERNAME YOU ARE LOOKING FOR OR PRESS ENTER KEY FOR ALL USERS */

SET PAGESIZE 50;
SET LINESIZE 300;

COLUMN "SID" FORMAT 99999999
COLUMN "SERIAL" FORMAT 99999999
COLUMN "OS ID" FORMAT A12
COLUMN "OSUSER" FORMAT A12
COLUMN "LOGON TIME" FORMAT A18
COLUMN "DB USERNAME" FORMAT A12
COLUMN "STATUS" FORMAT A9

BREAK ON "LOGON TIME" ON "OS ID" ON "OSUSER" ON "DB USERNAME" ON "SID" ON "SERIAL" ON "SQL ID" ON "STATUS";

SELECT TO_CHAR(B.LOGON_TIME,'DD-MON-YYYY HH24:MI') "LOGON TIME",
       C.SPID "OS ID",
       B.OSUSER "OSUSER",
       B.USERNAME "DB USERNAME",
       B.SID "SID",
       B.SERIAL# "SERIAL",
       A.SQL_ID "SQL ID",
       B.STATUS "STATUS",
       A.SQL_TEXT "SQL TEXT"
FROM V$SQLTEXT A, V$SESSION B, V$PROCESS C
WHERE A.ADDRESS = B.SQL_ADDRESS
  AND B.PADDR = C.ADDR
  AND A.HASH_VALUE = B.SQL_HASH_VALUE
  AND B.STATUS = 'ACTIVE' /* YOU CAN CHOOSE THIS OPTION ONLY TO SEE ACTVE TRANSACTION ON THAT MOMENT */
  AND B.USERNAME LIKE UPPER('%&DATABASE_USERNAME%')
  ORDER BY C.SPID, A.HASH_VALUE, A.PIECE
/

/* ACTIVE SESSIONS DETAILS SPECIFIED OS USERNAME YOU ARE LOOKING FOR OR PRESS ENTER KEY FOR ALL OS USERS CONNECTED TO DATABASE */

SET PAGESIZE 50;
SET LINESIZE 300;

COLUMN "SID" FORMAT 99999999
COLUMN "SERIAL" FORMAT 99999999
COLUMN "OS ID" FORMAT A12
COLUMN "OSUSER" FORMAT A12
COLUMN "LOGON TIME" FORMAT A18
COLUMN "DB USERNAME" FORMAT A12
COLUMN "STATUS" FORMAT A9

BREAK ON "LOGON TIME" ON "OS ID" ON "OSUSER" ON "DB USERNAME" ON "SID" ON "SERIAL" ON "SQL ID" ON "STATUS";

SELECT TO_CHAR(B.LOGON_TIME,'DD-MON-YYYY HH24:MI') "LOGON TIME",
       C.SPID "OS ID",
       B.OSUSER "OSUSER",
       B.USERNAME "DB USERNAME",
       B.SID "SID",
       B.SERIAL# "SERIAL",
       A.SQL_ID "SQL ID",
       B.STATUS "STATUS",
       A.SQL_TEXT "SQL TEXT"
FROM V$SQLTEXT A, V$SESSION B, V$PROCESS C
WHERE A.ADDRESS = B.SQL_ADDRESS
  AND B.PADDR = C.ADDR
  AND A.HASH_VALUE = B.SQL_HASH_VALUE
  AND B.STATUS = 'ACTIVE' /* YOU CAN CHOOSE THIS OPTION ONLY TO SEE ACTVE TRANSACTION ON THAT MOMENT */
  AND B.OSUSER LIKE '%&OS_USERNAME%'
  ORDER BY C.SPID, A.HASH_VALUE, A.PIECE
/

/* ACTIVE SESSIONS DETAILS SPECIFIED DB SID YOU ARE LOOKING FOR OR PRESS ENTER KEY FOR ALL SID'S */

SET PAGESIZE 50;
SET LINESIZE 300;

COLUMN "SID" FORMAT 99999999
COLUMN "SERIAL" FORMAT 99999999
COLUMN "OS ID" FORMAT A12
COLUMN "OSUSER" FORMAT A12
COLUMN "LOGON TIME" FORMAT A18
COLUMN "DB USERNAME" FORMAT A12
COLUMN "STATUS" FORMAT A9

BREAK ON "LOGON TIME" ON "OS ID" ON "OSUSER" ON "DB USERNAME" ON "SID" ON "SERIAL" ON "SQL ID" ON "STATUS";

SELECT TO_CHAR(B.LOGON_TIME,'DD-MON-YYYY HH24:MI') "LOGON TIME",
       C.SPID "OS ID",
       B.OSUSER "OSUSER",
       B.USERNAME "DB USERNAME",
       B.SID "SID",
       B.SERIAL# "SERIAL",
       A.SQL_ID "SQL ID",
       B.STATUS "STATUS",
       A.SQL_TEXT "SQL TEXT"
FROM V$SQLTEXT A, V$SESSION B, V$PROCESS C
WHERE A.ADDRESS = B.SQL_ADDRESS
  AND B.PADDR = C.ADDR
  AND A.HASH_VALUE = B.SQL_HASH_VALUE
  AND B.STATUS = 'ACTIVE' /* YOU CAN CHOOSE THIS OPTION ONLY TO SEE ACTVE TRANSACTION ON THAT MOMENT */
  AND B.SID LIKE '%&DB_SID%'
  ORDER BY C.SPID, A.HASH_VALUE, A.PIECE
/

/* ACTIVE SESSIONS DETAILS SPECIFIED OS PID YOU ARE LOOKING FOR OR PRESS ENTER KEY FOR ALL OS ID'S CONNECTED TO DATABASE */

SET PAGESIZE 50;
SET LINESIZE 300;

COLUMN "SID" FORMAT 99999999
COLUMN "SERIAL" FORMAT 99999999
COLUMN "OS ID" FORMAT A12
COLUMN "OSUSER" FORMAT A12
COLUMN "LOGON TIME" FORMAT A18
COLUMN "DB USERNAME" FORMAT A12
COLUMN "STATUS" FORMAT A9

BREAK ON "LOGON TIME" ON "OS ID" ON "OSUSER" ON "DB USERNAME" ON "SID" ON "SERIAL" ON "SQL ID" ON "STATUS";

SELECT TO_CHAR(B.LOGON_TIME,'DD-MON-YYYY HH24:MI') "LOGON TIME",
       C.SPID "OS ID",
       B.OSUSER "OSUSER",
       B.USERNAME "DB USERNAME",
       B.SID "SID",
       B.SERIAL# "SERIAL",
       A.SQL_ID "SQL ID",
       B.STATUS "STATUS",
       A.SQL_TEXT "SQL TEXT"
FROM V$SQLTEXT A, V$SESSION B, V$PROCESS C
WHERE A.ADDRESS = B.SQL_ADDRESS
  AND B.PADDR = C.ADDR
  AND A.HASH_VALUE = B.SQL_HASH_VALUE
  AND B.STATUS = 'ACTIVE' /* YOU CAN CHOOSE THIS OPTION ONLY TO SEE ACTVE TRANSACTION ON THAT MOMENT */
  AND C.SPID LIKE '%&OS_PID%'
  ORDER BY C.SPID, A.HASH_VALUE, A.PIECE
/

/* ACTIVE SESSIONS DETAILS SPECIFIED SQL ID YOU ARE LOOKING FOR OR PRESS ENTER KEY FOR ALL SQL ID'S */

SET PAGESIZE 50;
SET LINESIZE 300;

COLUMN "SID" FORMAT 99999999
COLUMN "SERIAL" FORMAT 99999999
COLUMN "OS ID" FORMAT A12
COLUMN "OSUSER" FORMAT A12
COLUMN "LOGON TIME" FORMAT A18
COLUMN "DB USERNAME" FORMAT A12
COLUMN "STATUS" FORMAT A9

BREAK ON "LOGON TIME" ON "OS ID" ON "OSUSER" ON "DB USERNAME" ON "SID" ON "SERIAL" ON "SQL ID" ON "STATUS";

SELECT TO_CHAR(B.LOGON_TIME,'DD-MON-YYYY HH24:MI') "LOGON TIME",
       C.SPID "OS ID",
       B.OSUSER "OSUSER",
       B.USERNAME "DB USERNAME",
       B.SID "SID",
       B.SERIAL# "SERIAL",
       A.SQL_ID "SQL ID",
       B.STATUS "STATUS",
       A.SQL_TEXT "SQL TEXT"
FROM V$SQLTEXT A, V$SESSION B, V$PROCESS C
WHERE A.ADDRESS = B.SQL_ADDRESS
  AND B.PADDR = C.ADDR
  AND A.HASH_VALUE = B.SQL_HASH_VALUE
  AND B.STATUS = 'ACTIVE' /* YOU CAN CHOOSE THIS OPTION ONLY TO SEE ACTVE TRANSACTION ON THAT MOMENT */
  AND A.SQL_ID LIKE '%&SQL_ID%'
  ORDER BY C.SPID, A.HASH_VALUE, A.PIECE
/

Friday, February 1, 2013

Identify Long running queries

Note:  Proofread any scripts before using. Always try scripts on a test instance first. This Blog is not responsible for any damage.

/* To find the long running queries details */

SET LINESIZE 132

COLUMN SSID FORMAT 999999 HEADING SID
COLUMN SSERIAL FORMAT 999999 HEADING SERIAL
COLUMN OPNAME FORMAT A15 HEADING OPERATION
COLUMN TARGET FORMAT A40 HEADING TARGET
COLUMN ES FORMAT 9999999.90 HEADING "TIME RAN|(in Min's)"
COLUMN TR FORMAT 9999999.90 HEADING "TIME LEFT|(in Min's)"
COLUMN PCT FORMAT 990 HEADING "PCT"
COLUMN RATE FORMAT A10 HEADING "I/O RATE|per Min" JUST RIGHT

SELECT SID SSID, SERIAL# SSERIAL,
       SUBSTR(OPNAME,1,15) OPNAME,
       TARGET,
       TRUNC((SOFAR/TOTALWORK)*100) PCT,
       TO_CHAR(60*SOFAR*8192/(24*60*(LAST_UPDATE_TIME - START_TIME))/1024/1024/60, '9999.0')||'M' RATE,
       ELAPSED_SECONDS/60 ES,
       TIME_REMAINING/60 TR
FROM V$SESSION_LONGOPS
WHERE TIME_REMAINING > 0
ORDER BY START_TIME
/

Oracle ASM Concepts

Note: Proofread any scripts before using. Always try scripts on a test instance first. This Blog is not responsible for any damage. O...