Tuesday 26 May 2015

Obtaining Execution Plan in Oracle


Obtaining Execution Plan in Oracle
What is execution plan?
An execution plan describes the list of operations which are performed by SQL Engine for SQL statement. The order of operations and their implementation is decided by the oracle query optimizer. An execution plan also shows the estimated number of rows, cost require to perform the operation, how many bytes oracle will read the data and estimated time required for the operations.
Sample Execution Plan:





1. Access Method & Join type of data access.
2. Name of the objects on which operation is going to perform.
3. Cardinality: Estimated number of rows.
4. Bytes: How much byte of data needs to process for each operation.
5. Cost: Cost require to perform operation.
6. Time: Estimated time require to complete the operation.
Displaying Execution plan:
Below are the two mostly used methods to display an execution plan.
1.      EXPLAIN PLAN command: This displays an execution plan for SQL statement without actually executing it.
2.      V$SQL_PLAN: This dynamic performance view shows execution plan for statement that has been compiled into cursor and stored in the cursor cache.
 DBMS_XPLAN Package: This package provides the different PL/SQL interfaces to display the plan from different sources.
  • Obtaining Execution Plan from EXPLAIN PLAN Command and DBMS_XPLAN.DISPLAY function:
Below example shows how to use EXLAIN_PLAN command and DBMS_XPLAN.DISPLAY function to display the plan.
SQL> explain plan for select * from test1 a,test2 b where a.emp_no=b.emp_no;
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 497311279

----------------------------------------------------------------------------
| Id  | Operation          | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |       |     1 |    40 |     5  (20)| 00:00:01 |
|*  1 |  HASH JOIN         |       |     1 |    40 |     5  (20)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| TEST1 |     1 |    20 |     2   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| TEST2 |     1 |    20 |     2   (0)| 00:00:01 |
----------------------------------------------------------------------------


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

   1 - access("A"."EMP_NO"="B"."EMP_NO")

Note
-----
   - dynamic sampling used for this statement (level=2)

19 rows selected.
  • Obtaining Plan from DBMS_XPLAN.DISPLAY_CURSOR function:
Execution plan for executed statement can be displayed by using DBMS_XPLAN.DISPLAY_CURSOR function. It takes input as SQL_ID of the statement.

SQL> select * from table(dbms_xplan.display_cursor('0kkhhb2w93cx0'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  0kkhhb2w93cx0, child number 0
-------------------------------------
update seg$ set type#=:4,blocks=:5,extents=:6,minexts=:7,maxexts=:8,exts
ize=:9,extpct=:10,user#=:11,iniexts=:12,lists=decode(:13, 65535, NULL,
:13),groups=decode(:14, 65535, NULL, :14), cachehint=:15, hwmincr=:16,
spare1=DECODE(:17,0,NULL,:17),scanhint=:18, bitmapranges=:19 where
ts#=:1 and file#=:2 and block#=:3

Plan hash value: 2170058777
 ----------------------------------------------------------------------------------------

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation             | Name           | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | UPDATE STATEMENT      |                |       |       |     3 (100)|          |
|   1 |  UPDATE               | SEG$           |       |       |            |          |
|   2 |   TABLE ACCESS CLUSTER| SEG$           |     1 |    72 |     3   (0)| 00:00:01 |
|*  3 |    INDEX UNIQUE SCAN  | I_FILE#_BLOCK# |     1 |       |     2   (0)| 00:00:01 |
----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   3 - access("TS#"=:1 AND "FILE#"=:2 AND "BLOCK#"=:3)
  • Obtaining History Plan from DBMS_XPLAN.DISPLAY_AWR function
Sometimes you will not get plan from DISPLAY_CURSOR function as it might have flushed from the cursor cache. In this case we can obtain the plan using DISPLAY_AWR function. This function gives us all the execution plans that the statement had used in the past. It takes input as SQL_ID of the statement.

SQL> select * from table(dbms_xplan.display_awr('0kkhhb2w93cx0'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID 0kkhhb2w93cx0
--------------------
update seg$ set type#=:4,blocks=:5,extents=:6,minexts=:7,maxexts=:8,exts
ize=:9,extpct=:10,user#=:11,iniexts=:12,lists=decode(:13, 65535, NULL,
:13),groups=decode(:14, 65535, NULL, :14), cachehint=:15, hwmincr=:16,
spare1=DECODE(:17,0,NULL,:17),scanhint=:18, bitmapranges=:19 where
ts#=:1 and file#=:2 and block#=:3

Plan hash value: 2170058777
----------------------------------------------------------------------------------------
 PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation             | Name           | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | UPDATE STATEMENT      |                |       |       |     2 (100)|          |
|   1 |  UPDATE               | SEG$           |       |       |            |          |
|   2 |   TABLE ACCESS CLUSTER| SEG$           |     1 |    71 |     2   (0)| 00:00:01 |
|   3 |    INDEX UNIQUE SCAN  | I_FILE#_BLOCK# |     1 |       |     1   (0)| 00:00:01 |
----------------------------------------------------------------------------------------

19 rows selected.
Conclusion: In this article we have seen the methods to obtain an execution plan from the cursor cache as well as from AWR. I will write an article on interpreting these execution plans very soon.

Thursday 30 April 2015

How to lock/unlock statistics on a table

In certain cases you may want to lock statistics in a table in certain cases, for example if you want a table not be analyzed by automatic statistics job but analyze it later or in cases where you want prevent from analyzing statistics in cases where data in the table doesn’t change.
The following example shows how to lock table statistics and what happens when one tries to gather statistics on table that has statistics locked.

STEP 1: Create Table for test

SQL> create table test ( x number );

Table created.

STEP2: Create index on table.

SQL> create index test_idx on test(x);

Index created.

STEP3: Check stats are not locked on table.

When stats is not locked the value of stattype_locked is NULL

SQL> SELECT stattype_locked FROM dba_tab_statistics WHERE table_name = 'TEST' and owner = 'SCOTT';

STATT
—–


STEP4: Lock the statistics

SQL> exec dbms_stats.lock_table_stats('scott', 'test');

PL/SQL procedure successfully completed.

STEP5: Now check stats are locked status

When stats is locked the value of stattype_locked is ALL

SQL> SELECT stattype_locked FROM dba_tab_statistics WHERE table_name = 'TEST' and owner = 'SCOTT';

STATT
—–
ALL


STEP 6: Try to gather statistics on locked table and index


SQL> exec dbms_stats.gather_index_stats('scott', 'test_idx');

BEGIN dbms_stats.gather_index_stats('scott', 'test_idx'); END;
*
ERROR at line 1:
ORA-20005: object statistics are locked (stattype = ALL)
ORA-06512: at “SYS.DBMS_STATS”, line 10640
ORA-06512: at “SYS.DBMS_STATS”, line 10664
ORA-06512: at line 1


SQL> analyze index ajaffer.test_idx compute statistics;

analyze index ajaffer.test_idx compute statistics
*
ERROR at line 1:
ORA-38029: object statistics are locked


STEP7: Unlock the statistics

SQL> exec dbms_stats.unlock_table_stats('scott', 'test');

PL/SQL procedure successfully completed.










I hope this article helped you. Your suggestions/feedback are most welcome.

Keep learning... Have a great day!!!



Tuesday 28 April 2015

Restore the database from tape backup of the Database

Suppose the entire server is lost, 
we have the  tape copy of the backup of the database , which includes RMAN backup pieces and control file backup
Assuming that were the case, we would have to rebuild the entire server, reinstall the OS and the Oracle Software, then restore the backup of the database from tape. . If the Archives and online redo are lost, the recovered database will not include all transactions,
but it will be current up to the last backup.

Steps Required
1.copy the tape backup of the database to disk
2.create the init.ora file
3.create the password file
 4.start the instance in nomount
5.restore the spfile from autobackup spfile backup piece
6.shutdown immediate
7.startup nomount
 8.RESTORE CONTROLFILE FROM AUTOBACKUP;
9.alter database mount;
10.catalog all the backup piece into RMAN
11.restore database
12.recover database;
13.alter database open resetlogs;
14. check the status of listener and if any connection issues then workout and fix the problem

Detailed Description of Steps
Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

[oracle@localhost Stasdb_database]$ . oraenv
ORACLE_SID = [statsdb] ?
The Oracle base for ORACLE_HOME=/u01/app/oracle/product/11.2.0/dbhome_1 is /u01/app/oracle

[oracle@localhost Stasdb_database]$ rman
Recovery Manager: Release 11.2.0.1.0 - Production on Wed Jun 13 15:49:57 2012
Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.

RMAN> connect target /
connected to target database (not started)

RMAN> startup nomount
Oracle instance started
Total System Global Area     893562880 bytes
Fixed Size                     2218512 bytes
Variable Size                243271152 bytes
Database Buffers             641728512 bytes
Redo Buffers                   6344704 bytes

RMAN> RESTORE SPFILE FROM '/u02/app/Stasdb_database/c-782188580-20120613-02';
Starting restore at 13-JUN-12
using target database control file instead of recovery catalog
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=19 device type=DISK
channel ORA_DISK_1: restoring spfile from AUTOBACKUP /u02/app/Stasdb_database/c-782188580-20120613-02
channel ORA_DISK_1: SPFILE restore from AUTOBACKUP complete
Finished restore at 13-JUN-12

RMAN> shutdown immediate;
Oracle instance shut down

RMAN> startup nomount;

connected to target database (not started)
Oracle instance started
Total System Global Area     893562880 bytes
Fixed Size                     2218512 bytes
Variable Size                243271152 bytes
Database Buffers             641728512 bytes
Redo Buffers                   6344704 bytes

RMAN> RESTORE CONTROLFILE FROM '/u02/app/Stasdb_database/c-782188580-20120613-02';
Starting restore at 13-JUN-12
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=17 device type=DISK
channel ORA_DISK_1: restoring control file
channel ORA_DISK_1: restore complete, elapsed time: 00:00:01
output file name=/u01/app/statsdb/control01.ctl
output file name=/u01/app/oracle/flash_recovery_area/statsdb/control02.ctl
Finished restore at 13-JUN-12

RMAN> alter database mount;
database mounted
released channel: ORA_DISK_1

RMAN> catalog start with '/u01/app/oracle/flash_recovery_area/statsdb';
Starting implicit crosscheck backup at 13-JUN-12
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=17 device type=DISK
Crosschecked 100 objects
Finished implicit crosscheck backup at 13-JUN-12
Starting implicit crosscheck copy at 13-JUN-12
using channel ORA_DISK_1
Finished implicit crosscheck copy at 13-JUN-12
searching for all files in the recovery area
cataloging files...
no files cataloged
searching for all files that match the pattern /u01/app/oracle/flash_recovery_area/statsdb
List of Files Unknown to the Database
=====================================
File Name: /u01/app/oracle/flash_recovery_area/statsdb/hhndeia8_1_1
File Name: /u01/app/oracle/flash_recovery_area/statsdb/hindeimj_1_1
File Name: /u01/app/oracle/flash_recovery_area/statsdb/hgndeia5_1_1
Do you really want to catalog the above files (enter YES or NO)? YES
cataloging files...
cataloging done
List of Cataloged Files
=======================
File Name: /u01/app/oracle/flash_recovery_area/statsdb/hhndeia8_1_1
File Name: /u01/app/oracle/flash_recovery_area/statsdb/hindeimj_1_1
File Name: /u01/app/oracle/flash_recovery_area/statsdb/hgndeia5_1_1

RMAN> restore database;
Starting restore at 13-JUN-12
using channel ORA_DISK_1
channel ORA_DISK_1: starting datafile backup set restore
channel ORA_DISK_1: specifying datafile(s) to restore from backup set
channel ORA_DISK_1: restoring datafile 00001 to /u01/app/oracle/oradata/statsdb/system01.dbf
channel ORA_DISK_1: restoring datafile 00002 to /u01/app/oracle/oradata/statsdb/sysaux01.dbf
channel ORA_DISK_1: restoring datafile 00003 to /u01/app/oracle/oradata/statsdb/undotbs01.dbf
channel ORA_DISK_1: restoring datafile 00004 to /u01/app/oracle/oradata/statsdb/users01.dbf
channel ORA_DISK_1: restoring datafile 00005 to /u01/app/oracle/oradata/statsdb/example01.dbf
channel ORA_DISK_1: restoring datafile 00006 to /u01/app/oracle/oradata/statsdb/tripointmonitor01.dbf
channel ORA_DISK_1: reading from backup piece /u01/app/oracle/flash_recovery_area/statsdb/hhndeia8_1_1
channel ORA_DISK_1: piece handle=/u01/app/oracle/flash_recovery_area/statsdb/hhndeia8_1_1 tag=TAG20120613T144216
channel ORA_DISK_1: restored backup piece 1
channel ORA_DISK_1: restore complete, elapsed time: 00:05:56
Finished restore at 13-JUN-12

RMAN> recover database;
Starting recover at 13-JUN-12
using channel ORA_DISK_1
starting media recovery
channel ORA_DISK_1: starting archived log restore to default destination
channel ORA_DISK_1: restoring archived log
archived log thread=1 sequence=2345
channel ORA_DISK_1: reading from backup piece /u01/app/oracle/flash_recovery_area/statsdb/hindeimj_1_1
channel ORA_DISK_1: piece handle=/u01/app/oracle/flash_recovery_area/statsdb/hindeimj_1_1 tag=TAG20120613T144851
channel ORA_DISK_1: restored backup piece 1
channel ORA_DISK_1: restore complete, elapsed time: 00:00:01
archived log file name=/u01/app/oracle/flash_recovery_area/STATSDB/archivelog/2012_06_13/o1_mf_1_2345_7xl72djp_.arc thread=1 sequence=2345
channel default: deleting archived log(s)
archived log file name=/u01/app/oracle/flash_recovery_area/STATSDB/archivelog/2012_06_13/o1_mf_1_2345_7xl72djp_.arc RECID=1851 STAMP=785865820
unable to find archived log
archived log thread=1 sequence=2346
RMAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-03002: failure of recover command at 06/13/2012 16:03:42
RMAN-06054: media recovery requesting unknown archived log for thread 1 with sequence 2346 and starting SCN of 92188455

RMAN> alter database open resetlogs;
database opened

RMAN>
Your database is ready to use.




I hope this article helped you. Your suggestions/feedback are most welcome.

Keep learning... Have a great day!!!