Table Access Path
Hi,
I am using oracle 10g on windowz xp. I am giving below query :
SQL> ED
Wrote file afiedt.buf
1 SELECT GRANTEE,PRIVILEGE,GRANTABLE FROM DBA_TAB_PRIVS
2 WHERE
3 OWNER='SCOTT' AND
4* TABLE_NAME='EMP'
SQL> /
GRANTEE PRIVILEGE GRA
HR SELECT YES
TEST SELECT NO
TESTROLE SELECT NO
TESTROLE UPDATE NO
SQL>But i need output in below manner :
GRANTEE PRIVILEGE GRA
HR (DIRECT) SELECT YES
TEST (DIRECT) SELECT NO
TEST (THROUGH-->TESTROLE) SELECT NO
ABC (THROUGH-->TESTROLE) UPDATE NOI mean how do i know that which user is having which privilege on scott.emp through direct access or through a role. If user is having direct privilege it should be (USERNAME (DIRECT)) in GRANTEE column else (USERNAME (THROUGH-->ROLENAME).
Thanks in advance.
Hello Anuragji,
Yes, your query is taking care of it, but i have a little question (basic) :
SQL> select t.grantee, null Through, t.privilege, t.grantable
2 from dba_tab_privs t
3 where t.grantee in (select username from dba_users) and owner = 'SCOTT' and table_name = 'EMP'
4 union all
5 select r.grantee, tr.grantee Through, tr.privilege, tr.grantable
6 from dba_tab_privs tr, dba_role_privs r
7 where r.granted_role=tr.grantee and owner = 'SCOTT' and table_name = 'EMP';
GRANTEE THROUGH PRIVILEGE GRA
HR SELECT YES
TEST SELECT NO
SYS TESTROLE SELECT NO
HR TESTROLE SELECT NO
SYS TESTROLE UPDATE NO
HR TESTROLE UPDATE NO
6 rows selected.
SQL> show user;
USER is "SYS"
SQL> delete from scott.emp;
15 rows deleted.
SQL> rollback;
Rollback complete.My question is if sys is not having delete privilege on scott.emp as output shown above, then how 15 rows deleted?
Thank you again for your replies.
Similar Messages
-
How improve performance on access path TABLE ACCESS BY INDEX ROWID ?
I have table MOVEMENT with about 26millions entries,
select rowid from movement xxx
where
xxx.sTransType > 0
AND xxx.sDevice < 1000
AND xxx.sDevice >= 0
AND (bitand(xxx.sSaleFlag,1) = 0 AND bitand(xxx.sSaleFlag,4) = 0)
AND xxx.sArtClassRef < 100
and xxx.tActionTime BETWEEN TO_DATE('13-05-2011 08:08:34', 'dd-mm-yyyy hh24:mi:ss') AND to_date('13-05-2011 14:08:34', 'dd-mm-yyyy hh24:mi:ss') ;
PLAN_TABLE_OUTPUT
Plan hash value: 679628763
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 34 | 10102 (1)| 00:02:02 |
|* 1 | TABLE ACCESS BY INDEX ROWID| MOVEMENT | 1 | 34 | 10102 (1)| 00:02:02 |
|* 2 | INDEX RANGE SCAN | MOVATIME_IX | 18489 | | 51 (0)| 00:00:01 |
Predicate Information (identified by operation id):
1 - filter("XXX"."SARTCLASSREF"<100 AND BITAND("XXX"."SSALEFLAG",1)=0 AND
BITAND("XXX"."SSALEFLAG",4)=0 AND "XXX"."STRANSTYPE">0 AND "XXX"."SDEVICE"<1000
AND "XXX"."SDEVICE">=0)
2 - access("XXX"."TACTIONTIME">=TO_DATE('2011-05-13 08:08:34', 'yyyy-mm-dd
hh24:mi:ss') AND "XXX"."TACTIONTIME"<=TO_DATE('2011-05-13 14:08:34', 'yyyy-mm-dd
hh24:mi:ss'))
there is index on tActionTime - MOVATIME_IX
This query returns 12203 rows, so I would anticipate this number in plan table in row with id 1 and column Rows
Final question if it is possible to optimize this query and what are the next steps to do it?
Thanks.>
I thought that access path via ROWID's is the fastest way to get row
>
It is the fastest way to get the row - FROM THE TABLE.
But the ROWIDs have to be gotten from the index. That is what the INDEX RANGE SCAN is doing. It is getting the ROWIDs needed and then the TABLE ACCESS BY INDEX ROWID is getting the rows.
>
I'am still confused with COST values, TABLE ACCESS BY INDEX ROWID has 200times higher cost than INDEX RANGE SCAN,
>
The index entries for a range scan are in order so they are very compact. The actual rows might be all over the place.
Have you ever you a library? Not the online ones - I mean the old-fashioned kind that actually has books printed on paper?
If the librarian asks you, her helper, to go get all books whose title begins with the letter 'B' how would you do it?
You could go back to the stacks and look at every book on every shelf for books with titles' starting with 'B'. That is the same as a FULL TABLE SCAN.
Or you could go to the card catalog, pull out the drawer (or drawers) that has 'B' on the label and look at the information on the card. Part of that information is the location of the actual book: section, stack; that is similar to the ROWID.
The card catalog might get you to the right stack of books; then you have to search the stack sequentially to look for the book by name.
A ROWID will get Oracle to the right block but then it has to find the right row.
So the cost of getting ROWIDs from an index using a RANGE SCAN (where values are scanned in order) is a lot cheaper than actually getting the rows. The first two index entries needed might be right next to each other in order but the rows themselves might be far apart on the disk. -
Index not being used in access path
Hi,
I have been trying to rewrite a query which currently is taking almost 1min and 25 secs to execute. The database version is 11.1.0.7.
The query is -
SELECT COUNT(1)
FROM TAB1 p
WHERE p.ACODE = 24377
AND NOT EXISTS (SELECT 1 FROM TAB2 ph where ph.PKey = p.AKey )
AND NOT EXISTS (SELECT 1 FROM TAB3 phs where phs.PKey = p.AKey )
AND p.rflag = 'Y';
The table originally didn't have an index on p.ACODE. So, I created this index and set it to visible and set the optimizer_use_invisible_indexes parameter also to TRUE. I set the monitoring on this index too. Even though I have created the index on the ACODE column, the access path doesn't use it. Can someone please tell me why this is not being used.
Below is the explain plan for the sql stmt and the usage of the index -
I have changed the actual table and column names -
SQL> SELECT COUNT(1)
2 FROM TAB1 p
3 WHERE p.ACODE = 24377
4 AND NOT EXISTS (SELECT 1 FROM TAB2 ph where ph.PKey = p.AKey )
5 AND NOT EXISTS (SELECT 1 FROM TAB3 phs where phs.PKey = p.AKey )
6 AND p.rflag = 'Y';
COUNT(1)
1
SQL> explain plan for
2 SELECT COUNT(1)
3 FROM TAB1 p
4 WHERE p.ACODE = 24377
5 AND NOT EXISTS (SELECT 1 FROM TAB2 ph where ph.PKey = p.AKey )
6 AND NOT EXISTS (SELECT 1 FROM TAB3 phs where phs.PKey = p.AKey )
7 AND p.rflag = 'Y';
Explained.
Elapsed: 00:00:00.02
SQL> @$ORACLE_HOME/rdbms/admin/utlxpls.sql
PLAN_TABLE_OUTPUT
Plan hash value: 3942424611
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 87 | 214K (2)| 00:42:57 |
| 1 | SORT AGGREGATE | | 1 | 87 | | |
|* 2 | HASH JOIN ANTI | | 1 | 87 | 214K (2)| 00:42:57 |
|* 3 | HASH JOIN ANTI | | 1 | 60 | 209K (2)| 00:41:56 |
|* 4 | TABLE ACCESS FULL | TAB1 | 1 | 32 | 209K (2)| 00:41:55 |
| 5 | INDEX FAST FULL SCAN| PK_TAB3 | 29918 | 818K| 53 (0)| 00:00:01 |
| 6 | INDEX FAST FULL SCAN | PK_TAB2 | 3199K| 82M| 5059 (1)| 00:01:01 |
Predicate Information (identified by operation id):
2 - access("PH"."PKey"="P"."AKey")
3 - access("PHS"."PKey"="P"."AKey")
4 - filter(TO_NUMBER("P"."ACODE")=24377 AND "P"."rflag"='Y')
20 rows selected.
Elapsed: 00:00:00.03
SQL> select index_name,VISIBILITY from user_indexes where index_name='IDX_TAB1_ACODE';
INDEX_NAME VISIBILIT
IDX_TAB1_ACODE VISIBLE
Elapsed: 00:00:00.01
SQL> show parameter visible
NAME TYPE VALUE
optimizer_use_invisible_indexes boolean TRUE
SQL>
SQL> SELECT v.index_name, v.table_name,
v.monitoring, v.used,
start_monitoring, end_monitoring
FROM v$object_usage v, dba_indexes u
WHERE v.index_name = u.index_name
AND v.index_name = 'IDX_TAB1_ACODE';
INDEX_NAME TABLE_NAME MON USE START_MONITORING END_MONITORING
IDX_TAB1_ACODE TAB1 YES NO 05/26/2010 14:13:41
Elapsed: 00:00:00.10
Edited by: user12158503 on May 26, 2010 1:24 PMThanks Centinul.
I apologize for posting in both sections. I put it in the Database General too because I thought I originally posted it in the wrong section.
The index was not being used because it was doing the implicit type conversion. When I enclosed it in quotes, it returns the result within a second and it uses the index.(whereas without the index it takes around 1min 25 sec)
Here is the explain plan and execution time after enclosing it in quotes -
SQL> explain plan for
2 SELECT COUNT(1)
3 FROM TAB1 p
4 WHERE p.AKey = '24377'
5 AND NOT EXISTS (SELECT 1 FROM TAB2 ph where ph.PKey = p.AgilityKey )
6 AND NOT EXISTS (SELECT 1 FROM TAB3 phs where phs.PKey = p.AgilityKey )
7 AND p.rflag = 'Y';
Explained.
Elapsed: 00:00:00.02
SQL> @$ORACLE_HOME/rdbms/admin/utlxpls.sql
PLAN_TABLE_OUTPUT
Plan hash value: 2008452282
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 87 | 5134 (1)| 00:01:02 |
| 1 | SORT AGGREGATE | | 1 | 87 | | |
|* 2 | HASH JOIN ANTI | | 1 | 87 | 5134 (1)| 00:01:02 |
|* 3 | HASH JOIN ANTI | | 1 | 60 | 60 (2)| 00:00:01 |
|* 4 | TABLE ACCESS BY INDEX ROWID| TAB1 | 1 | 32 | 6 (0)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | IDX_TAB1_AKey | 4 | | 1 (0)| 00:00:01 |
| 6 | INDEX FAST FULL SCAN | PK_TAB3 | 29918 | 818K| 53 (0)| 00:00:01 |
| 7 | INDEX FAST FULL SCAN | PK_TAB2 | 3199K| 82M| 5059 (1)| 00:01:01 |
Predicate Information (identified by operation id):
2 - access("PH"."PKey"="P"."AGILITYKEY")
3 - access("PHS"."PKey"="P"."AGILITYKEY")
4 - filter("P"."rflag"='Y')
5 - access("P"."AKey"='24377')
22 rows selected.
Elapsed: 00:00:00.02
SQL> SELECT COUNT(1)
2 FROM TAB1 p
3 WHERE p.AKey = '24377'
4 AND NOT EXISTS (SELECT 1 FROM TAB2 ph where ph.PKey = p.AgilityKey )
5 AND NOT EXISTS (SELECT 1 FROM TAB3 phs where phs.PKey = p.AgilityKey )
6 AND p.rflag = 'Y';
COUNT(1)
1
Elapsed: 00:00:00.52
Can you give me some tips on where I could read about learning to understand the explain plan. I did read a few articles which did help me, but not much. I am looking for something in detail. -
FILTER access path..
Hi ,
I have read a section in Performance Tuning e-book regarding the "Use of EXISTS versus IN for Subqueries".
In this section an example with its explain plan is posed....
SELECT
e.employee_id, e.first_name, e.last_name, e.salary
FROM employees e
WHERE EXISTS (SELECT 1 FROM orders o
WHERE e.employee_id = o.sales_rep_id
AND o.customer_id = 144);
ID OPERATION OPTIONS OBJECT_NAME OPT COST
0 SELECT STATEMENT CHO
1 FILTER
2 TABLE ACCESS FULL EMPLOYEES ANA 155
3 TABLE ACCESS BY INDEX ROWID ORDERS ANA 3
4 INDEX RANGE SCAN ORD_CUSTOMER_IX ANA 1As this type of access path is not described , at least in this section, can somebody describe when is this used....????
NOTE: I use Oracle10g. v2
Thank you....
SimIt does say "The plan requires a full table scan of the employees table, returning many rows. Each of these rows is then filtered against the orders table (through an index)." The FILTER operation consists of working through one set of rows performing some test against it, in this case an index lookup.
I'm a little surprised at those examples though. In 11g (using the predefined "OE" demo schema) I get the same plan for both versions:
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 3 | 90 | 5 (20)| 00:00:01 |
| 1 | NESTED LOOPS | | | | | |
| 2 | NESTED LOOPS | | 3 | 90 | 5 (20)| 00:00:01 |
| 3 | SORT UNIQUE | | 3 | 21 | 2 (0)| 00:00:01 |
|* 4 | TABLE ACCESS BY INDEX ROWID| ORDERS | 3 | 21 | 2 (0)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | ORD_CUSTOMER_IX | 5 | | 1 (0)| 00:00:01 |
|* 6 | INDEX UNIQUE SCAN | EMP_EMP_ID_PK | 1 | | 0 (0)| 00:00:01 |
| 7 | TABLE ACCESS BY INDEX ROWID | EMPLOYEES | 1 | 23 | 1 (0)| 00:00:01 |
Predicate Information (identified by operation id):
4 - filter("O"."SALES_REP_ID" IS NOT NULL)
5 - access("O"."CUSTOMER_ID"=144)
6 - access("E"."EMPLOYEE_ID"="O"."SALES_REP_ID")I haven't tested in 10g but I would expect similar results. If you can use either IN or EXISTS without affecting the logic, so can the optimizer. -
PARTITION RANGE SUBQUERY - Access path
Below quote is from Oracle product documentation.
<quote>
If the table with the WHERE predicate is relatively small compared to the partitioned table, and the expected reduction of records or partitions for the partitioned table is significant, Oracle will perform dynamic partition pruning using a recursive subquery
</quote>
http://download.oracle.com/docs/cd/B19306_01/server.102/b14223/parpart.htm#sthref215
create table t(
x number,
y number,
z number
) partition by range(z)
partition p_10 values less than ( 11),
partition p_20 values less than ( 21),
partition p_30 values less than ( 31),
partition p_40 values less than ( 41),
partition p_50 values less than ( 51),
partition p_60 values less than ( 61),
partition p_70 values less than ( 71),
partition p_80 values less than ( 81),
partition p_90 values less than ( 91),
partition p_100 values less than ( 101)
create table t1
as
select mod(rownum,10) as id,
username ,
sysdate as dt
from all_users;
insert /*+ append */ into t
select level,level,10
from dual
connect by level <= 1000000;
commit;
insert /*+ append */ into t select x,y,20 from t partition (p_10);
commit;
insert /*+ append */ into t select x,y,30 from t partition (p_10);
commit;
insert /*+ append */ into t select x,y,40 from t partition (p_10);
commit;
insert /*+ append */ into t select x,y,50 from t partition (p_10);
commit;
insert /*+ append */ into t select x,y,60 from t partition (p_10);
commit;
insert /*+ append */ into t select x,y,70 from t partition (p_10);
commit;
insert /*+ append */ into t select x,y,80 from t partition (p_10);
commit;
insert /*+ append */ into t select x,y,90 from t partition (p_10);
commit;
insert /*+ append */ into t select x,y,100 from t partition (p_10);
commit;
begin
dbms_stats.gather_table_Stats(user,'T1');
dbms_stats.gather_table_stats(ownname=>user,tabname=>'T',degree=>16);
end;
select /*+ use_hash(t,t1) */ t.*
from t, t1
where t.z = t1.id
and t1.username ='SCOTT'
call count cpu elapsed disk query current rows
Parse 1 0.03 0.67 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 1 0.65 0.65 0 2507 0 0
total 3 0.68 1.32 0 2507 0 0
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 100
Rows Row Source Operation
0 HASH JOIN (cr=2510 pr=0 pw=0 time=653031 us)
1 TABLE ACCESS FULL T1 (cr=3 pr=0 pw=0 time=59 us)
1000000 PARTITION RANGE SUBQUERY PARTITION: KEY(SUBQUERY) KEY(SUBQUERY) (cr=2507 pr=0 pw=0 t
1000000 TABLE ACCESS FULL T PARTITION: KEY(SUBQUERY) KEY(SUBQUERY) (cr=2504 pr=0 pw=0 t
select /*+ use_nl(t,t1) */ t.*
from t, t1
where t.z = t1.id
and t1.username ='SCOTT'
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 0 0
Fetch 1 0.12 0.12 0 2506 0 0
total 3 0.12 0.12 0 2506 0 0
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 100
Rows Row Source Operation
0 NESTED LOOPS (cr=2506 pr=0 pw=0 time=123836 us)
1 TABLE ACCESS FULL T1 (cr=3 pr=0 pw=0 time=53 us)
0 PARTITION RANGE ITERATOR PARTITION: KEY KEY (cr=2503 pr=0 pw=0 time=123777 us)
0 TABLE ACCESS FULL T PARTITION: KEY KEY (cr=2503 pr=0 pw=0 time=123761 us)
Questions_
1) what is the significant in having this PARTITION RANGE SUBQUERY access path in Oracle 10g? Even reading documentation, still unclear.
Edited by: Rajeshwaran on Nov 15, 2010 8:05 AMYep..Here is the code.
create table t(
x number,
y number,
z number
) partition by range(z)
partition p_10 values less than ( 11),
partition p_20 values less than ( 21),
partition p_30 values less than ( 31),
partition p_40 values less than ( 41),
partition p_50 values less than ( 51),
partition p_60 values less than ( 61),
partition p_70 values less than ( 71),
partition p_80 values less than ( 81),
partition p_90 values less than ( 91),
partition p_100 values less than ( 101)
create table t1
as
select mod(rownum,10) as id,
username ,
sysdate as dt
from all_users;
insert /*+ append */ into t
select level,level,10
from dual
connect by level <= 1000000;
commit;
insert /*+ append */ into t select x,y,20 from t partition (p_10);
commit;
insert /*+ append */ into t select x,y,30 from t partition (p_10);
commit;
insert /*+ append */ into t select x,y,40 from t partition (p_10);
commit;
insert /*+ append */ into t select x,y,50 from t partition (p_10);
commit;
insert /*+ append */ into t select x,y,60 from t partition (p_10);
commit;
insert /*+ append */ into t select x,y,70 from t partition (p_10);
commit;
insert /*+ append */ into t select x,y,80 from t partition (p_10);
commit;
insert /*+ append */ into t select x,y,90 from t partition (p_10);
commit;
insert /*+ append */ into t select x,y,100 from t partition (p_10);
commit;
begin
dbms_stats.gather_table_Stats(user,'T1');
dbms_stats.gather_table_stats(ownname=>user,tabname=>'T',degree=>16);
end;
select /*+ use_hash(t,t1) */ t.*
from t, t1
where t.z = t1.id
and t1.username ='SCOTT'
call count cpu elapsed disk query current rows
Parse 1 0.03 0.67 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 1 0.65 0.65 0 2507 0 0
total 3 0.68 1.32 0 2507 0 0
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 100
Rows Row Source Operation
0 HASH JOIN (cr=2510 pr=0 pw=0 time=653031 us)
1 TABLE ACCESS FULL T1 (cr=3 pr=0 pw=0 time=59 us)
1000000 PARTITION RANGE SUBQUERY PARTITION: KEY(SUBQUERY) KEY(SUBQUERY) (cr=2507 pr=0 pw=0 t
1000000 TABLE ACCESS FULL T PARTITION: KEY(SUBQUERY) KEY(SUBQUERY) (cr=2504 pr=0 pw=0 t
select /*+ use_nl(t,t1) */ t.*
from t, t1
where t.z = t1.id
and t1.username ='SCOTT'
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 0 0
Fetch 1 0.12 0.12 0 2506 0 0
total 3 0.12 0.12 0 2506 0 0
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 100
Rows Row Source Operation
0 NESTED LOOPS (cr=2506 pr=0 pw=0 time=123836 us)
1 TABLE ACCESS FULL T1 (cr=3 pr=0 pw=0 time=53 us)
0 PARTITION RANGE ITERATOR PARTITION: KEY KEY (cr=2503 pr=0 pw=0 time=123777 us)
0 TABLE ACCESS FULL T PARTITION: KEY KEY (cr=2503 pr=0 pw=0 time=123761 us) -
Why the query access path is different !
Hi All
I have a query which is running satisfactorily in TEST but is taking a long time in PROD.
SELECT * FROM MTHLY_PROD_BASE WHERE START_DATE >= to_date('1/1/2013','mm/dd/yyyy') AND START_DATE < to_date('1/1/2014','mm/dd/yyyy')
MTHLY_PROD_BASE is a view, containing some underlying tables and views which are doing summations and groupings of data.
I have access plans for it in TEST and PROD in jpg format, but I am not able to attach here as the "Insert Image" button is inactive for me. How can I attach them for explaining my issue properly ?
There was some memory added around a week ago to the DB server for improving performance of another database, but since then the DB in which I ran the query is performing poorly.
Data for underlying tables, being referenced in the query, in TEST is same as in PROD, but the plans are different.
I need to know what factors may cause the access path for a query to change, so that I can investigate what else might have got changed/impacted in PROD ?
ThanksAnkitV wrote:
Hi all
1) version info of TEST and PROD:
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
PL/SQL Release 11.2.0.2.0 - Production
"CORE 11.2.0.2.0 Production"
TNS for IBM/AIX RISC System/6000: Version 11.2.0.2.0 - Production
NLSRTL Version 11.2.0.2.0 - Production
2) Platform is Aix 6.1.0.0
3) Query as mentioned in initial post too :SELECT * FROM MTHLY_PROD_BASE WHERE START_DATE >= to_date('1/1/2013','mm/dd/yyyy') AND START_DATE < to_date('1/1/2014','mm/dd/yyyy')
4) As I mentioned, I do not have plan in text format, and its lots of lines in the
I need to know what might be the reason for change in the access mode for the query in PROD, which has caused it to take 3-4 hrs instead of 30 mins ?
Any help will be highly appreciated.
different results occur when something is different between the two environments.
Since we don't have access to either system, YOU are the only one who can actually compare & contrast between the two systems.
HOW To Make TUNING request
https://forums.oracle.com/forums/thread.jspa?threadID=2174552#9360003 -
Access path difference between Primary Key and Unique Index
Hi All,
Is there any specific way the oracle optimizer treats Primary key and Unique index differently?
Oracle Version
SQL> select * from v$version;
BANNER
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
PL/SQL Release 11.2.0.3.0 - Production
CORE 11.2.0.3.0 Production
TNS for IBM/AIX RISC System/6000: Version 11.2.0.3.0 - Production
NLSRTL Version 11.2.0.3.0 - Production
SQL> Sample test data for Normal Index
SQL> create table t_test_tab(col1 number, col2 number, col3 varchar2(12));
Table created.
SQL> create sequence seq_t_test_tab start with 1 increment by 1 ;
Sequence created.
SQL> insert into t_test_tab select seq_t_test_tab.nextval, round(dbms_random.value(1,999)) , 'B'||round(dbms_random.value(1,50))||'A' from dual connect by level < 100000;
99999 rows created.
SQL> commit;
Commit complete.
SQL> exec dbms_stats.gather_table_stats(USER_OWNER','T_TEST_TAB',cascade => true);
PL/SQL procedure successfully completed.
SQL> select col1 from t_test_tab;
99999 rows selected.
Execution Plan
Plan hash value: 1565504962
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 99999 | 488K| 74 (3)| 00:00:01 |
| 1 | TABLE ACCESS FULL| T_TEST_TAB | 99999 | 488K| 74 (3)| 00:00:01 |
Statistics
1 recursive calls
0 db block gets
6915 consistent gets
259 physical reads
0 redo size
1829388 bytes sent via SQL*Net to client
73850 bytes received via SQL*Net from client
6668 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
99999 rows processed
SQL> create index idx_t_test_tab on t_test_tab(col1);
Index created.
SQL> exec dbms_stats.gather_table_stats('USER_OWNER','T_TEST_TAB',cascade => true);
PL/SQL procedure successfully completed.
SQL> select col1 from t_test_tab;
99999 rows selected.
Execution Plan
Plan hash value: 1565504962
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 99999 | 488K| 74 (3)| 00:00:01 |
| 1 | TABLE ACCESS FULL| T_TEST_TAB | 99999 | 488K| 74 (3)| 00:00:01 |
Statistics
1 recursive calls
0 db block gets
6915 consistent gets
0 physical reads
0 redo size
1829388 bytes sent via SQL*Net to client
73850 bytes received via SQL*Net from client
6668 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
99999 rows processed
SQL> Sample test data when using Primary Key
SQL> create table t_test_tab1(col1 number, col2 number, col3 varchar2(12));
Table created.
SQL> create sequence seq_t_test_tab1 start with 1 increment by 1 ;
Sequence created.
SQL> insert into t_test_tab1 select seq_t_test_tab1.nextval, round(dbms_random.value(1,999)) , 'B'||round(dbms_random.value(1,50))||'A' from dual connect by level < 100000;
99999 rows created.
SQL> commit;
Commit complete.
SQL> exec dbms_stats.gather_table_stats('USER_OWNER','T_TEST_TAB1',cascade => true);
PL/SQL procedure successfully completed.
SQL> select col1 from t_test_tab1;
99999 rows selected.
Execution Plan
Plan hash value: 1727568366
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 99999 | 488K| 74 (3)| 00:00:01 |
| 1 | TABLE ACCESS FULL| T_TEST_TAB1 | 99999 | 488K| 74 (3)| 00:00:01 |
Statistics
1 recursive calls
0 db block gets
6915 consistent gets
0 physical reads
0 redo size
1829388 bytes sent via SQL*Net to client
73850 bytes received via SQL*Net from client
6668 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
99999 rows processed
SQL> alter table t_test_tab1 add constraint pk_t_test_tab1 primary key (col1);
Table altered.
SQL> exec dbms_stats.gather_table_stats('USER_OWNER','T_TEST_TAB1',cascade => true);
PL/SQL procedure successfully completed.
SQL> select col1 from t_test_tab1;
99999 rows selected.
Execution Plan
Plan hash value: 2995826579
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 99999 | 488K| 59 (2)| 00:00:01 |
| 1 | INDEX FAST FULL SCAN| PK_T_TEST_TAB1 | 99999 | 488K| 59 (2)| 00:00:01 |
Statistics
1 recursive calls
0 db block gets
6867 consistent gets
0 physical reads
0 redo size
1829388 bytes sent via SQL*Net to client
73850 bytes received via SQL*Net from client
6668 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
99999 rows processed
SQL> If you see here the even though statistics were gathered,
* In the 1st table T_TEST_TAB, the table is still using FULL table access after creation of index.
* And in the 2nd table T_TEST_TAB1, table is using PRIMARY KEY as expected.
Any comments ??
Regards,
BPatThanks.
Yes, ignored the NOT NULL part.Did a test and now it is working as expected
SQL> create table t_test_tab(col1 number not null, col2 number, col3 varchar2(12));
Table created.
SQL>
create sequence seq_t_test_tab start with 1 increment by 1 ;SQL>
Sequence created.
SQL> insert into t_test_tab select seq_t_test_tab.nextval, round(dbms_random.value(1,999)) , 'B'||round(dbms_random.value(1,50))||'A' from dual connect by level < 100000;
99999 rows created.
SQL> commit;
Commit complete.
SQL> exec dbms_stats.gather_table_stats('GREP_OWNER','T_TEST_TAB',cascade => true);
PL/SQL procedure successfully completed.
SQL> set autotrace traceonly
SQL> select col1 from t_test_tab;
99999 rows selected.
Execution Plan
Plan hash value: 1565504962
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 99999 | 488K| 74 (3)| 00:00:01 |
| 1 | TABLE ACCESS FULL| T_TEST_TAB | 99999 | 488K| 74 (3)| 00:00:01 |
Statistics
1 recursive calls
0 db block gets
6912 consistent gets
0 physical reads
0 redo size
1829388 bytes sent via SQL*Net to client
73850 bytes received via SQL*Net from client
6668 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
99999 rows processed
SQL> create index idx_t_test_tab on t_test_tab(col1);
Index created.
SQL> exec dbms_stats.gather_table_stats('GREP_OWNER','T_TEST_TAB',cascade => true);
PL/SQL procedure successfully completed.
SQL> select col1 from t_test_tab;
99999 rows selected.
Execution Plan
Plan hash value: 4115006285
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 99999 | 488K| 63 (2)| 00:00:01 |
| 1 | INDEX FAST FULL SCAN| IDX_T_TEST_TAB | 99999 | 488K| 63 (2)| 00:00:01 |
Statistics
1 recursive calls
0 db block gets
6881 consistent gets
0 physical reads
0 redo size
1829388 bytes sent via SQL*Net to client
73850 bytes received via SQL*Net from client
6668 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
99999 rows processed
SQL> -
INDEX UNIQUE SCAN instead of INDEX FULL SCAN or TABLE ACCESS FULL
I have calculated statistics in all tables and indexes
I have a table and a view and when I put it
SELECT *
FROM TABLE_A A
INNER JOIN VIEW_B B ON A.KEY_ID = B.PFK_KEY_ID
WHERE (B.FK_ID_XXX = 1)
If I see the execution plan:
In TABLE_A make a
TABLE ACCESS BY INDEX ROWID
INDEX UNIQUE SCAN (FIELD_A_TABLE_A_PK)
Itâs OK. I NEED IT (INDEX UNIQUE SCAN)
But If I put
SELECT A.Field_1, A.Field_2, A.Field_3, A.Field_4
FROM TABLE_A A
INNER JOIN VIEW_B B ON A.KEY_ID = B.PFK_KEY_ID
WHERE (B.FK_ID_XXX = 1)
In table A make a TABLE ACCESS FULL.
Then If I put:
SELECT /*+ INDEX(A FIELD_A_TABLE_A_PK) */ A.Field_1, A.Field_2, A.Field_3, A.Field_4
FROM TABLE_A A
INNER JOIN VIEW_B B ON A.KEY_ID = B.PFK_KEY_ID
WHERE (B.FK_ID_XXX = 1)
If I see the execution plan:
In TABLE_A make a
TABLE ACCESS BY INDEX ROWID
INDEX UNIQUE SCAN (FIELD_A_TABLE_A_PK)
Itâs OK. I NEED IT (INDEX UNIQUE SCAN)
Finally, If I put other tables and views in the query (I NEED IT)
For example:
SELECT /*+ INDEX(A FIELD_A_TABLE_A_PK) */ A.Field_1, A.Field_2, A.Field_3, A.Field_4
FROM TABLE_A A
INNER JOIN VIEW_B B ON A.KEY_ID = B.PFK_KEY_ID
INNER JOIN TABLE_Câ¦.
LEFT JOIN VIEW_Dâ¦.
WHERE (B.FK_ID_XXX = 1)
If I see the execution plan:
In TABLE_A make a
TABLE ACCESS BY INDEX ROWID
INDEX FULL SCAN (FIELD_A_TABLE_A_PK)
I need INDEX UNIQUE SCAN instead of INDEX FULL SCAN or TABLE ACCESS FULL.
How can obtain it?
What happens???
Thanks!Notice the difference in cardinality between your two select statements:
SELECT STATEMENT, GOAL = ALL_ROWS Cost=5 Cardinality=1
SELECT STATEMENT, GOAL = ALL_ROWS Cost=10450 Cardinality=472161Apparently since the optimizer believed the first statement was going to return one row, it used an index. But in the second statement it believed it was going to return nearly the whole table (didn't you say it had around 500k rows?). Hence full table scan. -
How to change access path for 'where' clause by using HINTS?
I searched a loooot of posts and haven't found a solution for my case. I don't even know whether it is possible or not. Is it possible to change the sequence of Oracle "Predicate Information"?
Here is my SQL and Oracle's execution plan.
SELECT Max(logId) AS logId FROM online_users_t
WHERE online_users_date >= to_date('2011-09-19 10:00:00') - 3.2 AND online_users_date <= to_date('2011-09-19 10:00:00') AND online_users_result in (1, -1)
GROUP BY online_users_user
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 24800 | 629K| 1336 (1)| 00:00:17 |
| 1 | HASH GROUP BY | | 24800 | 629K| 1336 (1)| 00:00:17 |
|* 2 | TABLE ACCESS BY INDEX ROWID| ONLINE_USERS_T | 38833 | 985K| 1334 (1)| 00:00:17 |
|* 3 | INDEX RANGE SCAN | ONLINE_USERS_T_IDX | 116K| | 313 (1)| 00:00:04 |
Predicate Information (identified by operation id):
2 - filter("ONLINE_USERS_RESULT"=(-1) OR "ONLINE_USERS_RESULT"=1)
3 - access("ONLINE_USERS_DATE">=TO_DATE(' 2011-09-16 05:12:00', 'syyyy-mm-dd
hh24:mi:ss') AND "ONLINE_USERS_DATE"<=TO_DATE(' 2011-09-19 10:00:00', 'syyyy-mm-dd
hh24:mi:ss'))I have 2 conditions in my 'where' clause, one is date range and the other is 'online_users_result in (1, -1)'. It seems that Oracle filter the table by using 'online_users_result in (1, -1)' first, then access it through date range.
What I want to do is firstly filtering the table by using date range followed by other things. How can I do it?
Any clue or help would be highly appreciated.
Thanks in advance.It seems that Oracle filter the table by using 'online_users_result in (1, -1)' first, then access it through date range. No it's not.
What I want to do is firstly filtering the table by using date range followed by other things. How can I do it?That's precisely what it's doing now.
It is using the T_IDX index to quickly find all rows that satisfy the range predicate on the date column.
And then filter those rows to only retrieve the ones that satisfy the other predicate (... in (1,-1)). -
Using index in a query return few records than full table access
Today we have an issue with a query, when it use the ok index the returned are not all records that apply to where clause condition.
See bellow
explain plan for
select * from movdb.zan_m03 where
M00AF = TO_DATE('11/01/28','YY/MM/DD') AND
M00za = 10 AND
m00AC = 50 AND
M00AD between 136906 and 136999
SELECT * FROM TABLE(dbms_xplan.display);
PLAN_TABLE_OUTPUT
Plan hash value: 1882720105
| Id | Operation | Name |
| 0 | SELECT STATEMENT | |
| 1 | TABLE ACCESS BY INDEX ROWID| ZAN_M03 |
|* 2 | INDEX RANGE SCAN | PK_ZAN_M03 |
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
2 - access("M00AF"=TO_DATE('11/01/28','YY/MM/DD') AND "M00ZA"=10 AND
"M00AC"=50 AND "M00AD">=136906 AND "M00AD"<=137141)
filter("M00AD"<=137141 AND "M00AD">=136906)
Note
- rule based optimizer used (consider using cbo)
20 rows selected.
The query above return only one row insted 1579 record that apply to this conditions.
When forcing a full table acess with a hint, the query return all records that apply, the 1579 record.
select /*+ FULL(zan_m03) */ M00AF, M00za, m00AC , M00AD from movdb.zan_m03 where
M00AF = TO_DATE('11/01/28','YY/MM/DD') AND
M00za = 10 AND
m00AC = 50 AND
M00AD between 136906 and 137141
Can you help me to identify what's happening?
I am with Oracle 10g R2 10.2.0.4 standard edition
the statistics are up to date
the opitimizer_mode are rule, but altering in session level to all_rows happens the same issue.
Nothing about corruption in the alert log.
Thanks in advance
Regards
CristianoYes the query are the same and correct restriction for where clause are M00AD between 136906 and 137141.
I've pasted, by mistake, another test query
The corrects are:
select M00AF, M00za, m00AC , M00AD from movdb.zan_m03 where
M00AF = TO_DATE('11/01/28','YY/MM/DD') AND
M00za = 10 AND
m00AC = 50 AND
M00AD between 136906 and 137141
This use pk index and return one row
select /*+ FULL(zan_m03) */ M00AF, M00za, m00AC , M00AD from movdb.zan_m03 where
M00AF = TO_DATE('11/01/28','YY/MM/DD') AND
M00za = 10 AND
m00AC = 50 AND
M00AD between 136906 and 137141
This does a full table access and return 1579 records
I´ve been searching for wrong results bugs on my oracle support, but not found one that mentions something like our issue.
I checked the dba_tables and dba indexes and the number of rows are different, and I think this would be the same because it's is a pk.
Look this
SQL> select NUM_ROWS from dba_tables where table_name = 'ZAN_M03'
2 /
NUM_ROWS
228527878
select NUM_ROWS from dba_indexes where index_name = 'PK_ZAN_M03';
SQL> select NUM_ROWS from dba_indexes where index_name = 'PK_ZAN_M03';
NUM_ROWS
217510185
Is normal a index for pk having much fewer rows than table? I think not, but not sure.
Again
Thanks in advance
Regards
Cristiano -
Table access by index rowid taking more time
Hi All
I've a query like
update tab1
set col1 = ( select col2 from
tab2
where tab1.id = tab2.id) table 1 has arnd 10,000 rows
table 2 has arnd 1,700,000 rows and has a primay key on column id.
This query is taking around 20 secs to execute. I checked the xplan and most of time taken for table access by index rowid.
Could you please suggest what can be the reason for this. (Can it be the clustering factor or something else)
I checked the stats for the tab2, its just three days old.
Regards
Ashwani>
table 1 has arnd 10,000 rows
table 2 has arnd 1,700,000 rows and has a primay key on column id.
This query is taking around 20 secs to execute. I checked the xplan and most of time taken for table access by index rowid.
Could you please suggest what can be the reason for this. (Can it be the clustering factor or something else)
I checked the stats for the tab2, its just three days old.
>
If you checked the xplan why haven't you posted it so we can look at it? Then we could see what table is being accessed by index rowid. Presumably it is table 2 but we the plan would eliminate the need to make assumptions.
The clustering factor could be a factor. You haven't told us how table1 is being accessed. All rows are being updated so a full table scann is most likely but again the plan would actually show the access.
Did you query the dictionary to see what the clustering factor is? Post the results of that
SQL> select index_name, leaf_blocks, avg_leaf_blocks_per_key, avg_data_blocks_per_key, clustering_factor, distinct_keys
2 from dba_indexes
3 where owner = 'schema'
4 and index_name in ('index_b','index_a'); -
Oracle 9.2 prefers Table Access Full over Local Index by rowid access
There's this table that has phone call records (30 million per day) that is partitioned by month (using the date column) and stores the last 6 months.
The primary key is date (varchar2 in yymmdd format) + call_id (a varchar2(18) with a format like this yyyymmdd+<3letters>+<sequentialnumber>)
The partition is by range like this:
PARTITION BY RANGE (FECHA)
PARTITION P200804 VALUES LESS THAN ('080501')
LOGGING
NOCOMPRESS,
If I run this query I get this plan
SELECT FECHA, SENTIDOTRAFICO,GEOGRAFIAID,SWITCHID,TIPOTRAFICOID,COUNT(*)
FROM GES_CDRS_RCNG_NEW
WHERE FECHA BETWEEN '080801' AND '080825'
AND TASACION IS NULL
AND BORRADO IS NULL
GROUP BY FECHA, SENTIDOTRAFICO,GEOGRAFIAID,SWITCHID,TIPOTRAFICOID
Plan
SELECT STATEMENT CHOOSECost: 78 K Bytes: 24 K Cardinality: 1 K
2 SORT GROUP BY Cost: 78 K Bytes: 24 K Cardinality: 1 K
1 TABLE ACCESS FULL GESTION.GES_CDRS_RCNG_NEW Cost: 43 K Bytes: 625 M Cardinality: 31 M Partition #: 2 Partitions accessed #5
If I hint the primary key index using /*+INDEX(GES_CDRS_RCNG_NEW PK_CDRS_RCNG_NEW)*/
I get a different plan
Plan
SELECT STATEMENT CHOOSECost: 954 K Bytes: 24 K Cardinality: 1 K
3 SORT GROUP BY Cost: 954 K Bytes: 24 K Cardinality: 1 K
2 TABLE ACCESS BY LOCAL INDEX ROWID GESTION.GES_CDRS_RCNG_NEW Cost: 918 K Bytes: 625 M Cardinality: 31 M Partition #: 2 Partitions accessed #5
1 INDEX RANGE SCAN UNIQUE GESTION.PK_CDRS_RCNG_NEW Cost: 137 K Cardinality: 31 M Partition #: 3 Partitions accessed #5
Looking at the cost, the full scan is way better, but this is obviously not the case. Why does this happen?
This problem forces many querys on this table to use hints or force the index use by adding conditions to the where clause like this
where fecha = '080801'
and clave like '20080801%'
when just by stating the date would be enough to choose the correct partition. It also messes up joins with other tables.
The table is analized every month, it has statistics that claim: 237,981,000 rows, 3,222,677 blocks, GLOBAL STATS: YES, LAST ANALYZED: 15/10/2008 21:05:26, Average row length: 213.
The partition envolved in this query has this stats: 32,520,520 rows, 442,715 blocks, analized on 27/08/2008 20:43:40
The index has this stats: analized on 15/10/2008 21:35:32, Blevel: 3, leaf blocks: 1,056,410, distinct keys: 238,484,510.
It is a local index and each partition has its own statistics.If I don't understand incorrectly the plan and the Predicater information, it seems the full scan version that costs less is actually doing a full scan from the biggining of the table (6 months) up to the 080825 date and the one using an index (hinted) does a better scan.
without hint
| Id | Operation | Name | Rows | Bytes | Cost | Pstart| Pstop |
| 0 | SELECT STATEMENT | | 1170 | 24570 | 78443 | | |
| 1 | SORT GROUP BY | | 1170 | 24570 | 78443 | | |
|* 2 | TABLE ACCESS FULL | GES_CDRS_RCNG_NEW | 31M| 625M| 42579 | 5 | 5 |
Predicate Information (identified by operation id):
2 - filter("GES_CDRS_RCNG_NEW"."FECHA"<='080825')
Note: cpu costing is offWith the hint:
| Id | Operation | Name | Rows | Bytes | Cost | Pstart| Pstop |
| 0 | SELECT STATEMENT | | 1170 | 24570 | 953K| | |
| 1 | SORT GROUP BY | | 1170 | 24570 | 953K| | |
| 2 | TABLE ACCESS BY LOCAL INDEX ROWID| GES_CDRS_RCNG_NEW | 31M| 625M| 918K| 5 | 5 |
|* 3 | INDEX RANGE SCAN | PK_CDRS_RCNG_NEW | 31M| | 136K| 5 | 5 |
Predicate Information (identified by operation id):
3 - access("GES_CDRS_RCNG_NEW"."FECHA">='080801' AND "GES_CDRS_RCNG_NEW"."FECHA"<='080825')
Note: cpu costing is off -
Export table access to oracle with Database ODBC()
Hi,
I export a table, access 2003, ent_tab whit 'DataBase ODBC()' to oracle.
I open Oracle SQL Developer and i can show table ent_tab, but i go worksheet and execute:
select * from ent_tab
and display error: ORA-00942...
Why??!!
Regards
JomarBecause ODBC created the table with "" which allowed lower case table name, but Oracle uses upper case table name by default. Suggest you recreate the table with upper-case name to avoid having to use "" in select statements.
Edited by: rgeier on Oct 27, 2009 5:34 PM -
Excluding slow table access in a UNION ALL view
Hi,
I have a view which unions three tables together.
One component of the view requires a table scan, as 90% of the records are required.
This view is then used in another outer select where these records are actually not required.
So I tagged each component with a code and excluded that in the outer select. However it still appears to access the table.
Is there any way I can exclude a component of the UNION ALL or do I need to explicitly split them?
example:
SELECT * FROM (
SELECT 'A' Q, JANUARY F FROM ENORMOUS.TABLE WHERE KEY = 'Non Selective Key' UNION ALL
SELECT 'B' Q, 1 F FROM DUAL UNION ALL
SELECT 'C' Q, 1 F FROM DUAL
) A
WHERE Q = 'B'
When I run the query plan without the WHERE it performs the table scan
When I include the WHERE it still performs the table scan but with a FILTER NULL IS NOT NULL afterwards.
So it appears that it is doing the table scan regardless and then throwing the records away - is that correct?
Any thoughts appreciated. I would prefer not the split this view out if possible as it is used everywhere.In summary my question is: is The Oracle query planner smart enough to exclude a component from a load of stacked UNION ALL queries?
given this query:
CREATE VIEW TEST AS
SELECT Q, F
FROM
SELECT 'A' Q, JANUARY F FROM ENORMOUS.TABLE WHERE KEY = 'Non Selective Key' UNION ALL
SELECT 'B' Q, 1 F FROM DUAL UNION ALL
SELECT 'C' Q, 1 F FROM DUAL
) A;
-- 1. This one selects from all tables, including a table scan on the enormous table
SELECT * FROM TEST;
-- 2. This one selects from all tables, including a table scan on the enormous table
-- However the query plan has a FILTER after the table scan. Does it exclude this work?
SELECT * FROM TEST WHERE Q = 'B';When I run the query plan without the WHERE it performs the table scan
When I include the WHERE the query plan indicates it's doing the table scan but with a FILTER NULL IS NOT NULL afterwards.
So it appears that it is doing the table scan regardless and then throwing the records away - is that correct?
Any thoughts appreciated. I would prefer not the split this view out if possible as it is used everywhere.
Oracle version:
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
PL/SQL Release 11.2.0.2.0 - Production
CORE 11.2.0.2.0 Production
TNS for 64-bit Windows: Version 11.2.0.2.0 - Production
NLSRTL Version 11.2.0.2.0 - Production
Plan output for 1:
SELECT STATEMENT Optimizer Mode=ALL_ROWS (Cost=7166 Card=2 M Bytes=41 M)
1 VIEW (Cost=7166 Card=2 M Bytes=41 M)
2 1 UNION-ALL
3 2 TABLE ACCESS FULL PLANNING.BF_GEN_STATS_TRAN (Cost=7162 Card=2 M Bytes=72 M)
4 2 FAST DUAL (Cost=2 Card=1)
5 2 FAST DUAL (Cost=2 Card=1)
Plan output for 2:
SELECT STATEMENT Optimizer Mode=ALL_ROWS (Cost=2 Card=3 Bytes=48)
1 VIEW (Cost=2 Card=3 Bytes=48)
2 1 UNION-ALL
3 2 FILTER
4 3 TABLE ACCESS FULL PLANNING.BF_GEN_STATS_TRAN (Cost=7162 Card=2 M Bytes=72 M)
5 2 FAST DUAL (Cost=2 Card=1)
6 2 FILTER
7 6 FAST DUAL (Cost=2 Card=1) -
oracle 9.2.0.8 (if there's a 10G way that would work)
This is a simplified view of a much biiger table I am having to deal with.
create table stg
(ddate date,
num number);
insert into stg
select sysdate, 26 from dual
union all
select sysdate - 1, 38 from dual
union all
select sysdate - 2, 10 from dual
union all
select sysdate - 3, 40 from dual
union all
select sysdate - 4, 50 from dual
union all
select sysdate - 5, 1 from dual
union all
select sysdate - 6, 11 from dual
union all
select sysdate - 7, 50 from dual
union all
select sysdate - 9, 38 from dual
union all
select sysdate - 10, 20 from dual
union all
select sysdate - 11, 11 from dual
union all
select sysdate - 12, 99 from dual
union all
select sysdate - 13, 18 from dual
union all
select sysdate - 14, 27 from dual
union all
select sysdate - 15, 28 from dual
union all
select sysdate - 16, 2 from dual
union all
select sysdate - 17, 99 from dual
union all
select sysdate - 18, 12 from dual
union all
select sysdate - 19, 27 from dual
union all
select sysdate - 20, 28 from dual
select
sum(case when ddate > d.the_date then 1
else 0
end)
,sum(case when ddate < d.the_date then 1
else 0
end)
,the_date
,max(ddate)
from stg, (select min(ddate) as the_date from stg
where num in (10,11,12,13,14,25))d
group by the_date
the query does give me the result set I'm looking for but the explain plan
shows it takes 2 table accesses. My question is how to re-write this so it
takes one access.
I have tried the analytic functions but there does not seem to be a way to
use the where clause in just the analytic function. Also I have tried:
select min(ddate), max(ddate) from stg
where num in (10,11,12,13,14,25)
but the problem with this is the max is the max where num is (10,11,12,13,14,25)not the max of the whole table.
any ideas to get rid of the nested loop would be helpful
thanksWhat do you want is not clear for me, but you can try to replace your query :
SCOTT@demo102> select greater,lesser,min_date,max_date
2 from
3 (SELECT
4 SUM(decode(SIGN(ddate -stg_sub."min_date"), 1, 1, 0)) over() AS greater
5 ,SUM(decode(SIGN(ddate -stg_sub."min_date"), -1, 1, 0)) over() AS lesser
6 ,stg_sub."min_date" AS min_date
7 ,stg_sub."max_date" AS max_date
8 ,rownum AS rnum
9 FROM
10 (SELECT
11 ddate
12 ,(SELECT MIN(ddate) FROM stg WHERE num IN(10,11,12,13,14,25)) AS "min_date"
13 ,max(ddate) over() AS "max_date"
14 FROM stg)stg_sub)
15 where rnum = 1
16 ;
GREATER LESSER MIN_DATE MAX_DATE
17 2 26/09/06 14/10/06by
SCOTT@demo102> select sum(greater) greater, sum(lesser) lesser, max(min_date) min_date, max(max_date) max_date
2 from
3 (SELECT
4 case when ddate - MIN(case when num IN(10,11,12,13,14,25) then ddate end) over () > 0 then 1 end AS greater,
5 case when ddate - MIN(case when num IN(10,11,12,13,14,25) then ddate end) over () < 0 then 1 end AS lesser,
6 MIN(case when num IN(10,11,12,13,14,25) then ddate end) over () as min_date,
7 max(ddate) over() AS max_date
8 FROM stg)
9 ;
GREATER LESSER MIN_DATE MAX_DATE
17 2 26/09/06 14/10/06
SCOTT@demo102>
It is a lower cost What did you mean by cost ? Is it cost from explain plan ? Take care, a low cost here doesn't say that your query will run fatser...
Nicolas.
Maybe you are looking for
-
Oracle DB Adapter throwing NLS_LANGUAGE' by invoking SP in BPEL Process
Hi, While i am invoking a Store procedure, the DB Adapter in BPEL process reslting throwing following below error in <fault> <bpelFault> <faultType>0</faultType> <bindingFault> <part name="summary"> <summary>Exception occured when binding was invoked
-
Copy applications from Apple IPOD Touch to Apple IPHONE
I purchased me an IPHONE and I have application that I installed from Apple Applications from using the ICON on the IPOD TOUCH. I am interested in know instead of paying again for the same applications can I transfer/copy these applications to the IP
-
altought recent items is set to none when I open pictures, texedit or word docs at least 10 previous files open up at the same time this is really confusing and annoying safari 6 still ***** why does mountain lion have the same bugs as the first vers
-
Hi All, Working on RH X5 generating webhelp. I need some logic help or some help on developing different manuals for different users for the same system, will explain below. I have got one project which have contents for different version i.e. from 6
-
PowerShell : SPWeb.GetFolder() with browser folder url failed
I am using powershell script and when I call SPWeb.GetFolder() with (short url) it works fine and when I used (browser url) it's not working. However it refers to the same folder e.g short url http://intranet.company.eg/it/Test/Test browser url : htt