Home » RDBMS Server » Performance Tuning » Driving Table in Oracle 9i
Driving Table in Oracle 9i [message #170424] |
Wed, 03 May 2006 13:28 |
kumarsz
Messages: 180 Registered: March 2005 Location: canada
|
Senior Member |
|
|
Hi,
i am using "Oracle9i Enterprise Edition Release 9.0.1.1.1"
attached herewith is a file which has a query written with changing a table sequence and its Explain Plans.
i was assuming was that, if both tables are having indexes on joining column and if i am changing sequence of table in FROM clause the driving table shall go for FTS and inner table for index scan.
however in the results shown inspite of the fact that Dept table is using index "Table Access Full" is not understood by me.
also the Nested Loop position is changed.
Please guide me about this
Note : i have taken statistics (incl histograms) and ran the query 3-4 times for the Explain Plans.
Thanks in advance
Pratap
|
|
|
|
Re: Driving Table in Oracle 9i [message #170670 is a reply to message #170424] |
Thu, 04 May 2006 13:46 |
kumarsz
Messages: 180 Registered: March 2005 Location: canada
|
Senior Member |
|
|
Hi Mahesh,
now i have tried with following table structure and queries where i am getting suprising results
when index is only on 1 table FTS is occurring for 1 table.
when i create index on another table also (involved in join) both tables are FTS in the Explain plan
also driving table has no effect inspite of equal ranked index.
(Note :regarding optmizer_index_caching i will try today, but can you brief it here about it)
Please guide me on following result, i am trying to understand only a single join query plan for a long time, please help me understand it why it takes hash sometimes why sometimes Nested loop.
Microsoft Windows 2000 [Version 5.00.2195]
(C) Copyright 1985-2000 Microsoft Corp.
C:\>sqlplus
SQL*Plus: Release 9.0.1.0.1 - Production on Thu May 4 23:49:02 2006
(c) Copyright 2001 Oracle Corporation. All rights reserved.
Enter user-name: scott/[email]tiger@db02.world[/email]
Connected to:
Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.1.0 - Production
create table objects as select * from dba_objects;
create table objects1 as select * from dba_objects;
update objects1 set object_id = 17287 where rownum<150;
update objects1 set object_id = 7559 where rownum<150 and object_id <> 17287;
update objects1 set object_id = 22543 where rownum<150 and object_id <> 17287 and object_id <> 7559;
update objects1 set object_id = 13615 where rownum<150 and object_id <> 17287 and object_id <> 7559 and object_id <> 22543;
update objects1 set object_id = 10173 where object_id <> 17287 and object_id <> 7559 and object_id <> 22543 and object_id <> 13615;
commit;
alter table objects add constraint pk_objects primary key(object_id);
alter table objects1 add constraint fk_objects1 foreign key(object_id) references objects(object_id)
analyze tables / indexes comput statistics
******************************************
SQL> set autotrace traceonly
SQL> select o.object_name,o1.owner from objects o, objects1 o1 where o.object_id = o1.object_id;
30058 rows selected.
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 NESTED LOOPS
2 1 TABLE ACCESS (FULL) OF 'OBJECTS1'
3 1 TABLE ACCESS (BY INDEX ROWID) OF 'OBJECTS'
4 3 INDEX (UNIQUE SCAN) OF 'PK_OBJECTS' (UNIQUE)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
64515 consistent gets
0 physical reads
0 redo size
814299 bytes sent via SQL*Net to client
262888 bytes received via SQL*Net from client
2005 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
30058 rows processed
SQL> select o.object_name,o1.owner from objects o1, objects1 o where o.object_id = o1.object_id;
30058 rows selected.
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 NESTED LOOPS
2 1 TABLE ACCESS (FULL) OF 'OBJECTS1'
3 1 TABLE ACCESS (BY INDEX ROWID) OF 'OBJECTS'
4 3 INDEX (UNIQUE SCAN) OF 'PK_OBJECTS' (UNIQUE)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
64515 consistent gets
0 physical reads
0 redo size
1632112 bytes sent via SQL*Net to client
262888 bytes received via SQL*Net from client
2005 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
30058 rows processed
SQL> create index fk_objects1 on objects1(object_id);
Index created.
Analyze tables / indexes
SQL> select o.object_name,o1.owner from objects o, objects1 o1 where o.object_id = o1.object_id;
30058 rows selected.
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=185 Card=30058 Bytes
=3276322)
1 0 HASH JOIN (Cost=185 Card=30058 Bytes=3276322)
2 1 TABLE ACCESS (FULL) OF 'OBJECTS1' (Cost=43 Card=30058 By
tes=901740)
3 1 TABLE ACCESS (FULL) OF 'OBJECTS' (Cost=43 Card=30057 Byt
es=2374503)
Statistics
----------------------------------------------------------
42 recursive calls
2 db block gets
837 consistent gets
16 physical reads
0 redo size
814307 bytes sent via SQL*Net to client
262888 bytes received via SQL*Net from client
2005 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
30058 rows processed
SQL> select o.object_name,o1.owner from objects o1, objects1 o where o.object_id = o1.object_id;
30058 rows selected.
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=185 Card=30058 Bytes
=3276322)
1 0 HASH JOIN (Cost=185 Card=30058 Bytes=3276322)
2 1 TABLE ACCESS (FULL) OF 'OBJECTS' (Cost=43 Card=30057 Byt
es=901710)
3 1 TABLE ACCESS (FULL) OF 'OBJECTS1' (Cost=43 Card=30058 By
tes=2374582)
Statistics
----------------------------------------------------------
42 recursive calls
0 db block gets
2784 consistent gets
63 physical reads
0 redo size
1632112 bytes sent via SQL*Net to client
262888 bytes received via SQL*Net from client
2005 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
30058 rows processed
Thanks in Advance,
Pratap
[Updated on: Thu, 04 May 2006 16:20] by Moderator Report message to a moderator
|
|
|
Re: Driving Table in Oracle 9i [message #170708 is a reply to message #170670] |
Thu, 04 May 2006 20:06 |
|
Mahesh Rajendran
Messages: 10708 Registered: March 2002 Location: oracleDocoVille
|
Senior Member Account Moderator |
|
|
Talking about your testcase, CBO is doing exactly what needs to be done.
Once you add proper indexes and analyzed(statistics and histograms) both tables/indexes,
both the queries go for HASH JOIN as i said in earlier post.
Talking about Joins, there are basically 3 types.
Hash Joins,sort-merge and nested loops (which ***may***produce two different plans using unique scans or range scan)
I am taking the regular EMP/DEPT tables and tweaking them in this session.
As usual,proper statistics along with histograms are *****always**** very important.
In your case, i suspect whether you have collected any statistics at all (where it produces the nested loop),because i am not seeing any statistics!!.
Or You may have collected statistics but NO HISTOGRAMS, so the CBO might be hallucinating.
--
-- I am setting up my environment
-- Just regular emp/dept tables. I modified the deptno number(2) to deptno number
--
scott@9i > get emp_loopinsert
1 begin
2 for mag in 1..15 loop
3 insert into emp (select * from emp);
4 end loop;
5 commit;
6* end;
scott@9i > /
PL/SQL procedure successfully completed.
scott@9i > get dept_loopinsert
1 begin
2 for mag in 1..15 loop
3 insert into dept (select * from dept);
4 end loop;
5 commit;
6* end;
scott@9i > /
PL/SQL procedure successfully completed.
scott@9i > update dept set deptno=rownum;
131072 rows updated.
scott@9i > commit;
Commit complete.
scott@9i > alter table dept add constraint pk_deptno primary key (deptno);
Table altered.
--
-- What you might have done is
--
scott@9i > analyze table dept compute statistics for all columns for all indexes;
Table analyzed.
scott@9i > analyze table emp compute statistics for all columns for all indexes;
Table analyzed.
scott@9i > set autotrace traceonly exp;
scott@9i > select E.empno,D.dname from emp E, dept D where e.deptno=d.deptno;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 NESTED LOOPS
2 1 TABLE ACCESS (FULL) OF 'EMP'
3 1 TABLE ACCESS (BY INDEX ROWID) OF 'DEPT'
4 3 INDEX (UNIQUE SCAN) OF 'PK_DEPTNO' (UNIQUE)
--
-- Now let us create the second index, you were talking about.
-- Now, you can see the other nested loop plan that uses a RANGE SCAN.
--
1* create index index_deptno on emp(deptno)
scott@9i > /
Index created.
scott@9i > analyze table dept compute statistics for all columns for all indexes;
Table analyzed.
scott@9i > analyze table emp compute statistics for all columns for all indexes;
Table analyzed.
scott@9i > select E.empno,D.dname from emp E, dept D where e.deptno=d.deptno;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'EMP'
2 1 NESTED LOOPS
3 2 TABLE ACCESS (FULL) OF 'DEPT'
4 2 INDEX (RANGE SCAN) OF 'INDEX_DEPTNO' (NON-UNIQUE)
--
-- What you should have done is
--
scott@9i > get gather_table_stats
1* exec dbms_stats.gather_table_stats('SCOTT',upper('&TABLE_NAME'),METHOD_OPT=>'For all indexed columns size 250',CASCADE=>true);
scott@9i > @gather_table_stats
Enter value for table_name: EMP
PL/SQL procedure successfully completed.
scott@9i > @gather_table_stats
Enter value for table_name: DEPT
PL/SQL procedure successfully completed.
scott@9i > select E.empno,D.dname from emp E, dept D where e.deptno=d.deptno;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=801 Card=458752 Byte
s=9633792)
1 0 HASH JOIN (Cost=801 Card=458752 Bytes=9633792)
2 1 TABLE ACCESS (FULL) OF 'DEPT' (Cost=49 Card=131072 Bytes
=1835008)
3 1 TABLE ACCESS (FULL) OF 'EMP' (Cost=261 Card=458752 Bytes
=3211264)
/*
--
-- So with a Nested loop, for each row in the driving table you search an
-- equal value in the other table.
-- In Hash Join, you using the smaller table , hash it and probe the Bigger table.
-- You can see from the Card, DEPT is the smaller table that is hashed.
-- Let us cross-check that Card and play with the statistics see whether it holds true.
--
*/
scott@9i > set autotrace off;
scott@9i > select table_name,num_rows from user_tables where table_name in ('EMP','DEPT');
TABLE_NAME NUM_ROWS
------------------------------ ----------
DEPT 131072
EMP 458752
scott@9i > exec dbms_stats.set_table_stats('SCOTT','EMP',numrows=>100);
PL/SQL procedure successfully completed.
/*
-- let us trick the CBO. Now CBO thinks EMP has only 100 records.
-- When running the same query, driving table is changed.
*/
scott@9i > select table_name,num_rows from user_tables where table_name in ('EMP','DEPT');
TABLE_NAME NUM_ROWS
------------------------------ ----------
DEPT 131072
EMP 100
scott@9i > set autotrace traceonly exp
scott@9i > select E.empno,D.dname from emp E, dept D where e.deptno=d.deptno;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=312 Card=100 Bytes=2
100)
1 0 HASH JOIN (Cost=312 Card=100 Bytes=2100)
2 1 TABLE ACCESS (FULL) OF 'EMP' (Cost=261 Card=100 Bytes=70
0)
3 1 TABLE ACCESS (FULL) OF 'DEPT' (Cost=49 Card=131072 Bytes
/*
-- Now What is up with this SortMerge Join?
-- here Both the tables are sorted first and then Merged
-- This will typicall occurs when Both the involved tables are massively large
-- So let us tweak the stats again.
*/
scott@9i > @gather_table_stats
Enter value for table_name: EMP
PL/SQL procedure successfully completed.
scott@9i > @gather_table_stats
Enter value for table_name: dept
PL/SQL procedure successfully completed.
scott@9i > set autotrace off;
scott@9i > select table_name,num_rows from user_tables where table_name in ('DEPT','EMP');
TABLE_NAME NUM_ROWS
------------------------------ ----------
DEPT 131072
EMP 458752
scott@9i > exec dbms_stats.set_table_stats('SCOTT','DEPT',numrows=>100000000);
PL/SQL procedure successfully completed.
scott@9i > set autotrace traceonly exp
scott@9i > select E.empno,D.dname from emp E, dept D where e.deptno=d.deptno;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=3768 Card=350000000
Bytes=7350000000)
1 0 MERGE JOIN (Cost=3768 Card=350000000 Bytes=7350000000)
2 1 TABLE ACCESS (BY INDEX ROWID) OF 'DEPT' (Cost=726 Card=1
00000000 Bytes=1400000000)
3 2 INDEX (FULL SCAN) OF 'PK_DEPTNO' (UNIQUE) (Cost=274 Ca
rd=100000000)
4 1 SORT (JOIN) (Cost=3042 Card=458752 Bytes=3211264)
5 4 TABLE ACCESS (FULL) OF 'EMP' (Cost=261 Card=458752 Byt
es=3211264)
|
|
|
Re: Driving Table in Oracle 9i [message #170874 is a reply to message #170424] |
Fri, 05 May 2006 12:02 |
kumarsz
Messages: 180 Registered: March 2005 Location: canada
|
Senior Member |
|
|
Hi Mahesh,
Your analysis and further help is simply amazing!! no words for it.
attached herewith a file where i have taken EXPLAIN PLAN for queries on different server (this i have tried in my office) and got the exact results as you have described.
The Plans and reports (htm) are generated by some utility "(sql) scrubsheet in OEM" which is not available in Oracle OEM version i am using at home->(Oracle9i Enterprise Edition Release 9.0.1.1.1 - Production)
That utility also tells you which step is executed when, in the Explain Plan.
It may not be new to you, but i was stunned using that.(please have a look at the reports attached)
anyways,
with your guidence and some work on it, i got some idea of the three major joins but these joins "occur" according to the
method and frequency of statistics taken and structure of the database. So where does developer come in picture for tuning queries involving such joins? i mean when i will explicitly change join or try to tune it further?
Also
please suggest me on following query
which is better practice of writing query, considering statistics are taken properly (with histograms) and data distribution as with our normal emp ,dept tables
select e.ename,d.dname from emp e, dept d where e.deptno = d.deptno and d.deptno = 30;
OR
select e.ename,d.dname from emp e, dept d where d.deptno = 30 and e.deptno = d.deptno and
If in a join both tables have index (one may have unique and another non-unique) are they considred equal ranked? Will
driving table concept matters here?
If a table has sequnce generated primary key then still do we need histogram for it?
Please suggest.
Thanks in Advance
Pratap
|
|
|
|
Re: Driving Table in Oracle 9i [message #171073 is a reply to message #171070] |
Mon, 08 May 2006 04:38 |
kumarsz
Messages: 180 Registered: March 2005 Location: canada
|
Senior Member |
|
|
Hi Mahesh,
Thanks for your suggestions and advice,
However, can you give 2-3 examples where Developer is explicitly changing joins or forcing to change navigation (access path) of a query.
Now i have understood what joins are there and generally when they get used, but not sure when i will need to change its default behaviour.Please give examples and help me.
Thanks in Advance,
Pratap
Note : The feature in OEM, i am using is "SQL Scratchpad", Oracle version is - Oracle9i Enterprise Edition Release 9.2.0.7.0 - Production
you might have seen the report it generates ( i attached to this thread last time. Also each tells which step will occur at what sequence in Explain Plan)
|
|
|
|
|
|
|
Re: Driving Table in Oracle 9i [message #171369 is a reply to message #171329] |
Tue, 09 May 2006 10:03 |
kumarsz
Messages: 180 Registered: March 2005 Location: canada
|
Senior Member |
|
|
Hi mahesh,
sorry, i was not knowing, change of work is rest for you.
people like you always motivate me and other so many.
i hope i am not stretching this thread much.
however i have gone through the links you referred in this thread which made my undestanding better.
But what i was looking for is example where we are "explicitly" changing joins or/and filtering condition, after seeing the Explain not as required or optimist.
May be i will send individual queries with plans and statistics when i stuck up and with your suggestions on that will improve myself on Tuning.
Thanks
Pratap
|
|
|
|
|
Goto Forum:
Current Time: Sat Nov 23 15:30:30 CST 2024
|