oracle health check report last_call - oracle

************************
Long running sessions for LNLS12P_SB
************************
INST_ID SID SERIAL# SQL_ID USERNAME LOCKWAIT SCHEMANAME MACHINE LAST_CALL
------- ------- ------- ------------- ------------------------------ ---------------- --------------- --------------- -------------------------------------------------- ---------
1 166 56286 fxd3d1mf6qsg4 NPL_USER NPL_USER nycindapp4.us.db.com 398.57
1 848 57444 fxd3d1mf6qsg4 NPL_USER NPL_USER nycindapp4.us.db.com 408.53
1 273 15473 fxd3d1mf6qsg4 NPL_USER NPL_USER nycindapp3.us.db.com 418.53
1 844 58591 fxd3d1mf6qsg4 NPL_USER NPL_USER nycindapp3.us.db.com 428.58
1 139 45028 fxd3d1mf6qsg4 NPL_USER NPL_USER nycindapp3.us.db.com 512.73
1 718 18749 fxd3d1mf6qsg4 NPL_USER NPL_USER nycindapp3.us.db.com 522.75
I am troubleshooting a database performance issue. In the report I spot a few long running sessions. Not sure what last_call exactly stands for..

I would guess that the LAST_CALL column refers to V$SESSION.LAST_CALL_ET, which the 19c Database Reference describes as:
If the session STATUS is currently ACTIVE, then the value represents
the elapsed time (in seconds) since the session has become active.
If the session STATUS is currently INACTIVE, then the value represents
the elapsed time (in seconds) since the session has become inactive.
To know for sure, it would help if you specified exactly what Oracle health check you are using. If necessary, you could probably figure out how the health check is working by running this query while the health check results are being generated: select * from gv$sql where users_executing > 0;

Related

Weird results from oracle query with indexes and PreparedStatement

Recently, after upgrading our test env with a new version of application and introducing some new features I've stumbled upon some weird oracle behavior, which shows itself in query results that doesn't make sense and seem to be index dependant.
After doing some investigation I was able to create a minimal conditions to reproduce the issue.
I was experimenting on Oracle21 started in with docker:
docker run --restart always -d -p 1521:1521 -e ORACLE_PASSWORD=system --name oracle-21c-01 gvenzl/oracle-xe:21-slim
Then logging in as system user (system/system) I created another one with few permissions:
CREATE USER test PROFILE DEFAULT IDENTIFIED BY test ACCOUNT UNLOCK;
GRANT CONNECT TO test;
GRANT UNLIMITED TABLESPACE TO test;
GRANT CREATE TABLE TO test;
After that I logged in under this new user (test/test) and executed the following:
CREATE TABLE TEST_BUG
(
ID NUMBER(10) NOT NULL
CONSTRAINT PK_TEST_BUG PRIMARY KEY,
TENANT NUMBER(10) NOT NULL,
IDENTIFIER VARCHAR2(255) NOT NULL,
NAME VARCHAR2(255) NOT NULL
);
INSERT INTO TEST_BUG
VALUES (10, 1, 'IDENTIFIER', 'TESTBUG');
ALTER TABLE TEST_BUG
ADD CONSTRAINT UK_NAME_TENANT UNIQUE (NAME, TENANT);
ALTER TABLE TEST_BUG
ADD CONSTRAINT UK_IDENTIFIER_TENANT UNIQUE (IDENTIFIER, TENANT);
ALTER INDEX PK_TEST_BUG REBUILD;
As you can see here I'm just creating a very simple table with a couple of indexes, but the statements must be executed in this particular order (Also only with index rebuild on the last line I was able to reproduce the issue we're having on the actual environment, even though we do not do it anywhere in the update scripts).
With all that in mind, executing the following simle java code gives me weird results:
public class Main {
public static void main(String[] args) throws Exception {
Class.forName("oracle.jdbc.driver.OracleDriver");
try (Connection connection = DriverManager.getConnection("jdbc:oracle:thin:#localhost:1521:XE", "test", "test")) {
try (PreparedStatement preparedStatement = connection.prepareStatement(
"select id from test_bug where tenant = ? and name=? and id<>?"
)) {
preparedStatement.setInt(1, 1);
preparedStatement.setString(2, "TESTBUG");
preparedStatement.setInt(3, 10);
ResultSet resultSet = preparedStatement.executeQuery();
System.out.println(resultSet.next());
System.out.println(resultSet.getInt(1));
}
}
}
}
And results are:
true
10
Meaning that even though I've inserted a single record with id=10 and in the query asking specifically that id<>10, I still get that recoded as an output instead of getting nothing!
Couple more notes:
This only works with PreparedStatement, if I try to execute this query with sql developer - works just fine.
If I remove put id condition explicitly in query (like select id from test_bug where tenant = ? and name=? and id<>10) and remove preparedStatement.setInt(3, 10); - works also fine (no results)
If I disable PK index with ALTER INDEX PK_TEST_BUG UNUSABLE; - works also fine, no results, until I get index back with ALTER INDEX PK_TEST_BUG REBUILD;
For oracle driver I'm using here ojdbc11 21.9.0.0, but I've played with different versions - no difference.
Any ideas kindly appreciated!
This is an optimizer bug. If I run the java unchanged and do a SQL trace on it, you see the following the trace file
select id
from
test_bug where tenant = :1 and name=:2 and id != :3
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 1 0
Fetch 1 0.00 0.00 0 3 0 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 3 0.00 0.00 0 3 1 1
Misses in library cache during parse: 1
Misses in library cache during execute: 1
Optimizer mode: ALL_ROWS
Parsing user id: 109
Number of plan statistics captured: 1
Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ---------------------------------------------------
1 1 1 TABLE ACCESS BY INDEX ROWID BATCHED TEST_BUG (cr=3 pr=0 pw=0 time=32 us starts=1 cost=0 size=155 card=1)
1 1 1 BITMAP CONVERSION TO ROWIDS (cr=2 pr=0 pw=0 time=25 us starts=1)
1 1 1 BITMAP AND (cr=2 pr=0 pw=0 time=23 us starts=1)
1 1 1 BITMAP CONVERSION FROM ROWIDS (cr=1 pr=0 pw=0 time=9 us starts=1)
1 1 1 INDEX RANGE SCAN UK_NAME_TENANT (cr=1 pr=0 pw=0 time=8 us starts=1 cost=0 size=0 card=1)(object id 100690)
1 1 1 BITMAP CONVERSION FROM ROWIDS (cr=1 pr=0 pw=0 time=13 us starts=1)
1 1 1 SORT ORDER BY (cr=1 pr=0 pw=0 time=11 us starts=1)
1 1 1 INDEX RANGE SCAN PK_TEST_BUG (cr=1 pr=0 pw=0 time=3 us starts=1 cost=0 size=0 card=1)(object id 100689)
with the Fetch line Rows column of 1 meaning we found a row. If I disable that plan from use by changing the statement to:
con.prepareStatement("select /*+ full(t) */ id from test_bug t where tenant = ? and name=? and id != ?");
then with the altered plan, we get the result you expect
select /*+ full(t) */ id
from
test_bug t where tenant = :1 and name=:2 and id != :3
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 1 0
Fetch 1 0.00 0.00 0 7 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 3 0.00 0.00 0 7 1 0
Misses in library cache during parse: 1
Misses in library cache during execute: 1
Optimizer mode: ALL_ROWS
Parsing user id: 109
Number of plan statistics captured: 1
Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ---------------------------------------------------
0 0 0 TABLE ACCESS FULL TEST_BUG (cr=7 pr=0 pw=0 time=32 us starts=1 cost=3 size=155 card=1)
This is not to say that you should just put in a FULL hint and forget about it :-) but its worth logging an SR to see if that's an existing bug or if patches are available.
If you want a quick workaround, then:
select /*+ opt_param('_b_tree_bitmap_plans','false') */ id from test_bug where tenant = :b1 and name= :b2 and id<> :b3;
should take care of it.

in Oracle SQL-Trace: how can I group a set of SQL executions when the code is not instrumented?

I have an oracle-10046—aka. sqltrace—file similar to this structure:
Oracle Release 11.2
PARSING IN CURSOR #1 len=20 dep=0 uid=7 oct=6 lid=7 tim=2 hv=1 ad='1' sqlid='A'
insert
END OF STMT
PARSING IN CURSOR #2 len=20 dep=0 uid=7 oct=6 lid=7 tim=2 hv=2 ad='2' sqlid='r'
update next_step
END OF STMT
PARSING IN CURSOR #3 len=20 dep=0 uid=7 oct=6 lid=7 tim=2 hv=3 ad='3' sqlid='B'
update complete
END OF STMT
PARSING IN CURSOR #4 len=20 dep=0 uid=7 oct=3 lid=7 tim=2 hv=4 ad='4' sqlid='X'
select X
END OF STMT
PARSING IN CURSOR #5 len=20 dep=0 uid=7 oct=3 lid=7 tim=2 hv=5 ad='5' sqlid='Y'
select Y
END OF STMT
EXEC #1:c=1,e=1,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=100
EXEC #2:c=2,e=2,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=200
EXEC #3:c=4,e=4,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=300
EXEC #4:c=5,e=5,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=310
EXEC #5:c=6,e=6,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=320
EXEC #1:c=8,e=8,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=400
EXEC #2:c=16,e=16,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=416
EXEC #3:c=32,e=32,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=3,tim=448
I identified sqlid 'A' as the beginning of a specific sequence, and sqlid 'B' as it's end. In between there is only sqlid 'r' in my example, but it could be much more, even not the same SQLs or sequence of SQLs.
Other SQLs like sqlid 'X' and 'Y' are not within my sequence of interest and should be visible as such.
My tool of choice right now is mrskew from the Method R Tools product from methodr.
As it can be extended with Perl code, I'm sure this can be done, but my Perl skills are limited as my understanding of mrskew internals.
I highly appreciate any hint or help here.
Using your test data, martin1.trc, I created the rc file, martin1.rc.
--init='
my $xfrm_id;
sub xfrm {
$xfrm_id = $exec_id if ($sqlid//"") eq "A";
return $xfrm_id//$exec_id;
}
'
--group='xfrm()'
Then I executed mrskew --rc martin1.rc martin1.trc and I got this output:
'xfrm()' DURATION % CALLS MEAN MIN MAX
--------- -------- ------ ----- -------- -------- --------
25 0.000056 75.7% 3 0.000019 0.000008 0.000032
18 0.000018 24.3% 5 0.000004 0.000001 0.000006
--------- -------- ------ ----- -------- -------- --------
TOTAL (2) 0.000074 100.0% 8 0.000009 0.000001 0.000032
This report shows two executions of the interesting transaction. The most interesting (greatest response time) transaction execution began on trace file line 25 and contributed 0.000056 seconds (75.7% of the total) over 3 dbcalls to the total response time. The other most interesting execution began on line 18 and contributed the other 24.3% to the total. We know that lines 22-23 are uninteresting, but the simple method does not distinguish them. And that is why the report says the execution starting on line 18 has 5 dbcalls for 0.000018 seconds instead of 3 dbcalls for 0.000007 seconds.
If we significantly change the transformation function then we can handle the transaction ending at statement B (even if B is an EXEC followed by other B dbcalls (e.g., FETCH). Here is martin2.rc:
--init='
my $sawB;
my $xfrm_id;
sub xfrm {
if (($sqlid//"") eq "A") {
$xfrm_id = $exec_id; # global scope maintains state
} else {
if (($sqlid//"") eq "B") {
$sawB = 1;
} else {
if ($sawB) {
$sawB = undef;
$xfrm_id = undef;
}
}
}
return $xfrm_id//0;
}
'
--group='xfrm()'
In keeping with the notion of a profile (whereby the total represents the total for the whole experience), I decided to transform all non-interesting transaction dbcalls to 0 which is a line number that cannot appear in a file. This way you can see how the interesting transactions rank w.r.t. the whole experience.
$ mrskew --rc martin2.rc martin1.trc
'xfrm()' DURATION % CALLS MEAN MIN MAX
--------- -------- ------ ----- -------- -------- --------
25 0.000056 75.7% 3 0.000019 0.000008 0.000032
0 0.000011 14.9% 2 0.000005 0.000005 0.000006
18 0.000007 9.5% 3 0.000002 0.000001 0.000004
--------- -------- ------ ----- -------- -------- --------
TOTAL (3) 0.000074 100.0% 8 0.000009 0.000001 0.000032
If I duplicate line 20 (which takes 4 µsecs), then the output says this:
'xfrm()' DURATION % CALLS MEAN MIN MAX
--------- -------- ------ ----- -------- -------- --------
26 0.000056 71.8% 3 0.000019 0.000008 0.000032
18 0.000011 14.1% 4 0.000003 0.000001 0.000004
0 0.000011 14.1% 2 0.000005 0.000005 0.000006
--------- -------- ------ ----- -------- -------- --------
TOTAL (3) 0.000078 100.0% 9 0.000009 0.000001 0.000032
You can see that the interesting transaction starting on line 18 now contributes 11 µsecs over 4 dbcalls. This seems to be a more complete test confirming the appropriateness of martin2.rc.
In the last report, you can see that the interesting transaction represents 71.8%+14.1%=85.9% of the total response time in the file. If you further modify the transformation function (exercise left to the reader), then you can aggregate into "interesting" and "not interesting" rather than what I did, which was to add two percentages.

Oracle 11GR2 TKPROF - How to capture the recursive call-tree

Objective
Find out a way to visually capture the recursive call trees in the TKPROF output (SYS=YES specified).
Environment
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
Windows 7 64 bit on DELL Latitude core i7 2.8GHz 8G memory & SSD HDD
Background
I am tryng to understand the effect of indexing and the performance indications as in the question Oacle 11G - Performance effect of indexing at insert.
To further understand what is happening behind the scene for indexing, run a SQL trace on a create index statement.
Execution
Run trace on the index creation (SQL towards the bottom) and run tkprof with "sys=yes" option.
SQL> ALTER TABLE TBL2 ADD CONSTRAINT PK_TBL2_COL1 PRIMARY KEY(COL1) ;
Table altered.
Elapsed: 00:00:01.75
> trcsess clientid="CREATE_INDEX" output="report_createindex.trc" *.trc
> tkprof createindex.trc output=createindex.txt sys=yes
Question
I would like to know if there is a way to visucaly capture the call hierarchy like explain plan from the trace (.trc) file with tkprof or with other tools.
The generated report includes recursive calls such as "ALTER TABLE TBL2 ADD" inducing "INDEX BUILD UNIQUE", and probably further sys recursive calls down the path. I suppose the output does not reflect the call-hierarchy (parent first, childs following immediately after).
TKPROF OUTPUT
SQL ID: 2w9c2khpsfj4m
Plan Hash: 3219312727
CREATE UNIQUE INDEX "TRY"."PK_TBL2_COL1" on "TRY"."TBL2"("COL1") NOPARALLEL
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 1 0 0
Execute 1 0.63 0.84 2999 15565 3173 0
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 2 0.63 0.85 2999 15566 3173 0
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 106 (recursive depth: 1) <----------------- child?
Rows Row Source Operation
------- ---------------------------------------------------
1 INDEX BUILD UNIQUE PK_TBL2_COL1 (cr=15904 pr=3003 pw=2090 time=0 us)(object id 0)
1000000 SORT CREATE INDEX (cr=15486 pr=2997 pw=0 time=208370 us)
1000000 TABLE ACCESS FULL TBL2 (cr=15486 pr=2997 pw=0 time=245360 us cost=4413 size=5000000 card=1000000)
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
db file sequential read 575 0.00 0.08
db file scattered read 138 0.00 0.07
direct path write 1 0.00 0.00
********************************************************************************
SQL ID: 47f85g3cmftry
Plan Hash: 0
ALTER TABLE TBL2 ADD CONSTRAINT PK_TBL2_COL1 PRIMARY KEY(COL1)
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.20 0.64 15630 29477 3 0
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 2 0.20 0.64 15630 29477 3 0
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 106 <------------------------------------------ parent?
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
db file sequential read 4 0.00 0.00
db file scattered read 259 0.01 0.42
db file parallel read 2 0.00 0.00
SQL*Net message to client 1 0.00 0.00
SQL*Net message from client 1 0.00 0.00
********************************************************************************
SQL
CREATE TABLE TBL2 (
"COL1" NUMBER,
"COL2" VARCHAR2(100 BYTE)
-- CONSTRAINT "PK_TBL2_COL1" PRIMARY KEY ("COL1")
);
INSERT INTO TBL2 /*+ APPEND MONITOR GATHER_PLAN_STATISTICS CONNECTBY_INSERT */
SELECT LEVEL, rpad(TO_CHAR(LEVEL),100,'A') FROM DUAL CONNECT BY LEVEL <= 1000000
COMMIT;
---------------------------------------------------------------------------
-- Flush the buffers and clear the caches.
---------------------------------------------------------------------------
ALTER SYSTEM CHECKPOINT;
ALTER SYSTEM FLUSH SHARED_POOL;
ALTER SYSTEM FLUSH BUFFER_CACHE;
ALTER SYSTEM SWITCH LOGFILE;
---------------------------------------------------------------------------
-- Start monitoring
---------------------------------------------------------------------------
ALTER SESSION SET TRACEFILE_IDENTIFIER ='CREATE_INDEX';
ALTER SESSION SET TIMED_STATISTICS=true;
BEGIN
DBMS_SESSION.SET_IDENTIFIER('CREATE_INDEX');
DBMS_MONITOR.CLIENT_ID_TRACE_ENABLE('CREATE_INDEX', waits=>true, binds=>false);
DBMS_MONITOR.CLIENT_ID_STAT_ENABLE('CREATE_INDEX');
END;
/
---------------------------------------------------------------------------
-- Run the SQL to insert and monitor
---------------------------------------------------------------------------
SET PAGESIZE 200
SET LINESIZE 200
SET TIMING ON
SET ECHO ON
SET AUTOTRACE ON
ALTER TABLE TBL2 ADD CONSTRAINT PK_TBL2_COL1 PRIMARY KEY(COL1) ;
SET AUTOTRACE OFF
SET ECHO OFF
SET TIMING OFF
---------------------------------------------------------------------------
-- Stop monitoring.
---------------------------------------------------------------------------
BEGIN
DBMS_MONITOR.CLIENT_ID_TRACE_DISABLE('CREATE_INDEX');
DBMS_MONITOR.CLIENT_ID_STAT_DISABLE('CREATE_INDEX');
END;
/
References
Oracle 11GR2 document 21.4.4.5 Understanding Recursive Calls
Sometimes, to execute a SQL statement issued by a user, Oracle Database must issue additional statements. ... If recursive calls occur while the SQL Trace facility is enabled, then TKPROF produces statistics for the recursive SQL statements and marks them clearly as recursive SQL statements in the output file.
I recommend the traceanalyzer. You can download it from oracle support.
TRCANLZR (TRCA): SQL_TRACE/Event 10046 Trace File Analyzer - Tool for Interpreting Raw SQL Traces (Doc ID 224270.1)
The trace analyzer features a chapter "SQL Genealogy" which shows a tree like view of recursive SQL.
Once the traceanalyzer is installed, you invoke it with
#trcanlzr <name of tracefile>
You can even do this remotely from you client (copy the trcanlzr.sql script to your local SQLPATH). It will eventually copy the html-file containing the analysis to your client machine.
Based on the information from #Jan, run the TRCA. I understand that SQL Genealogy is the call hierarchy and breakdown, but please provide any suggestions/corrections.
SQL
SET AUTOTRACE OFF
SET ECHO ON
SET TIMING OFF
DROP TABLE TBL2 PURGE;
CREATE TABLE TBL2 (
"COL1" NUMBER,
"COL2" VARCHAR2(100 BYTE)
-- CONSTRAINT "PK_TBL2_COL1" PRIMARY KEY ("COL1")
);
INSERT INTO TBL2 /*+ APPEND MONITOR GATHER_PLAN_STATISTICS CONNECTBY_INSERT */
SELECT LEVEL, rpad(TO_CHAR(LEVEL),100,'A') FROM DUAL CONNECT BY LEVEL <= 1000000;
COMMIT;
---------------------------------------------------------------------------
-- Start monitoring
---------------------------------------------------------------------------
ALTER SESSION SET TRACEFILE_IDENTIFIER ='CREATE_INDEX';
ALTER SESSION SET TIMED_STATISTICS=TRUE;
alter session set events '10046 trace name context forever, level 8';
---------------------------------------------------------------------------
-- Run the SQL to insert and monitor
---------------------------------------------------------------------------
ALTER TABLE TBL2 ADD CONSTRAINT PK_TBL2_COL1 PRIMARY KEY(COL1) ;
---------------------------------------------------------------------------
-- Stop monitoring.
---------------------------------------------------------------------------
alter session set events '10046 trace name context off';
TRCA
#run/trcanlzr.sql nr_ora_6976_CREATE_INDEX.trc
TOP SQL (CPU)
SQL Genealogy
I use orasrp for analyze trace files. Its generate html-reports with hierarchy plans in easy to read form.
Also its easy to use (in console) -
orasrp in_trace.trc out_report.html

Monitor index usage

Is there a way to find if a a particular Oracle index was ever used by Oracle when executing a query?
We have a function based index, which I suspect is not getting used by Oracle and hence some queries are running slow. How could I find out if any query run against the database is using this query?
If the question is : if there are any queries that ever use the index?
ALTER INDEX myindex MONITORING USAGE;
Wait a few days/months/years:
SELECT *
FROM v$object_usage
WHERE index_name = 'MYINDEX';
http://docs.oracle.com/cd/B28359_01/server.111/b28310/indexes004.htm#i1006905
If you're using some sort of IDE (e.g. Oracle's SQL Developer, PL/SQL Developer from Allround Automations, Toad, etc) each one of them has some way to dump the plan for a statement - poke around in the menus and the on-line help.
If you can get into SQL*Plus (try typing "sql" at your friendly command line) you can turn autotrace on, execute your statement, and the plan should be printed. As in
SQL> set autotrace on
SQL> select * from dept where deptno = 40;
DEPTNO DNAME LOC
---------- -------------- -------------
40 OPERATIONS BOSTON
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=1 Card=1 Bytes=18)
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'DEPT' (Cost=1 Card=1 Bytes=18)
2 1 INDEX (UNIQUE SCAN) OF 'PK_DEPT' (UNIQUE)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
499 bytes sent via SQL*Net to client
503 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
This assumes that your friendly neighborhood DBA has performed the necessary incantations to enable this feature. If this hasn't been done, or you just want One More Way (tm) to do this, try something like the following, substituting the query you care about:
SQL> EXPLAIN PLAN FOR select * from dept where deptno = 40;
Explained.
SQL> set linesize 132
SQL> SELECT * FROM TABLE( dbms_xplan.display);
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------
Plan hash value: 2852011669
---------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 20 | 1 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 | 20 | 1 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | PK_DEPT | 1 | | 0 (0)| 00:00:01 |
---------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("DEPTNO"=40)
14 rows selected.
Share and enjoy.

Table not doing index scan

Hey guy so some reason my table is doing index fast full scan.
here is my query
SELECT bo.bid,cu.cid
FROM ass2master_booking bo, ass2master_customer cu
WHERE bo.cid = cu.cid
and rownum < 135000;
here is the trace file
SELECT bo.bid,cu.cid
FROM ass2master_booking bo, ass2master_customer cu
WHERE bo.cid = cu.cid
and rownum < 135000
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 2 0.00 0.00 0 0 0 0
Fetch 9001 0.19 0.41 387 2131 0 134999
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 9004 0.19 0.41 387 2131 0 134999
Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 5594
Rows Row Source Operation
------- ---------------------------------------------------
134999 COUNT STOPKEY (cr=2131 pr=387 pw=189 time=411804 us)
134999 HASH JOIN (cr=2131 pr=387 pw=189 time=276737 us)
150000 INDEX FAST FULL SCAN CUSTOMER_CID_IDX (cr=320 pr=315 pw=0 time=263 us)(object id 332052)
7412 TABLE ACCESS FULL ASS2MASTER_BOOKING (cr=1811 pr=44 pw=0 time=7566 us)
basically i was told to add structure to unstructred data i was given 2 tables with 150,000 rows and determ which of the following structures were the best.
non clustered index
clustered index
hash clustered
unstructured data.
And the query i chose to do the testing with is given above.
You are selecting a large part of both tables, so index access doesn't makes sense. (at least oracle thinks that)
It uses Index Fast Full Scan instead of Table Access Full because because it finds everything it needs (cu.cid) in the index and doesn't need the table.
I have no idea what you mean with
non clustered index clustered index hash clustered unstructured data.
Update:
I think a rule of thumb I use:
If you need more then 20% of a table I expect a full table scan.
If you need less then 5% of a table I expect some kind of index access.
One of the first things I do when tuning SQL statement is to look in the execution plan and check the number of rows oracle expects to get back from each step. If those numbers are completely wrong, the execution plan is probably pretty bad.

Resources