Showing posts with label Oracle 11g. Show all posts
Showing posts with label Oracle 11g. Show all posts

Thursday, September 11, 2014

DESCRIBE ref cursor - How to display the metadata of the ref cursor.



In  most of the development houses , the database API ( aka  package ) are developed by the database development team and then the API's signature handed over the application / web development team. 

For the most part , it is easier to print the ref cursor contents ; but to get the column name and its datatypes , it is not that obvious in sqlplus ( Some of the tools has features ) .  In Oracle 11g , we can use dbms_sql package to display the column type , size , precision and so on. 

Let us see an example . 
First , let us create a package and package body .  This API will display 10 zipcodes for a given state code. 



SQL> desc zips
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 ZIPCODE                                            VARCHAR2(5)
 PO_NAME                                            VARCHAR2(255)
 COUNTY                                             VARCHAR2(255)
 STATE                                              VARCHAR2(2)

SQL> create or replace PACKAGE listzipcode_pkg
  2  AS
  3    PROCEDURE list_by_statecode_p(
  4        statecode_p VARCHAR2 ,
  5        zipcode_list_rc OUT sys_refcursor) ;
  6  END listzipcode_pkg;
  7  /

Package created.

SQL> CREATE OR REPLACE PACKAGE body listzipcode_pkg
  2  AS
  3  PROCEDURE list_by_statecode_p(
  4      statecode_p VARCHAR2 ,
  5      zipcode_list_rc OUT sys_refcursor)
  6  AS
  7  BEGIN
  8    OPEN zipcode_list_rc FOR SELECT * FROM
  9    (
 10      SELECT
 11        state ,
 12        zipcode ,
 13        to_number(zipcode) AS ZipCode_Number
 14      FROM
 15        zips
 16      WHERE
 17        STATE = statecode_p
 18      ORDER BY
 19        zipcode
 20    )
 21    WHERE rownum < 11 ;
 22  END list_by_statecode_p;
 23  END listzipcode_pkg;
 24  /

Package body created.


We can use the ref cursor to display the contents as shown below. 

SQL> variable x refcursor;
SQL> exec listzipcode_pkg.list_by_statecode_p( 'NJ' , :x) ;

PL/SQL procedure successfully completed.

SQL> print :x ;

ST ZIPCO ZIPCODE_NUMBER
-- ----- --------------
NJ 07001           7001
NJ 07002           7002
NJ 07003           7003
NJ 07004           7004
NJ 07005           7005
NJ 07006           7006
NJ 07007           7007
NJ 07008           7008
NJ 07009           7009
NJ 07010           7010


10 rows selected.


To describe ( aka to list the column names , data types ) , let us create an anonymous PL/SQL block . 

Here we go.

SQL> SET serveroutput ON
SQL> DECLARE
  2    l_rcursor sys_refcursor;
  3    l_statecode   VARCHAR2(2);
  4    l_col_type    VARCHAR2(100) ;
  5    l_cursor_name VARCHAR2(100) ;
  6    l_colCnt      NUMBER;
  7    l_descTbl dbms_sql.desc_tab;
  8  BEGIN
  9    l_statecode := 'NJ';
 10    listzipcode_pkg.list_by_statecode_p( statecode_p => l_statecode ,
 11    zipcode_list_rc => l_rcursor) ;
 12    l_cursor_name := 'list_by_statecode_p';
 13    dbms_sql.describe_columns ( c => dbms_sql.to_cursor_number(l_rcursor) ,
 14    col_cnt => l_colCnt, desc_t => l_descTbl );
 15    dbms_output.put_line( RPAD( 'Name' , 25 , ' ' ) || 'Type' );
 16    dbms_output.put_line( RPAD( '----' , 25 , ' ' ) || '----' );
 17    FOR i IN 1 .. l_colCnt
 18    LOOP
 19      IF l_descTbl(i).col_type    = 2 THEN
 20        l_col_type               := 'NUMBER';
 21      ELSIF l_descTbl(i).col_type = 1 THEN
 22        l_col_type               := 'VARCHAR2';
 23      ELSE
 24        l_col_type := l_descTbl(i).col_type ;
 25      END IF;
 26      dbms_output.put_line( RPAD( l_descTbl(i).col_name, 25 , ' ' ) || l_col_type
 27      );
 28    END LOOP;
 29  END ;
 30
 31  /
Name                     Type
----                     ----
STATE                    VARCHAR2
ZIPCODE                  VARCHAR2
ZIPCODE_NUMBER           NUMBER


PL/SQL procedure successfully completed.



In the PL/SQL block , we use dbms_sql to get the metadata contents of the ref cursor . The above shows only the column name , column's datatype . We can extend the above block to show the maximum length , precision , scale and so forth. 

Another thing to note is that the return value of "col_type" is an integer . You need to look it up against the associated name . This information can be found in ALL_SOURCE view. 


SQL> select   text   from   all_source
  2  where   owner = 'SYS' and name = 'DBMS_TYPES' and type = 'PACKAGE';

TEXT
--------------------------------------------------------------------------------
PACKAGE dbms_types AS
  TYPECODE_DATE            PLS_INTEGER :=  12;
  TYPECODE_NUMBER          PLS_INTEGER :=   2;
  TYPECODE_RAW             PLS_INTEGER :=  95;
  TYPECODE_CHAR            PLS_INTEGER :=  96;
  TYPECODE_VARCHAR2        PLS_INTEGER :=   9;
  TYPECODE_VARCHAR         PLS_INTEGER :=   1;
  TYPECODE_MLSLABEL        PLS_INTEGER := 105;
  TYPECODE_BLOB            PLS_INTEGER := 113;
  TYPECODE_BFILE           PLS_INTEGER := 114;
  TYPECODE_CLOB            PLS_INTEGER := 112;
  TYPECODE_CFILE           PLS_INTEGER := 115;
  TYPECODE_TIMESTAMP       PLS_INTEGER := 187;
  TYPECODE_TIMESTAMP_TZ    PLS_INTEGER := 188;
  TYPECODE_TIMESTAMP_LTZ   PLS_INTEGER := 232;
  TYPECODE_INTERVAL_YM     PLS_INTEGER := 189;
  TYPECODE_INTERVAL_DS     PLS_INTEGER := 190;

  TYPECODE_REF             PLS_INTEGER := 110;
  TYPECODE_OBJECT          PLS_INTEGER := 108;
  TYPECODE_VARRAY          PLS_INTEGER := 247;            /* COLLECTION TYPE */
  TYPECODE_TABLE           PLS_INTEGER := 248;            /* COLLECTION TYPE */
  TYPECODE_NAMEDCOLLECTION PLS_INTEGER := 122;
  TYPECODE_OPAQUE          PLS_INTEGER := 58;                 /* OPAQUE TYPE */

  /* NOTE: These typecodes are for use in AnyData api only and are short forms
     for the corresponding char typecodes with a charset form of SQLCS_NCHAR.
  */
  TYPECODE_NCHAR           PLS_INTEGER := 286;
  TYPECODE_NVARCHAR2       PLS_INTEGER := 287;
  TYPECODE_NCLOB           PLS_INTEGER := 288;

  /* Typecodes for Binary Float, Binary Double and Urowid. */
  TYPECODE_BFLOAT          PLS_INTEGER := 100;
  TYPECODE_BDOUBLE         PLS_INTEGER := 101;
  TYPECODE_UROWID          PLS_INTEGER := 104;

  SUCCESS                  PLS_INTEGER := 0;
  NO_DATA                  PLS_INTEGER := 100;

  /* Exceptions */
  invalid_parameters EXCEPTION;
  PRAGMA EXCEPTION_INIT(invalid_parameters, -22369);

  incorrect_usage EXCEPTION;
  PRAGMA EXCEPTION_INIT(incorrect_usage, -22370);

  type_mismatch EXCEPTION;
  PRAGMA EXCEPTION_INIT(type_mismatch, -22626);

END dbms_types;


51 rows selected.


Happy describing . 

Comments Welcome !


Thursday, October 25, 2012

Duplicating Databases / Restoring Database to New Host using RMAN.



The duplicating  of the database has gotten lot more easier with RMAN.

Assume we have copied the backup sets / backup control file / spfile  into "C:\FlashRecoveryArea" in the target server Or access to the backup sets / backup control file / spfile in the network share , the process is straight forward.   

Of course , there is little bit of leg work to be done before we issue RMAN's  duplicate database . 

Let us look at the steps below.


Step1 : Create a PFILE


In the pfile , we just the db name to "DUP2" ( this is going to be the name of the duplicated database".

C:>echo db_name='DUP2' > C:\app\mohideen\product\11.2.0\dbhome_1\database\INITDUP2.ORA

Step2:  Create Oracle Instance using ORADIM

Being the duplication is done in Windows environment , we would need to create the service using oradim utility.

C:>oradim -new -sid dup2 -intpwd Orapwd$dup2
Instance created.


Step3: Create the directories to hold the datafiles , logfiles , archived redo logs , ....

C:>mkdir  C:\app\mohideen\oradata\dup2\CONTROLFILE\
C:>mkdir C:\app\mohideen\oradata\DUP2\DATAFILE\
C:>mkdir C:\app\mohideen\oradata\DUP2\LOGFILE\
C:>mkdir C:\app\mohideen\oradata\dup2\ARCHIVELOG1\
C:>mkdir C:\app\mohideen\oradata\dup2\ARCHIVELOG2\
C:>mkdir C:\app\mohideen\FRA\dup2


Step4 : Set the SID to the destination database. 
 
C:\>set ORACLE_SID=dup2
 


 Step 5: Connect to the instance . 

As there is no database associated with this instance . it should say " Connected to an idle instance" as below.

C:\>sqlplus / as sysdba
SQL*Plus: Release 11.2.0.3.0 Production on Thu Oct 25 10:36:03 201
Copyright (c) 1982, 2011, Oracle.  All rights reserved.

Connected to an idle instance.



Step 6: Start the database in nomount state

SQL> startup nomount;
ORACLE instance started.

Total System Global Area  313196544 bytes
Fixed Size                  2254704 bytes
Variable Size             255854736 bytes
Database Buffers           50331648 bytes
Redo Buffers                4755456 bytes
SQL>



Step 7:  Determine the location of the data files / log files from the source database.

SQL> select name   FROM v$datafile;

NAME
----------------------------------------
E:\DATA\DBPRD\SYSTEM01.DBF
E:\DATA\DBPRD\SYSAUX01.DBF
E:\DATA\DBPRD\UNDOTBS01.DBF
E:\DATA\DBPRD\USERS01.DBF
E:\DATA\DBPRD\SYSAUX02.DBF
E:\DATA\DBPRD\TBSDW.DBF

6 rows selected.


Get the log file's location .

SQL> select MEMBER  FROM v$logfile;

MEMBER

------------------------------------------------
E:\DATA\DBPRD\REDO03.LOG
E:\DATA\DBPRD\REDO02.LOG
E:\DATA\DBPRD\REDO01.LOG


These locations ( e:\data\dbprd)  need to be mentioned in the RCV File created in  the next step.

Step 8: Prepare the RCV file for RMAN to duplicate. 

Prepare the RCV that contains  the location for the  Control files  , flash recovery area , listener name , ADR location . Also , the file should contain the new locations for the data files / log files .

Finally , we need to provide the location where backups are stored ( c:\fastrecoveryarea ) in this case.


C:\dup_db>type dup.rcv
run
{
duplicate database to dup2
spfile
set control_files='c:\app\mohideen\oradata\dup2\CONTROLFILE\CONTROL1.CTL','c:\app\mohideen\oradata\dup2\CONTROLFILE\CONTROL2.CTL'
set db_file_name_convert='E:\DATA\DBPRD','c:\app\mohideen\oradata\DUP2\DATAFILE'
set log_file_name_convert='E:\DATA\DBPRD','c:\app\mohideen\oradata\DUP2\LOGFILE'
set db_recovery_file_dest='c:\app\mohideen\FRA\dup2\'
set LOG_ARCHIVE_DEST_2='location=c:\app\mohideen\oradata\dup2\ARCHIVELOG1\'
set LOG_ARCHIVE_DEST_3='location=c:\app\mohideen\oradata\dup2\ARCHIVELOG2\'
set diagnostic_dest='C:\app\mohideen'
set local_listener=''
backup location 'c:\FastRecoveryArea';



Step 9 : Issue RMAN  Duplicate Database

Here is where the rubber meets the road ; all of your leg work pays off . RMAN duplicates the database based on the RCV file . 

C:\dup_db>rman auxiliary  /  cmdfile dup.rcv  log  dup.log
RMAN> 2> 3> 4> 5> 6> 7> 8> 9> 10> 11> 12> 13> 14> 15>
C:\dup_db>



Look for any errors in the log file ( dup.log ) . You may want to look at the dup.log to see what are the steps RMAN did to perform the duplication process. 

Now you have duplicated the database .  

Hope this was clear . 

Please email me for your feedback.

Friday, December 2, 2011

Dump ASH Data.

These are few ways you can look at the ASH data.

1) Generating ASH Report from Enterprise Manager
2) Querying  v$active_session_history
3) Generating ASH Report from sql ( ashrpt.sql or ashrpti.sql  in ORACLE_HOME\admin )
4) Dump ASH to a file .


The first three steps are pretty straightforward.
I would opt for first method , as it is available right there in OEM and then I can navigate to appropriate SQLs.

But , for others , we do have some options . ...

Let us see how method 4 works.

The following example dumps the ASH data for the past 5 minutes.


C:>sqlplus / as sysdba
SQL> oradebug setmypid
Statement processed.
SQL> oradebug dump ashdump 5
Statement processed.

You can use the file to load into the table via SQL Loader or External Table and analyze the ASH data.

Contents of the trace file
--------------------------

Trace file D:\APP\ORACLE\diag\rdbms\dbdev\dbdev\trace\dbdev_ora_5592.trc
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Windows NT Version V6.1 
CPU                 : 2 - type 8664, 2 Physical Cores
Process Affinity    : 0x0x0000000000000000
Memory (Avail/Total): Ph:1835M/3839M, Ph+PgF:5607M/7677M
Instance name: dbdev
Redo thread mounted by this instance: 1
Oracle process number: 28
Windows thread id: 5592, image: ORACLE.EXE (SHAD)


*** 2011-12-02 09:53:33.615
*** SESSION ID:(24.6023) 2011-12-02 09:53:33.615
*** CLIENT ID:() 2011-12-02 09:53:33.615
*** SERVICE NAME:(dbdev.test.edu) 2011-12-02 09:53:33.615
*** MODULE NAME:(sqlplus.exe) 2011-12-02 09:53:33.615
*** ACTION NAME:() 2011-12-02 09:53:33.615
 
Processing Oradebug command 'setmypid'

*** 2011-12-02 09:53:33.615
Oradebug command 'setmypid' console output:

*** 2011-12-02 09:53:57.881
Processing Oradebug command 'dump ashdump 5'
ASH dump
<<>>
****************
SCRIPT TO IMPORT
****************
------------------------------------------
Step 1: Create destination table
------------------------------------------
CREATE TABLE ashdump AS
SELECT * FROM SYS.WRH$_ACTIVE_SESSION_HISTORY WHERE rownum < 0
----------------------------------------------------------------
Step 2: Create the SQL*Loader control file as below
----------------------------------------------------------------
load data
infile * "str '\n####\n'"
append
into table ashdump
fields terminated by ',' optionally enclosed by '"'
(                              
SNAP_ID  CONSTANT 0           ,
DBID                          ,
INSTANCE_NUMBER               ,
SAMPLE_ID                     ,
SAMPLE_TIME TIMESTAMP ENCLOSED BY '"' AND '"' "TO_TIMESTAMP(:SAMPLE_TIME   ,'MM-DD-YYYY HH24:MI:SSXFF')"   ,
SESSION_ID                    ,
SESSION_SERIAL#               ,
SESSION_TYPE                  ,
USER_ID                       ,
SQL_ID                        ,
SQL_CHILD_NUMBER              ,
SQL_OPCODE                    ,
FORCE_MATCHING_SIGNATURE      ,
TOP_LEVEL_SQL_ID              ,
TOP_LEVEL_SQL_OPCODE          ,
SQL_PLAN_HASH_VALUE           ,
SQL_PLAN_LINE_ID              ,
SQL_PLAN_OPERATION#           ,
SQL_PLAN_OPTIONS#             ,
SQL_EXEC_ID                   ,
SQL_EXEC_START DATE 'MM/DD/YYYY HH24:MI:SS' ENCLOSED BY '"' AND '"' ":SQL_EXEC_START"   ,
PLSQL_ENTRY_OBJECT_ID         ,
PLSQL_ENTRY_SUBPROGRAM_ID     ,
PLSQL_OBJECT_ID               ,
PLSQL_SUBPROGRAM_ID           ,
QC_INSTANCE_ID                ,
QC_SESSION_ID                 ,
QC_SESSION_SERIAL#            ,
EVENT_ID                      ,
SEQ#                          ,
P1                            ,
P2                            ,
P3                            ,
WAIT_TIME                     ,
TIME_WAITED                   ,
BLOCKING_SESSION              ,
BLOCKING_SESSION_SERIAL#      ,
BLOCKING_INST_ID              ,
CURRENT_OBJ#                  ,
CURRENT_FILE#                 ,
CURRENT_BLOCK#                ,
CURRENT_ROW#                  ,
TOP_LEVEL_CALL#               ,
CONSUMER_GROUP_ID             ,
XID                           ,
REMOTE_INSTANCE#              ,
TIME_MODEL                    ,
SERVICE_HASH                  ,
PROGRAM                       ,
MODULE                        ,
ACTION                        ,
CLIENT_ID                     ,
MACHINE                       ,
PORT                          ,
ECID                           
)                              
---------------------------------------------------
Step 3: Load the ash rows dumped in this trace file
---------------------------------------------------
sqlldr userid/password control=ashldr.ctl data= errors=1000000
---------------------------------------------------
<<>>
<<>>
####
2627103816,1,27387994,"12-02-2011 09:53:47.800000000",126,1,2,0,"",0,0,0,"",0,0,0,0,0,0,"",0,0,0,0,0,0,0,866018717,59482,100,0,0,998719,0,4294967291,0,0,4294967295,0,0,0,0,0,,0,0,165959219,"ORACLE.EXE (PSP0)","","","","SERVER-DB02",0,""
####
2627103816,1,27387993,"12-02-2011 09:53:46.801000000",6,1,2,0,"",0,0,0,"",0,0,0,0,0,0,"",0,0,0,0,0,0,0,3213517201,58536,0,1,1,0,12920,4294967295,0,0,4294967295,0,0,0,0,0,,0,0,165959219,"ORACLE.EXE (CKPT)","","","","SERVER-DB02",0,""
####
2627103816,1,27387990,"12-02-2011 09:53:43.802000000",6,1,2,0,"",0,0,0,"",0,0,0,0,0,0,"",0,0,0,0,0,0,0,4078387448,58530,2,3,2,0,651,4294967295,0,0,4294967295,0,0,0,0,0,,0,0,165959219,"ORACLE.EXE (CKPT)","","","","SERVER-DB02",0,""
####
2627103816,1,27387977,"12-02-2011 09:53:30.771000000",126,1,2,0,"",0,0,0,"",0,0,0,0,0,0,"",0,0,0,0,0,0,0,866018717,59466,100,0,0,999755,0,4294967291,0,0,4294967295,0,0,0,0,0,,0,0,165959219,"ORACLE.EXE (PSP0)","","","","SERVER-DB02",0,""
####
2627103816,1,27387959,"12-02-2011 09:53:12.731000000",126,1,2,0,"",0,0,0,"",0,0,0,0,0,0,"",0,0,0,0,0,0,0,866018717,59447,100,0,0,999253,0,4294967291,0,0,4294967295,0,0,0,0,0,,0,0,165959219,"ORACLE.EXE (PSP0)","","","","SERVER-DB02",0,""
####
2627103816,1,27387943,"12-02-2011 09:52:56.717000000",126,1,2,0,"",0,0,0,"",0,0,0,0,0,0,"",0,0,0,0,0,0,0,866018717,59431,100,0,0,1000095,0,4294967291,0,0,4294967295,0,0,0,0,0,,0,0,165959219,"ORACLE.EXE (PSP0)","","","","SERVER-DB02",0,""
####
2627103816,1,27387942,"12-02-2011 09:52:55.716000000",126,1,2,0,"",0,0,0,"",0,0,0,0,0,0,"",0,0,0,0,0,0,0,866018717,59430,100,0,0,998594,0,4294967291,0,0,4294967295,0,0,0,0,0,,0,0,165959219,"ORACLE.EXE (PSP0)","","","","SERVER-DB02",0,""
####
2627103816,1,27387926,"12-02-2011 09:52:39.717000000",126,1,2,0,"",0,0,0,"",0,0,0,0,0,0,"",0,0,0,0,0,0,0,866018717,59414,100,0,0,997838,0,4294967291,0,0,4294967295,0,0,0,0,0,,0,0,165959219,"ORACLE.EXE (PSP0)","","","","SERVER-DB02",0,""
####
2627103816,1,27387909,"12-02-2011 09:52:22.719000000",126,1,2,0,"",0,0,0,"",0,0,0,0,0,0,"",0,0,0,0,0,0,0,866018717,59393,100,0,0,999836,0,4294967291,0,0,4294967295,0,0,0,0,0,,0,0,165959219,"ORACLE.EXE (PSP0)","","","","SERVER-DB02",0,""
####
2627103816,1,27387892,"12-02-2011 09:52:05.705000000",126,1,2,0,"",0,0,0,"",0,0,0,0,0,0,"",0,0,0,0,0,0,0,866018717,59376,100,0,0,1001355,0,4294967291,0,0,4294967295,0,0,0,0,0,,0,0,165959219,"ORACLE.EXE (PSP0)","","","","SERVER-DB02",0,""
####
2627103816,1,27387875,"12-02-2011 09:51:48.707000000",126,1,2,0,"",0,0,0,"",0,0,0,0,0,0,"",0,0,0,0,0,0,0,866018717,59359,100,0,0,1000171,0,4294967291,0,3937105842,4294967295,0,0,0,0,0,,0,0,165959219,"ORACLE.EXE (PSP0)","","","","SERVER-DB02",0,""
####
2627103816,1,27387858,"12-02-2011 09:51:31.708000000",126,1,2,0,"",0,0,0,"",0,0,0,0,0,0,"",0,0,0,0,0,0,0,866018717,59343,100,0,0,999867,0,4294967291,0,0,4294967295,0,0,0,0,0,,0,0,165959219,"ORACLE.EXE (PSP0)","","","","SERVER-DB02",0,""
####
2627103816,1,27387841,"12-02-2011 09:51:14.697000000",126,1,2,0,"",0,0,0,"",0,0,0,0,0,0,"",0,0,0,0,0,0,0,866018717,59325,100,0,0,999688,0,4294967291,0,0,4294967295,0,0,0,0,0,,0,0,165959219,"ORACLE.EXE (PSP0)","","","","SERVER-DB02",0,""
####
2627103816,1,27387825,"12-02-2011 09:50:58.698000000",4,1,2,0,"",0,0,0,"",0,0,0,0,0,0,"",0,0,0,0,0,0,0,3176176482,54366,5,1,1000,999949,0,4294967291,0,0,4294967295,0,0,0,0,0,,0,0,165959219,"ORACLE.EXE (DIA0)","","","","SERVER-DB02",0,""
####
2627103816,1,27387824,"12-02-2011 09:50:57.698000000",126,1,2,0,"",0,0,0,"",0,0,0,0,0,0,"",0,0,0,0,0,0,0,866018717,59308,100,0,0,1000193,0,4294967291,0,0,4294967295,0,0,0,0,0,,0,0,165959219,"ORACLE.EXE (PSP0)","","","","SERVER-DB02",0,""
####
2627103816,1,27387814,"12-02-2011 09:50:47.683000000",4,1,2,0,"",0,0,0,"",0,0,0,0,0,0,"",0,0,0,0,0,0,0,3176176482,54355,5,1,1000,999911,0,4294967291,0,0,4294967295,0,0,0,0,0,,0,0,165959219,"ORACLE.EXE (DIA0)","","","","SERVER-DB02",0,""
####
2627103816,1,27387812,"12-02-2011 09:50:45.683000000",6,1,2,0,"",0,0,0,"",0,0,0,0,0,0,"",0,0,0,0,0,0,0,3213517201,58069,0,1,1,0,11257,4294967295,0,3306949592,4294967295,0,0,0,0,0,,0,0,165959219,"ORACLE.EXE (CKPT)","","","","SERVER-DB02",0,""
####
2627103816,1,27387809,"12-02-2011 09:50:42.683000000",6,1,2,0,"",0,0,0,"",0,0,0,0,0,0,"",0,0,0,0,0,0,0,3213517201,58065,0,15,1,0,428,4294967295,0,0,4294967295,0,0,0,0,0,,0,0,165959219,"ORACLE.EXE (CKPT)","","","","SERVER-DB02",0,""
####
2627103816,1,27387807,"12-02-2011 09:50:40.683000000",126,1,2,0,"",0,0,0,"",0,0,0,0,0,0,"",0,0,0,0,0,0,0,866018717,59292,100,0,0,1000681,0,4294967291,0,0,4294967295,0,0,0,0,0,,0,0,165959219,"ORACLE.EXE (PSP0)","","","","SERVER-DB02",0,""
####
2627103816,1,27387790,"12-02-2011 09:50:23.685000000",126,1,2,0,"",0,0,0,"",0,0,0,0,0,0,"",0,0,0,0,0,0,0,866018717,59274,100,0,0,999428,0,4294967291,0,0,4294967295,0,0,0,0,0,,0,0,165959219,"ORACLE.EXE (PSP0)","","","","SERVER-DB02",0,""
####
2627103816,1,27387773,"12-02-2011 09:50:06.686000000",126,1,2,0,"",0,0,0,"",0,0,0,0,0,0,"",0,0,0,0,0,0,0,866018717,59258,100,0,0,999501,0,4294967291,0,0,4294967295,0,0,0,0,0,,0,0,165959219,"ORACLE.EXE (PSP0)","","","","SERVER-DB02",0,""
####
2627103816,1,27387756,"12-02-2011 09:49:49.672000000",126,1,2,0,"",0,0,0,"",0,0,0,0,0,0,"",0,0,0,0,0,0,0,866018717,59241,100,0,0,999596,0,4294967291,0,0,4294967295,0,0,0,0,0,,0,0,165959219,"ORACLE.EXE (PSP0)","","","","SERVER-DB02",0,""
####
2627103816,1,27387750,"12-02-2011 09:49:43.672000000",4,1,2,0,"",0,0,0,"",0,0,0,0,0,0,"",0,0,0,0,0,0,0,3176176482,54291,5,1,1000,1001875,0,4294967291,0,0,4294967295,0,0,0,0,0,,0,0,165959219,"ORACLE.EXE (DIA0)","","","","SERVER-DB02",0,""
####
2627103816,1,27387739,"12-02-2011 09:49:32.659000000",126,1,2,0,"",0,0,0,"",0,0,0,0,0,0,"",0,0,0,0,0,0,0,866018717,59225,100,0,0,1000266,0,4294967291,0,0,4294967295,0,0,0,0,0,,0,0,165959219,"ORACLE.EXE (PSP0)","","","","SERVER-DB02",0,""
####
2627103816,1,27387722,"12-02-2011 09:49:15.641000000",126,1,2,0,"",0,0,0,"",0,0,0,0,0,0,"",0,0,0,0,0,0,0,866018717,59207,100,0,0,999939,0,4294967291,0,0,4294967295,0,0,0,0,0,,0,0,165959219,"ORACLE.EXE (PSP0)","","","","SERVER-DB02",0,""
####
2627103816,1,27387706,"12-02-2011 09:48:59.624000000",126,1,2,0,"",0,0,0,"",0,0,0,0,0,0,"",0,0,0,0,0,0,0,866018717,59189,100,0,0,999878,0,4294967291,0,0,4294967295,0,0,0,0,0,,0,0,165959219,"ORACLE.EXE (PSP0)","","","","SERVER-DB02",0,""
####
<<>>

*** 2011-12-02 09:53:57.896
Oradebug command 'dump ashdump 5' console output:

Saturday, October 1, 2011

How to estimate the size of the index in oracle

In Oracle , there are few ways to estimate the size of the index , that you are planning to create.
Let us see an example .


Method 1:
SQL> drop table t purge ;
Table dropped.

SQL> create table t as select object_id , object_name , object_type from all_objects ;
Table created.

SQL> exec dbms_stats.gather_table_stats(user,'T');
PL/SQL procedure successfully completed.

SQL> explain plan for create index idx1_t on t(object_id);
Explained.

SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------
------------------------------
Plan hash value: 2847741357
---------------------------------------------------------------------------------
| Id  | Operation              | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------
|   0 | CREATE INDEX STATEMENT |        | 77233 |   377K|   170   (1)| 00:00:01 |
|   1 |  INDEX BUILD NON UNIQUE| IDX1_T |       |       |            |          |
|   2 |   SORT CREATE INDEX    |        | 77233 |   377K|            |          |
|   3 |    TABLE ACCESS FULL   | T      | 77233 |   377K|   130   (1)| 00:00:01 |
---------------------------------------------------------------------------------
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------
------------------------------
Note
-----
   - automatic DOP: skipped because of IO calibrate statistics are missing
   - estimated index size: 2097K bytes
15 rows selected.


Method 2: 

SQL> variable u_byte number;
SQL> variable a_byte number;
SQL> exec dbms_space.create_index_cost( 'create index idx1_t on t(object_id)', :u_byte, :a_byte );
PL/SQL procedure successfully completed.

SQL> print :u_byte;
    U_BYTE
----------
    386165

SQL> print :a_byte;
    A_BYTE
----------
   2097152



As you can see , with the second method , the estimated size are not rounded . Being this is an estimate , this shouldn't matter.


Monday, August 22, 2011

Histograms Vs Extended Statistics

Oracle 11g introduced "extended statistics "  , by which we can create statistics on combination on columns  that you usually query with .  In theory , by generating extended statistics , optimizer  will generate better plan , with the correct selectivity .


Let us look at an example .


SQL> desc course_ext_stats
 Name                                      Null?    Type
 ----                                      -------  --------
 ID                                                 NUMBER
 COURSE_YEAR                               NOT NULL NUMBER
 COURSE_TERM                               NOT NULL NUMBER
 COURSE_NO                                 NOT NULL VARCHAR2(5)




SQL> exec dbms_stats.gather_table_stats(user , 'COURSE_EXT_STATS');
PL/SQL procedure successfully completed.


SQL> select column_name , num_distinct , density , sample_size , histogram from user_tab_col_statistics where table_name ='COURSE_EXT_STATS';

COLUMN_NAME                    NUM_DISTINCT    DENSITY SAMPLE_SIZE HISTOGRAM
------------------------------ ------------ ---------- ----------- ---------------
ID                                   432879 2.3101E-06      432879 NONE
COURSE_YEAR                              16      .0625      432879 NONE
COURSE_TERM                               4        .25      432879 NONE
COURSE_NO                             82656 .000012098      432879 NONE


SQL> set autotrace on
SQL> select * from course_ext_stats where course_year = 2011 and course_term = 5 ;

.....
....
....

3568 rows selected.

Execution Plan
----------------------------------------------------------
Plan hash value: 185418477

--------------------------------------------------------------------------------------
| Id  | Operation         | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |                  |  6764 |   118K|   390   (3)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| COURSE_EXT_STATS |  6764 |   118K|   390   (3)| 00:00:01 |
--------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("COURSE_YEAR"=2011 AND "COURSE_TERM"=5)

Note
-----
   - automatic DOP: skipped because of IO calibrate statistics are missing


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
       1615  consistent gets
          0  physical reads
          0  redo size
      77978  bytes sent via SQL*Net to client
       2971  bytes received via SQL*Net from client
        239  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
       3568  rows processed
 

By looking at the plan , the optimizer estimated 6764 rows , in fact ,  the query fetched only 3568 rows.       


Let us create extended statistics on these columns (  course_year and course_term ) .

SQL> Select  dbms_stats.create_extended_stats(user , 'COURSE_EXT_STATS' , '(COURSE_YEAR, COURSE_TERM)')  from dual ;

DBMS_STATS.CREATE_EXTENDED_STATS(USER,'COURSE_EXT_STATS','(COURSE_YEAR,COURSE_TERM)')
----------------------------------------------------------------------------------------------------------------------
SYS_STUNAZ4NUJOSOZ98MCGXG90RF7      

While  creating extended statistics , Oracle created another column as shown above.  The optimizer gives relatively better number.

SQL>  exec dbms_stats.gather_table_stats(user , 'COURSE_EXT_STATS' , method_opt=>'for all columns size 1' );
PL/SQL procedure successfully completed.

SQL>select * from course_ext_stats where course_year = 2011 and course_term = 5 ;
.....


--------------------------------------------------------------------------------------
| Id  | Operation         | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |                  |  3928 | 70704 |   390   (3)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| COURSE_EXT_STATS |  3928 | 70704 |   390   (3)| 00:00:01 |
--------------------------------------------------------------------------------------



Now , let us generate histograms up to 254 for all columns and see the output.

SQL> exec dbms_stats.delete_table_stats(user , 'COURSE_EXT_STATS');
PL/SQL procedure successfully completed.


SQL> exec dbms_stats.drop_extended_stats(user , 'COURSE_EXT_STATS' , '(COURSE_YEAR, COURSE_TERM)') ;
PL/SQL procedure successfully completed.

SQL> exec dbms_stats.gather_table_stats(user , 'COURSE_EXT_STATS' , method_opt=>'for all columns size 254' );
PL/SQL procedure successfully completed.


SQL> select column_name , num_distinct , density , sample_size , histogram , num_buckets from user_tab_col_statistics where table_name ='COURSE_EXT_STATS';

COLUMN_NAME                    NUM_DISTINCT    DENSITY SAMPLE_SIZE HISTOGRAM       NUM_BUCKETS
------------------------------ ------------ ---------- ----------- --------------- -----------
ID                                   432879 2.3186E-06        5480 HEIGHT BALANCED         254
COURSE_YEAR                              16 1.1593E-06        5480 FREQUENCY                16
COURSE_TERM                               4 1.1593E-06        5480 FREQUENCY                 4
COURSE_NO                             82656 .000026582        5480 HEIGHT BALANCED         254



Execution Plan
----------------------------------------------------------
Plan hash value: 185418477

--------------------------------------------------------------------------------------
| Id  | Operation         | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |                  |  3264 | 58752 |   390   (3)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| COURSE_EXT_STATS |  3264 | 58752 |   390   (3)| 00:00:01 |
--------------------------------------------------------------------------------------
 

Now , the optimizer estimated yet another number for expected rows.
So , which one  is better ?


I guess ,  the answer is "it depends" :-) 


Also , I would need to poke around a bit.