Index Range Scan / Deleted Leaf Blocks
Hello guys,
i have such a scenario on a big index / table which i can not reproduce on my test database, so i need to know how oracle handles the index range scan.
For example:
TABLE TAB with the following columns NR (number), I_DATE (date), TEXT (VARCHAR2(50))
INDEX I_TAB on the column I_DATE.
Now the index has blevel 2 and many leaf blocks. And now my question.
Query: SQL> SELECT * from TAB WHERE I_DATE < 10.10.2004
The index had stored some values which are a less than 2003 but these ones are already deleted (so the leaf blocks are gone to the freelist), but it was not reorganized.
The execution plan is a INDEX RANGE SCAN on the INDEX I_TAB. Does the branch block still have pointers to the deleted leaf blocks which contained only 2003 values before (and so the INDEX RANGE SCAN scans all these blocks too) or are the pointers to these leaf blocks deleted in the branch block?
Thanks and Regards
Stefan
You can verify it by yourself. See following:
SELECT count(*) FROM index_test;
==> 1569408
SELECT count(*) FROM index_test WHERE id <= 2;
==> 12
-- Delete all except first 12 rows
DELETE FROM index_test WHERE id > 2;
-- Query and SQL Trace
BEGIN
FOR C IN (SELECT /*+index(index_test index_test_idx) deleted */ * FROM INDEX_TEST WHERE ID < 1000000) LOOP
NULL;
END LOOP;
END;
SELECT /*+index(index_test index_test_idx) deleted */ *
FROM
INDEX_TEST WHERE ID < 1000000
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.00 0.00 0 3490 0 12
total 3 0.00 0.01 0 3490 0 12
==> 3490 logical reads only for 12 rows and range scan??
-- Index tree dump
ALTER SESSION SET EVENTS 'IMMEDIATE TRACE NAME TREEDUMP LEVEL 67513'
----- begin tree dump
branch: 0x1000124 16777508 (0: nrow: 6, level: 2)
branch: 0x100b1ca 16822730 (-1: nrow: 557, level: 1)
leaf: 0x1000125 16777509 (-1: nrow: 512 rrow: 12)
leaf: 0x1000126 16777510 (0: nrow: 484 rrow: 0)
leaf: 0x1000127 16777511 (1: nrow: 479 rrow: 0)
leaf: 0x1000128 16777512 (2: nrow: 479 rrow: 0)
leaf: 0x1000139 16777529 (3: nrow: 479 rrow: 0)
leaf: 0x100013a 16777530 (4: nrow: 478 rrow: 0)
branch: 0x100b401 16823297 (0: nrow: 558, level: 1)
leaf: 0x100b1c9 16822729 (-1: nrow: 449 rrow: 0)
leaf: 0x100b1cb 16822731 (0: nrow: 449 rrow: 0)
leaf: 0x100b1cc 16822732 (1: nrow: 449 rrow: 0)
==> leaf:3488, branch: 7
This means that almost all the branch and leaf nodes are read only for 12 keys.
You can cross check this with the result of "10200" event which traces cr reads. You would find out that the blocks that are read by the query are exactly same as all the index blocks.
This is what you mean? that the deleted leaf blocks(which contain no actual data) are read by range scan? Through the simple test, the anwer is "yes".
Similar Messages
-
Index range scan cost change in 10.2.0.1
SQL> create table t1 as
2 select
3 rpad('x',40) ind_pad,
4 trunc(dbms_random.value(0,25)) n1,
5 trunc(dbms_random.value(0,25)) n2,
6 lpad(rownum,10,'0') small_vc,
7 rpad('x',200) padding
8 from
9 all_objects
10 where
11 rownum <= 10000
12 ;
Table created.
SQL> create index t1_i1 on t1(ind_pad,n1,n2)
2 pctfree 91
3 ;
Index created.
SQL> set autot trace exp
SQL> alter session set optimizer_features_enable='10.2.0.1';
Session altered.
SQL> exec dbms_stats.gather_table_stats(user,'T1',method_opt=>'for all columns size 1');
PL/SQL procedure successfully completed.
SQL> select
2 t1.small_vc
3 from
4 t1
5 where
6 t1.ind_pad = rpad('x',40)
7 and t1.n1 = 0
8 and t1.n2 = 4
9 ;
Execution Plan
Plan hash value: 1429545322
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
|
0 SELECT STATEMENT 16 928 20 (0)00:00
:01
1 TABLE ACCESS BY INDEX ROWIDT1 16 928 20 (0)00:00
:01
* 2 INDEX RANGE SCAN T1_I1 16 4 (0)00:00
:01
Predicate Information (identified by operation id):
2 - access("T1"."IND_PAD"='x' AND
"T1"."N1"=0 AND "T1"."N2"=4)
SQL> update t1 set n2=n1; //now t1 and t2 are correlated
10000 rows updated.
SQL> commit;
Commit complete.
SQL> exec dbms_stats.gather_table_stats(user,'T1',method_opt=>'for all columns size 1');
PL/SQL procedure successfully completed.
SQL> select
2 t1.small_vc
3 from
4 t1
5 where
6 t1.ind_pad = rpad('x',40)
7 and t1.n1 = 0
8 and t1.n2 = 4
9 ;
Execution Plan
Plan hash value: 3617692013
Id Operation Name Rows Bytes Cost (%CPU)Time
0 SELECT STATEMENT 16 928 84 (2)00:00:02 * 1 TABLE ACCESS FULLT1 16 928 84 (2)00:00:02
Predicate Information (identified by operation id):
1 - filter("T1"."N1"=0 AND "T1"."N2"=4 AND "T1"."IND_PAD"='x
SQL> exec dbms_stats.delete_table_stats(user,'T1');
//delete table stats test dynamic sampling
PL/SQL procedure successfully completed.
SQL> select
2 t1.small_vc
3 from
4 t1
5 where
6 t1.ind_pad = rpad('x',40)
7 and t1.n1 = 0
8 and t1.n2 = 4
9 ;
Execution Plan
Plan hash value: 1429545322
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
|
0 SELECT STATEMENT 1 60 1 (0)00:00
:01
1 TABLE ACCESS BY INDEX ROWIDT1 1 60 1 (0)00:00
:01
* 2 INDEX RANGE SCAN T1_I1 1 1 (0)00:00
:01
Predicate Information (identified by operation id):
2 - access("T1"."IND_PAD"='x' AND
"T1"."N1"=0 AND "T1"."N2"=4)
Note
- dynamic sampling used for this statement
//under dynamic sampling ,oracle choose true explain plan
SQL> exec dbms_stats.gather_table_stats(user,'T1',method_opt=>'for all columns size 1');
PL/SQL procedure successfully completed.
SQL> select /*+ index(t1) */
2 t1.small_vc
3 from
4 t1
5 where
6 t1.ind_pad = rpad('x',40)
7 and t1.n1 = 0
8 and t1.n2 = 4
9 ;
Execution Plan
Plan hash value: 1429545322
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
|
0 SELECT STATEMENT 16 928 256 (0)00:00
:04
1 TABLE ACCESS BY INDEX ROWIDT1 16 928 256 (0)00:00
:04
* 2 INDEX RANGE SCAN T1_I1 400 7 (0)00:00
:01
Predicate Information (identified by operation id):
2 - access("T1"."IND_PAD"='x' AND
"T1"."N1"=0 AND "T1"."N2"=4)
SQL> set autot off
SQL> select blevel,leaf_blocks,clustering_factor from user_indexes where table_name='T1';
BLEVEL LEAF_BLOCKS CLUSTERING_FACTOR
2 119 6201
//index selectity and table selectity are 0.4
index cost=2+119/25=7
table cost=7+6201/25=256
SQL> alter session set optimizer_features_enable='10.1.0.4';
Session altered.
SQL> set autot trace exp
SQL> select /*+ index(t1) */
2 t1.small_vc
3 from
4 t1
5 where
6 t1.ind_pad = rpad('x',40)
7 and t1.n1 = 0
8 and t1.n2 = 4
9 ;
Execution Plan
Plan hash value: 1429545322
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
|
0 SELECT STATEMENT 16 928 13 (0)00:00
:01
1 TABLE ACCESS BY INDEX ROWIDT1 16 928 13 (0)00:00
:01
* 2 INDEX RANGE SCAN T1_I1 16 3 (0)00:00
:01
Predicate Information (identified by operation id):
2 - access("T1"."IND_PAD"='x' AND
"T1"."N1"=0 AND "T1"."N2"=4)
//change optimizer to 10.1,then cbo caculate index selectity and table selectity 1/625>
Very interesting again. I can reproduce your test case in 10.2.0.4, and it looks like you're right. I don't know whether it's intended behaviour or not, but in this particular case, when a index-only access is possible (and the table is not required) then the old selectivity formula is used (in this case 1/10000 * 1/10000), and it ignores the DISTINCT_KEYS of the index.
The trace file shows that the index selectivity is actually determined as 1/10000 but it's obviously not used for the calculation.
Interestingly, repeating the same test case in 11.1.0.7 shows that it uses the DISTINCT_KEYS again in the case you're using the entire index:
Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Session altered.
SQL>
SQL> drop table m purge;
Table dropped.
SQL>
SQL> create table m(id int,id1 int);
Table created.
SQL>
SQL> insert into m select rownum,rownum+1 from dba_objects where rownum<10001;
10000 rows created.
SQL>
SQL> insert into m select * from m;
10000 rows created.
SQL>
SQL> insert into m select * from m;
20000 rows created.
SQL>
SQL> insert into m select * from m;
40000 rows created.
SQL>
SQL> insert into m select * from m;
80000 rows created.
SQL>
SQL> commit;
Commit complete.
SQL>
SQL> select count(*) from m;
COUNT(*)
160000
SQL>
SQL> create index i_m_1 on m(id,id1);
Index created.
SQL>
SQL> exec dbms_stats.gather_table_stats(user,'M',method_opt=>'for all columns si
ze 1', estimate_percent => null);
PL/SQL procedure successfully completed.
SQL>
SQL> set autotrace traceonly
SQL>
SQL> select * from m where id=1;
16 rows selected.
Execution Plan
Plan hash value: 3644412196
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 16 | 112 | 2 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| I_M_1 | 16 | 112 | 2 (0)| 00:00:01 |
Predicate Information (identified by operation id):
1 - access("ID"=1)
Statistics
1 recursive calls
0 db block gets
4 consistent gets
0 physical reads
0 redo size
670 bytes sent via SQL*Net to client
427 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
16 rows processed
SQL>
SQL> select * from m where id=1 and id1=2;
16 rows selected.
Execution Plan
Plan hash value: 3644412196
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 16 | 112 | 1 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| I_M_1 | 16 | 112 | 1 (0)| 00:00:01 |
Predicate Information (identified by operation id):
1 - access("ID"=1 AND "ID1"=2)
Statistics
1 recursive calls
0 db block gets
4 consistent gets
0 physical reads
0 redo size
670 bytes sent via SQL*Net to client
427 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
16 rows processed
SQL>
SQL>So in 11.1.0.7 it seems to be consistent behaviour to take the DISTINCT_KEYS for an access using the entire index, but not in 10.2.
Regards,
Randolf
Oracle related stuff blog:
http://oracle-randolf.blogspot.com/
SQLTools++ for Oracle (Open source Oracle GUI for Windows):
http://www.sqltools-plusplus.org:7676/
http://sourceforge.net/projects/sqlt-pp/ -
Taking more time in INDEX RANGE SCAN compare to the full table scan
Hi all ,
Below are the version og my database.
SQL> select * from v$version;
BANNER
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi
PL/SQL Release 10.2.0.4.0 - Production
CORE 10.2.0.4.0 Production
TNS for HPUX: Version 10.2.0.4.0 - Production
NLSRTL Version 10.2.0.4.0 - Production
I have gather the table statistics and plan change for sql statment.
SELECT P1.COMPANY, P1.PAYGROUP, P1.PAY_END_DT, P1.PAYCHECK_OPTION,
P1.OFF_CYCLE, P1.PAGE_NUM, P1.LINE_NUM, P1.SEPCHK FROM PS_PAY_CHECK P1
WHERE P1.FORM_ID = :1 AND P1.PAYCHECK_NBR = :2 AND
P1.CHECK_DT = :3 AND P1.PAYCHECK_OPTION <> 'R'
Plan before the gather stats.
Plan hash value: 3872726522
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | | | *14306* (100)| |
| 1 | *TABLE ACCESS FULL| PS_PAY_CHECK* | 1 | 51 | 14306 (4)| 00:02:52 |
Plan after the gather stats:
Operation Object Name Rows Bytes Cost
SELECT STATEMENT Optimizer Mode=CHOOSE
1 4
*TABLE ACCESS BY INDEX ROWID SYSADM.PS_PAY_CHECK* 1 51 *4*
*INDEX RANGE SCAN SYSADM.PS0PAY_CHECK* 1 3After gather stats paln look good . but when i am exeuting the query it take 5 hours. before the gather stats it finishing the within 2 hours. i do not want to restore my old statistics. below are the data for the tables.and when i am obserrving it lot of db files scatter rea
NAME TYPE VALUE
_optimizer_cost_based_transformation string OFF
filesystemio_options string asynch
object_cache_optimal_size integer 102400
optimizer_dynamic_sampling integer 2
optimizer_features_enable string 10.2.0.4
optimizer_index_caching integer 0
optimizer_index_cost_adj integer 100
optimizer_mode string choose
optimizer_secure_view_merging boolean TRUE
plsql_optimize_level integer 2
SQL> select count(*) from sysadm.ps_pay_check;
select num_rows,blocks from dba_tables where table_name ='PS_PAY_CHECK';
COUNT(*)
1270052
SQL> SQL> SQL>
NUM_ROWS BLOCKS
1270047 63166
Event Waits Time (s) (ms) Time Wait Class
db file sequential read 1,584,677 6,375 4 36.6 User I/O
db file scattered read 2,366,398 5,689 2 32.7 User I/Oplease let me know why it taking more time in INDEX RANGE SCAN compare to the full table scan?suresh.ratnaji wrote:
NAME TYPE VALUE
_optimizer_cost_based_transformation string OFF
filesystemio_options string asynch
object_cache_optimal_size integer 102400
optimizer_dynamic_sampling integer 2
optimizer_features_enable string 10.2.0.4
optimizer_index_caching integer 0
optimizer_index_cost_adj integer 100
optimizer_mode string choose
optimizer_secure_view_merging boolean TRUE
plsql_optimize_level integer 2
please let me know why it taking more time in INDEX RANGE SCAN compare to the full table scan?Suresh,
Any particular reason why you have a non-default value for a hidden parameter, optimizercost_based_transformation ?
On my 10.2.0.1 database, its default value is "linear". What happens when you reset the value of the hidden parameter to default? -
Our os is;
SunOS 5.9
and database is;
Oracle Database 10g Enterprise Edition Release 10.2.0.2.0 - 64bit
Our autotrace outputs are below also we have 10046 trace outputs;
08:41:04 tcell_dev@SCME > set timing on
08:41:19 tcell_dev@SCME > set autot on
08:41:21 tcell_dev@SCME > SELECT lnpessv.PROFILE_ID FROM SCME.LNK_PROFILEENTITY_SUBSSERVVAR lnpessv
08:41:25 2 WHERE lnpessv.SUBSCRIPTION_SERVICEVARIANT_ID = 1695083 ;
PROFILE_ID
1.400E+14
1.600E+14
Elapsed: 00:00:03.07
Execution Plan
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=3 Card=3 Bytes=51)
1 0 PARTITION HASH (ALL) (Cost=3 Card=3 Bytes=51)
2 1 INDEX (RANGE SCAN) OF 'PK_PROFILEENTITY_SUBSSERVVAR' (INDEX (UNIQUE)) (Cost=
3 Card=3 Bytes=51)
Statistics
1 recursive calls
0 db block gets
1539 consistent gets
514 physical reads
0 redo size
258 bytes sent via SQL*Net to client
273 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
2 rows processed
08:41:32 tcell_dev@SCME > SELECT lnpessv.PROFILE_ID FROM SCME.LNK_PROFILEENTITY_SUBSSERVVAR lnpessv
08:41:43 2 WHERE lnpessv.SUBSCRIPTION_SERVICEVARIANT_ID = 169508 ;
PROFILE_ID
1.400E+14
1.600E+14
Elapsed: 00:00:04.01
Execution Plan
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=3 Card=3 Bytes=51)
1 0 PARTITION HASH (ALL) (Cost=3 Card=3 Bytes=51)
2 1 INDEX (RANGE SCAN) OF 'PK_PROFILEENTITY_SUBSSERVVAR' (INDEX (UNIQUE)) (Cost=
3 Card=3 Bytes=51)
Statistics
1 recursive calls
0 db block gets
1537 consistent gets
512 physical reads
0 redo size
258 bytes sent via SQL*Net to client
273 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
2 rows processed
Here we see 97% wait time, and responce time is unexceptable; These are the waits from 10046 trace file;
WAIT #1: nam='gc cr grant 2-way' ela= 783 p1=341 p2=67065 p3=1 obj#=169530 tim=571610438395
WAIT #1: nam='db file sequential read' ela= 6924 file#=341 block#=67065 blocks=1 obj#=169530 tim=571610445466
WAIT #1: nam='gc cr grant 2-way' ela= 564 p1=294 p2=86263 p3=1 obj#=169531 tim=571610446493
WAIT #1: nam='db file sequential read' ela= 6629 file#=294 block#=86263 blocks=1 obj#=169531 tim=571610453158
INDEX RANGE SCAN PK_PROFILEENTITY_SUBSSERVVAR PARTITION: 1 512 (cr=1537 pr=512 pw=0 time=4272017 us)
This is the related tables properties;
OWNER SCME
TABLE_NAME LNK_PROFILEENTITY_SUBSSERVVAR
TABLESPACE_NAME DATA01
STATUS VALID
PCT_FREE 10
INI_TRANS 10
MAX_TRANS 255
INITIAL_EXTENT 65536
MIN_EXTENTS 1
MAX_EXTENTS 2147483645
LOGGING NO
BACKED_UP N
NUM_ROWS 239587420
BLOCKS 1587288
EMPTY_BLOCKS 0
AVG_SPACE 0
CHAIN_CNT 0
AVG_ROW_LEN 41
AVG_SPACE_FREELIST_BLOCKS 0
NUM_FREELIST_BLOCKS 0
DEGREE 1
INSTANCES 1
CACHE N
TABLE_LOCK ENABLED
SAMPLE_SIZE 71876226
LAST_ANALYZED 29.05.2006 23:21:24
PARTITIONED NO
TEMPORARY N
SECONDARY N
NESTED NO
BUFFER_POOL DEFAULT
ROW_MOVEMENT DISABLED
GLOBAL_STATS YES
USER_STATS NO
SKIP_CORRUPT DISABLED
MONITORING YES
DEPENDENCIES DISABLED
COMPRESSION DISABLED
DROPPED NO
We are suspecting rac configuration and hash partition and index usage with rac.
Any comments will be welcomed,
Thank you.
Tonguçthis is the output of dbms_metadata.get_ddl for the table;
CREATE TABLE "SCME"."LNK_PROFILEENTITY_SUBSSERVVAR"
( "SUBSCRIPTION_SERVICEVARIANT_ID" NUMBER NOT NULL ENABLE NOVALIDATE,
"PROFILE_ID" NUMBER NOT NULL ENABLE NOVALIDATE,
"CREATED_BY_ID" NUMBER,
"CREATED_DATE" DATE DEFAULT SYSDATE,
"UPDATED_BY_ID" NUMBER,
"UPDATED_DATE" DATE,
CONSTRAINT "PK_PROFILEENTITY_SUBSSERVVAR" PRIMARY KEY ("SUBSCRIPTION_SERVICEVARIANT_ID", "PROFILE_ID")
USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOLOGGING
STORAGE(INITIAL 4194304
BUFFER_POOL DEFAULT)
TABLESPACE "INDX02" GLOBAL PARTITION BY HASH ("SUBSCRIPTION_SERVICEVARIANT_ID","PROFILE_ID")
(PARTITION "SYS_P52989"
TABLESPACE "INDX02",
PARTITION "SYS_P52990"
TABLESPACE "INDX02",
PARTITION "SYS_P54010"
TABLESPACE "INDX02",
PARTITION "SYS_P54011"
TABLESPACE "INDX02",
PARTITION "SYS_P54012"
TABLESPACE "INDX02") ;
CREATE UNIQUE INDEX "SCME"."PK_PROFILEENTITY_SUBSSERVVAR" ON "SCME"."LNK_PROFILEENTITY_SUBSSERVVAR" ("SUBSCRIPTION_SERVICEVARIANT_ID", "PROFILE_ID")
PCTFREE 10 INITRANS 2 MAXTRANS 255 NOLOGGING
STORAGE(INITIAL 4194304
BUFFER_POOL DEFAULT)
TABLESPACE "INDX02" GLOBAL PARTITION BY HASH ("SUBSCRIPTION_SERVICEVARIANT_ID","PROFILE_ID")
(PARTITION "SYS_P52989"
TABLESPACE "INDX02",
PARTITION "SYS_P52990"
TABLESPACE "INDX02",
PARTITION "SYS_P53499"
TABLESPACE "INDX02",
PARTITION "SYS_P53500"
TABLESPACE "INDX02") ENABLE NOVALIDATE,
CONSTRAINT "FK_LNK_PROF_REFERENCE_SDP_SUBS" FOREIGN KEY ("SUBSCRIPTION_SERVICEVARIANT_ID")
REFERENCES "SCME"."SDP_SUBSCRIPTIONSERVICEVARIANT" ("SUBSCRIPTION_SERVICEVARIANT_ID") DEFERRABLE INITIALLY DEFERRED ENABLE NOVALIDATE
) PCTFREE 10 PCTUSED 40 INITRANS 10 MAXTRANS 255 NOCOMPRESS NOLOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "DATA01" ;
CREATE INDEX "SCME"."LNK_PROFILEENTITY_SUB_HNDX3" ON "SCME"."LNK_PROFILEENTITY_SUBSSERVVAR" ("SUBSCRIPTION_SERVICEVARIANT_ID")
PCTFREE 10 INITRANS 2 MAXTRANS 255 NOLOGGING
STORAGE(INITIAL 2097152
BUFFER_POOL DEFAULT)
TABLESPACE "INDX02" GLOBAL PARTITION BY HASH ("SUBSCRIPTION_SERVICEVARIANT_ID")
(PARTITION "SYS_P53501"
TABLESPACE "INDX02",
PARTITION "SYS_P53502"
TABLESPACE "INDX02",
PARTITION "SYS_P53499"
TABLESPACE "INDX02",
PARTITION "SYS_P53500"
TABLESPACE "INDX02") ;
CREATE INDEX "SCME"."PROFILE_ID_NDX43" ON "SCME"."LNK_PROFILEENTITY_SUBSSERVVAR" ("PROFILE_ID")
PCTFREE 10 INITRANS 2 MAXTRANS 255 NOLOGGING COMPUTE STATISTICS
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "INDX03" ;
ALTER TABLE "SCME"."LNK_PROFILEENTITY_SUBSSERVVAR" ADD CONSTRAINT "PK_PROFILEENTITY_SUBSSERVVAR" PRIMARY KEY ("SUBSCRIPTION_SERVICEVARIANT_ID", "PROFILE_ID")
USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 NOLOGGING
STORAGE(INITIAL 4194304
BUFFER_POOL DEFAULT)
TABLESPACE "INDX02" GLOBAL PARTITION BY HASH ("SUBSCRIPTION_SERVICEVARIANT_ID","PROFILE_ID")
(PARTITION "SYS_P52989"
TABLESPACE "INDX02",
PARTITION "SYS_P52990"
PARTITION "SYS_P53498"
TABLESPACE "INDX02",
PARTITION "SYS_P53499"
TABLESPACE "INDX02",
PARTITION "SYS_P53500"
TABLESPACE "INDX02") ENABLE NOVALIDATE;
ALTER TABLE "SCME"."LNK_PROFILEENTITY_SUBSSERVVAR" MODIFY ("SUBSCRIPTION_SERVICEVARIANT_ID" NOT NULL ENABLE NOVALIDATE);
ALTER TABLE "SCME"."LNK_PROFILEENTITY_SUBSSERVVAR" MODIFY ("PROFILE_ID" NOT NULL ENABLE NOVALIDATE); -
What is mean by index range scan and fast full scan
What is mean by the following execution plans
1)Table access by index rowid
2) Index range scan
3) Index fast full scan
4) global index by rowid
..etc
where i can get this information.In what situation CBO take these paths.Can you pls give me a link where i can find all these.I read these long time ago but not able to recollect
Thanks
AnandOracle® Database Performance Tuning Guide
10g Release 2 (10.2)
Part Number B14211-01
13.5 Understanding Access Paths for the Query Optimizer
http://download-east.oracle.com/docs/cd/B19306_01/server.102/b14211/optimops.htm#sthref1281 -
Dblink + local function: INDEX RANGE SCAN not used
Hi All,
I have an sql query to remote database:
SELECT N FROM [email protected] WHERE cd_n = 60
It works with INDEX RANGE SCAN for "N" field of table "tab", it's ok.
Now I'm replacing the constant value with the local database function:
SELECT N FROM [email protected] WHERE cd_n = dannis.foo()
Then 'INDEX RANGE SCAN' is removed out from query execution plan :-(
I've tried some tricks as
/*+ rule index(user.tab TAB$PK) */,
driving_site(tab),
to_number(dannis.foo()),
(select dannis.foo from [email protected])
and so on...
but INDEX RANGE SCAN wasn't appear while using the local function.
Is it true when dblink is used in combination with local function then INDEX RANGE SCAN will never used?
/Oracle 9.0.1.2/
Thanx,
dannis.See Optimizer not taking the hint
-
Is index range scan the reason for query running long time
I would like to know whether index range scan is the reason for the query running long time. Below is the explain plan. If so, how to optimise it? Please help
Operation Object COST CARDINALITY BYTES
SELECT STATEMENT () 413 1000 265000
COUNT (STOPKEY)
FILTER ()
TABLE ACCESS (BY INDEX ROWID) ORDERS 413 58720 15560800
INDEX (RANGE SCAN) IDX_SERV_PROV_ID 13 411709
TABLE ACCESS (BY INDEX ROWID) ADDRESSES 2 1 14
INDEX (UNIQUE SCAN) SYS_C004605 1 1
TABLE ACCESS (BY INDEX ROWID) ADDRESSES 2 1 14
INDEX (UNIQUE SCAN) SYS_C004605 1 1
TABLE ACCESS (BY INDEX ROWID) ADDRESSES 2 1 14
INDEX (UNIQUE SCAN) SYS_C004605 1 1The index range scan means that the optimiser has determined that it is better to read the index rather than perform a full table scan. So in answer to your question - quite possibly but the alternative might take even longer!
The best thing to do is to review your query and check that you need every table included in the query and that you are accessing the tables via the best route. For example if you can access a table via primary key index that would be better than using a non-unique index. But the best way of reducing the time the query takes to run is to give it less tables (and indexes) to read.
John Seaman
http://www.asktheoracle.net -
Direct Path Reads instead of Sequential Reads for index range scan
Database is 11.2. I have two development schemas, with the same table loaded in each schema - a 5 million row table. The execution path for the sql statement is the same against both tables; it's doing an index range scan.
But it would appear Oracle performs a direct path read against one schema, and performs sequential reads against the other schema. I don't understand why I'm seeing different behavior when the execution plan is the same. Any ideas? These are two different schemas in the same database.There is not enough information.So you even these tables located same database and you gathered statistics it is not mean both run time wait event statistics must be same.Really they are different tables.If both query use INDEX RANGE SCAN the it is not mean these plans are same.What about table and their index statistics? are they same? for example num_row or num_blocks of both tables are same? also about indexes.In additionally if you want to get exact reason you can enable sql trace(using dbms_monitor or setting sql_trace parameter to true according session) and need analyze result trace file using tkprof utility.In additionally in 11g here when query execution time oracle automatically choose direct read path(serial) based on size of tables and size of buffer cache(also here is available some hidden parameter to controlling this behavior).
-
Issues with reverse key indexes and range scan
I have a question. Why is it that reverse key indexes do not work in a range scan?
ThanksChris, well said in simple terms.
Extract from metalink:
Oracle8 provides the ability to create reverse key indexes. Reverse key indexes
reverse the bytes of each indexed column with the exception of ROWID and still
maintains the column order. Reverse key indexes are useful for Oracle Parallel
Server environments.
In an OPS environment, modifications to indexes are focused on a small
set of leaf blocks. Reversing the keys of the index allows insertions to be
distributed across all the leaf keys in the index. Reverse key indexes prevent
queries from performing an index range scan since lexically adjacent keys
are not stored next to each other. Reverse key indexes can also be used in
situations where users insert ascending values and delete lower values from the
table, thus helping to prevent skewed indexes.
===
Good discussion at
http://asktom.oracle.com/pls/ask/f?p=4950:8:2737861489787945222::NO::F4950_P8_DISPLAYID,F4950_P8_CRITERIA:627823669999
http://asktom.oracle.com/pls/ask/f?p=4950:8:2737861489787945222::NO::F4950_P8_DISPLAYID,F4950_P8_CRITERIA:6163160472530
Jaffar
Message was edited by:
The Human Fly -
Oracle 11.2 slow with range scan
L.S.,
I have an issue with performance with select.
The select only selects 40 objects via index. The table is generated by SAP, but in customer namespace.
With ST05 the explain shows:
SELECT
FROM
"ZCSNN_CAS"
WHERE
"MANDT" = :A0 AND "BUSOBJ_TYPE" = :A1 AND "BUSOBJ_ID" IN ( :A2 , :A3 , :A4 , :A5 , :A6 , :A7 ,
:A8 , :A9 , :A10 , :A11 , :A12 , :A13 , :A14 , :A15 , :A16 , :A17 , :A18 , :A19 , :A20 , :A21 ,
:A22 , :A23 , :A24 , :A25 , :A26 , :A27 , :A28 , :A29 , :A30 , :A31 , :A32 , :A33 ) AND
"BUSOBJ_VERSDATE" >= :A34 AND "STATUS_VERSION" = :A35 AND "STATUS_WORK" = :A36 AND
"FLG_CANCEL_VERS" = :A37 AND "FLG_CANCEL_OBJ" <> :A38
The execution plan is:
SELECT STATEMENT ( Estimated Costs = 68 , Estimated #Rows = 4 )
3 INLIST ITERATOR
2 TABLE ACCESS BY INDEX ROWID ZCSNN_CAS
( Estim. Costs = 67 , Estim. #Rows = 4 )
Estim. CPU-Costs = 735.327 Estim. IO-Costs = 67
Filter Predicates
1 INDEX RANGE SCAN ZCSNN_CAS~Z02
( Estim. Costs = 7 , Estim. #Rows = 316 )
Search Columns: 3
Estim. CPU-Costs = 213.909 Estim. IO-Costs = 7
Access Predicates Filter Predicates
Then then following fetches show long runtimes:
Runtime Object Operation Returncode
329 ZCSNN_CAS PREPARE 0
2 ZCSNN_CAS OPEN 0
150.678 ZCSNN_CAS FETCH 46 0
194.637 ZCSNN_CAS FETCH 46 0
157.639 ZCSNN_CAS FETCH 46 0
12.707 ZCSNN_CAS FETCH 46 0
90.340 ZCSNN_CAS FETCH 46 0
138.845 ZCSNN_CAS FETCH 46 0
49.715 ZCSNN_CAS FETCH 46 0
137.186 ZCSNN_CAS FETCH 46 0
204.770 ZCSNN_CAS FETCH 46 0
339.622 ZCSNN_CAS FETCH 46 0
173.157 ZCSNN_CAS FETCH 14 1403
To me it looks like an Oracle issue? Changes in the ABAP-code did not help.
Can Oracle be tweaked?
Regards,
WalterFirst of all, thanks for all the responses!
Below the requested data for starters!
Table ZCSNN_ACT
Last statistics date 05.12.2011
Analyze Method Sample 344.222 Rows
Number of rows 34.422.200
Number of blocks allocated 416.900
Number of empty blocks 0
Average space 0
Chain count 0
Average row length 82
Partitioned NO
UNIQUE Index ZCSNN_ACT~0
Column Name
#Distinct
MANDT
1
IMPORT_YEAR
9
CASE_ID
2.459.014
CASE_VERS
3
ACT_POS
30
Last statistics date 05.12.2011
Analyze Method Sample 362.683 Rows
Levels of B-Tree 3
Number of leaf blocks 294.140
Number of distinct keys 36.268.300
Average leaf blocks per key 1
Average data blocks per key 1
Clustering factor 8.322.500 -
Wrong cardinality estimate for range scan
select * from v$version;
BANNER
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 Linux: Version 11.2.0.2.0 - Production
NLSRTL Version 11.2.0.2.0 - ProductionSQL : select * from GC_FULFILLMENT_ITEMS where MARKETPLACE_ID=:b1 and GC_FULFILLMENT_STATUS_ID=:b2;
Plan
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 474K| 99M| 102 (85)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| GC_FULFILLMENT_ITEMS | 474K| 99M| 102 (85)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | I_GCFI_GCFS_ID_SDOC_MKTPLID | 474K| | 91 (95)| 00:00:01 |
Predicate Information (identified by operation id):
2 - access("GC_FULFILLMENT_STATUS_ID"=TO_NUMBER(:B2) AND "MARKETPLACE_ID"=TO_NUMBER(:B1))
filter("MARKETPLACE_ID"=TO_NUMBER(:B1))If i use literals than CBO uses cardinality =1 (I believe this is due it fix control :5483301 which i set to off In my environment)
select * from GC_FULFILLMENT_ITEMS where MARKETPLACE_ID=5 and GC_FULFILLMENT_STATUS_ID=2;
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 220 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| GC_FULFILLMENT_ITEMS | 1 | 220 | 3 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | I_GCFI_GCFS_ID_SDOC_MKTPLID | 1 | | 2 (0)| 00:00:01 |
Predicate Information (identified by operation id):
2 - access("GC_FULFILLMENT_STATUS_ID"=2 AND "MARKETPLACE_ID"=5)
filter("MARKETPLACE_ID"=5)Here is column distribution and histogram information
Enter value for column_name: MARKETPLACE_ID
COLUMN_NAME ENDPOINT_VALUE CUMMULATIVE_FREQUENCY FREQUENCY ENDPOINT_ACTUAL_VALU
MARKETPLACE_ID 1 1 1
MARKETPLACE_ID 3 8548 8547
MARKETPLACE_ID 4 15608 7060
MARKETPLACE_ID 5 16385 777 --->
MARKETPLACE_ID 35691 16398 13
MARKETPLACE_ID 44551 16407 9
6 rows selected.
Enter value for column_name: GC_FULFILLMENT_STATUS_ID
COLUMN_NAME ENDPOINT_VALUE CUMMULATIVE_FREQUENCY FREQUENCY ENDPOINT_ACTUAL_VALU
GC_FULFILLMENT_STATUS_ID 5 19602 19602
GC_FULFILLMENT_STATUS_ID 6 19612 10
GC_FULFILLMENT_STATUS_ID 8 19802 190
3 rows selected.
Actual distribution
select MARKETPLACE_ID,count(*) from GC_FULFILLMENT_ITEMS group by MARKETPLACE_ID order by 1;
MARKETPLACE_ID COUNT(*)
1 2099
3 16339936
4 13358682
5 1471839 --->
35691 33623
44551 19881
78931 40273
101611 1
6309408
9 rows selected.
BHAVIK_DBA: GC1EU> select GC_FULFILLMENT_STATUS_ID,count(*) from GC_FULFILLMENT_ITEMS group by GC_FULFILLMENT_STATUS_ID order by 1;
GC_FULFILLMENT_STATUS_ID COUNT(*)
1 880
2 63 --->
3 24
5 37226908
6 22099
7 18
8 325409
9 343
8 rows selected.10053 trace
SINGLE TABLE ACCESS PATH
Table: GC_FULFILLMENT_ITEMS Alias: GC_FULFILLMENT_ITEMS
Card: Original: 36703588.000000 Rounded: 474909 Computed: 474909.06 Non Adjusted: 474909.06
Best:: AccessPath: IndexRange
Index: I_GCFI_GCFS_ID_SDOC_MKTPLID
Cost: 102.05 Degree: 1 Resp: 102.05 Card: 474909.06 Bytes: 0
Outline Data:
/*+
BEGIN_OUTLINE_DATA
IGNORE_OPTIM_EMBEDDED_HINTS
OPTIMIZER_FEATURES_ENABLE('11.2.0.2')
DB_VERSION('11.2.0.2')
OPT_PARAM('_b_tree_bitmap_plans' 'false')
OPT_PARAM('_optim_peek_user_binds' 'false')
OPT_PARAM('_fix_control' '5483301:0')
ALL_ROWS
OUTLINE_LEAF(@"SEL$F5BB74E1")
MERGE(@"SEL$2")
OUTLINE(@"SEL$1")
OUTLINE(@"SEL$2")
INDEX_RS_ASC(@"SEL$F5BB74E1" "GC_FULFILLMENT_ITEMS"@"SEL$2" ("GC_FULFILLMENT_ITEMS"."GC_FULFILLMENT_STATUS_ID" "GC_FULFILLMENT_ITEMS"."SHIP_DELIVERY_OPTION_CODE" "GC_FULFILLMENT_ITEMS"."MARKETPLACE_ID"))
END_OUTLINE_DATA
*/Is there any reason why CBO is using card=474909.06 ? Having fix control () in place, it should have set card=1 if it is considering GC_FULFILLMENT_STATUS_ID= 2 as "rare" value..isn't it ?OraDBA02 wrote:
You are right Charles.
I was reading one of your blog and saw that.
As you said, it is an issue with SQLPLUS.
However, plan for the sql which is comming from application still shows the same (wrong cardinality) plan. It does not have TO_NUMBER function because of the reason that it does not experience data-type conversion that SQLPLUS has.
But YES...Plan is exactly the same with/without NO_NUMBER.OraDBA02,
I believe that some of the other people responding to this thread might have already described why the execution plan in the library cache is the same plan that you are seeing. One of the goals of using bind variables in SQL statements is to reduce the number of time consuming (and resource intensive) hard parses. That also means that a second goal is to share the same execution plan for future executions of the same SQL statement, even through bind variable values have changed. The catch here is that bind variable peeking, introduced with Oracle Database 9.0.1 (may be disabled by modifying a hidden parameter), helps the optimizer select the "best" (lowest calculated cost) execution plan for those specific bind variable values - the same plan may not be the "best" execution plan for other sets of bind variable values on future executions.
Histograms on one or more of the columns in the WHERE clause could either help or hinder the situation further. It might further help the first execution, but might further hinder future executions with different bind variable values. Oracle Database 11.1 introduced something called adaptive cursor sharing (and 11.2 introduced cardinality feedback) that in theory addresses issues where the execution plan should change for later executions with different bind variable values (but the SQL statement must execute poorly at least once).
There might be multiple child cursors in the library cache for the same SQL statement, each potentially with a different execution plan. I suggest finding the SQL_ID of the SQL statement that the application is submitting (you can do this by checking V$SQL or V$SQLAREA). Once you have the SQL_ID, go back to the SQL statement that I suggested for displaying the execution plan:
SELECT * FROM TABLE (DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'TYPICAL'));The first NULL in the above SQL statement is where you would specify the SQL_ID. If you leave the second NULL in place, the above SQL statement will retrieve the execution plan for all child cursors with that SQL_ID.
For instance, if the SQL_ID was 75chksrfa5fbt, you would execute the following:
SELECT * FROM TABLE (DBMS_XPLAN.DISPLAY_CURSOR('75chksrfa5fbt',NULL,'TYPICAL'));Usually, you can take it a step further to see the bind variables that were used during the optimization phase. To do that, you would add the +PEEKED_BINDS format parameter:
SELECT * FROM TABLE (DBMS_XPLAN.DISPLAY_CURSOR('75chksrfa5fbt',NULL,'TYPICAL +PEEKED_BINDS'));Note that there are various optimizer parameters that affect the optimizer's decisions, for instance, maybe the optimizer mode is set to FIRST_ROWS. Also possibly helpful is the +OUTLINE format parameter that might provide a clue regarding the value of some of the parameters affecting the optimizer. The SQL statement that you would then enter is similar to the following:
SELECT * FROM TABLE (DBMS_XPLAN.DISPLAY_CURSOR('75chksrfa5fbt',NULL,'TYPICAL +PEEKED_BINDS +OUTLINE'));Additional information might be helpful. Please see the following two forum threads to see what kind of information you should gather:
When your query takes too long… : When your query takes too long ...
How to post a SQL statement tuning request: HOW TO: Post a SQL statement tuning request - template posting
Charles Hooper
http://hoopercharles.wordpress.com/
IT Manager/Oracle DBA
K&M Machine-Fabricating, Inc. -
Performance issue, same range scan different execution times
Oracle 11gR1, queries run within seconds of each other.
I have 2 queries that are logically the same. Even the explain plans are very similar, except the second one reports an index range scan doing much more work than the first. The table is an IOT with deal_bucket_id and datetime as PK (in that order).
TKPROF output below:
select count(*) from deal_bucket_detail where deal_bucket_id
in
(815
, 816
, 817
, 818
, 997)
and datetime between to_date('01-JUL-08','dd-MON-rr') and to_date('01-JAN-09','dd-MON-rr')
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 2 0.79 2.24 2936 3551 0 1
total 4 0.79 2.24 2936 3551 0 1
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 43
Rows Row Source Operation
1 SORT AGGREGATE (cr=3551 pr=2936 pw=2936 time=0 us)
1430928 FILTER (cr=3551 pr=2936 pw=2936 time=380920 us)
1430928 INLIST ITERATOR (cr=3551 pr=2936 pw=2936 time=372057 us)
1430928 INDEX RANGE SCAN PK_DEAL_BUCKET_DETAIL (cr=3551 pr=2936 pw=2936 time=8782 us cost=1203 size=4069596 card=339133)(object id 14199)
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 2 0.00 0.00
db file sequential read 2936 0.02 1.49
SQL*Net message from client 2 0.00 0.00
select count(*) from deal_bucket_detail where deal_bucket_id
between 815 and 997
and datetime between to_date('01-JUL-08','dd-MON-rr') and to_date('01-JAN-09','dd-MON-rr')
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 2 3.70 8.86 29199 26986 0 1
total 4 3.70 8.86 29199 26986 0 1
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 43
Rows Row Source Operation
1 SORT AGGREGATE (cr=26986 pr=29199 pw=29199 time=0 us)
1430928 FILTER (cr=26986 pr=29199 pw=29199 time=6986078 us)
1430928 INDEX RANGE SCAN PK_DEAL_BUCKET_DETAIL (cr=26986 pr=29199 pw=29199 time=6977063 us cost=45208 size=5195748 card=432979)(object id 14199)
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 2 0.00 0.00
db file sequential read 219 0.04 0.08
db file parallel read 35 0.04 0.32
db file scattered read 211 0.10 5.02
SQL*Net message from client 2 0.00 0.00
********************************************************************************How can I work out why the second query is doing much more work than the first?
Edited by: SamB on Aug 5, 2009 6:09 PMBoth are doing an index range scan, however a different index range scan.
query 1: inlist iterator with <n> index range scan for 1 value, due to hard-coded values.
query 2: index range scan for all values, starting at the lowest, due to between.
Sybrand Bakker
Senior Oracle DBA -
Index leaf blocks???
Can anybody explain me the details of index leaf blocks?
What are the possible usage of those?Hi DKar,
index leaf block is the smallest unit of a btree index, they are used to store the rowid of the indexed rows.
Their usage is transparent to you.
I suggest to take a look here:
http://download-uk.oracle.com/docs/cd/B14117_01/server.101/b10743/schema.htm#sthref883
search for: The Internal Structure of Indexes
Regards
Acr -
Leaf Block Dump / Output varies
Hello guys,
i have faced the following issues on a leaf block dump:
First)
row#0[8024] flag: ------, lock: 0, len=12, data:(6): 00 40 76 fa 00 00
col 0; len 2; (2): c1 02
col 1; NULL
row#1[7998] flag: ------, lock: 0, len=14, data:(6): 00 40 76 fa 00 02
col 0; len 2; (2): c1 03
col 1; len 2; (2): c1 02
.......Second)
1103F5A90 3D91D858 000C0100 03303130 0944454C [=..X.....010.DEL]
1103F5AA0 494E535F 494E0832 30303730 36303106 [0505.20070601.]
1103F5AB0 30303535 3331063D 91D85800 0D010003 [005531.=..X.....]
1103F5AC0 30313009 44454C49 4E535F49 4E083230 [010.DAT050_IN.20]
1103F5AD0 30373036 30310630 30353533 34063D91 [070601.005534.=.]
1103F5AE0 D858000E 01000330 31300944 454C494E [.X.....010.DAT03]
1103F5AF0 535F494E 08323030 37303630 31063030 [S_IN.20070601.00]
1103F5B00 35353334 063D91D8 58000F01 00033031 [5534.=..X.....01]
1103F5B10 30094445 4C494E53 5F494E08 32303037 [0.DAT050_IN.2007]Sometimes i am facing the row#n output like in the first example and sometimes i am facing only the "real data" like in the second example when i am doing a leaf block dump. Both examples are from different indeces...
When does one occur? Has anyone any idea?
Regards
StefanHi,
File is truncated by trace file limit. Yeah but the file is not big enough.. i only dumped one block.. and the limit is up to 10MB
But as far as I'm aware, a memory dump is normally not included in block dump. Did you check what's at the top? Really interesting... i have done the same on our test system on the same index.. and there the section leaf block dump includes the information. The same command on the same index (i have cloned the database 3 days ago to our test system).
Leaf block dump
===============
row#0[3514] flag: ---D--, lock: 2, len=39
col 0; len 3; (3): 30 31 30
col 1; len 9; (9): 44 45 4c 49 4e 53 5f 49 4e
col 2; len 8; (8): 32 30 30 37 30 36 30 31
col 3; len 6; (6): 30 30 35 35 31 39
col 4; len 6; (6): 3d 91 d7 d8 00 13
----- end of leaf block dump -----Can this leaf block cleaned out (by deletes) and not include any pointers anymore?
I have compared the leaf block attributes:
-> kdxcoavs 3298 (with row#n entries)
-> kdxcoavs 6988 (without row#n entries)
So the dump were are no row#n entries has much more available space - this would be confirm my guess.
Regards
Stefan -
The plan doesn't use the index but the cost of INDEX FULL SCAN looks better
Hi,
Well, I'm sure I miss the boat... and if the question is pretty tricky, the answer is probably :"You're stupid Greg!". Well anyway, you'll probably be interested in trying to answer it as I've spent some times on it without any result ! I use Oracle XE on Windows...
1) Below is my query and its plan. You'll find the full schema generation script at the end of this email. Look at the cost (468) of the plan and the cost of the same query when you force the use of the index (116). Why is this ?
select count(distinct col5)
2 from demo
3 where col1 between 1 and 50000
4 and col2=col1
5 and col3=col1
6 and col4=col1;
Plan d'execution
Plan hash value: 2072716547
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 116 | 468 (2)| 00:00:06 |
| 1 | SORT GROUP BY | | 1 | 116 | | |
|* 2 | TABLE ACCESS FULL| DEMO | 1 | 116 | 468 (2)| 00:00:06 |
Predicate Information (identified by operation id):
2 - filter("COL2"="COL1" AND "COL3"="COL1" AND "COL4"="COL1" AND
"COL1"<=50000 AND "COL2"<=50000 AND "COL3"<=50000 AND "COL4"<=50000 AND
"COL1">=1 AND "COL2">=1 AND "COL3">=1 AND "COL4">=1)2) When I force the use of an index (with a Hint), You'll see the cost of the plan is 116 which is definitly better than the TABLE ACCESS FULL (468) :
SQL> l
1 select /*+ index(demo demo_idx)*/ count(distinct col5)
2 from demo
3 where col1 between 1 and 50000
4 and col2=col1
5 and col3=col1
6* and col4=col1
SQL> /
Plan d'execution
Plan hash value: 189561699
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 116 | 437 (2)| 00:00:06 |
| 1 | SORT GROUP BY | | 1 | 116 | | |
| 2 | TABLE ACCESS BY INDEX ROWID| DEMO | 1 | 116 | 437 (2)| 00:00:06 |
|* 3 | INDEX FULL SCAN | DEMO_IDX | 1 | | 436 (2)| 00:00:06 |
Predicate Information (identified by operation id):
3 - filter("COL2"="COL1" AND "COL3"="COL1" AND "COL4"="COL1" AND
"COL1"<=50000 AND "COL2"<=50000 AND "COL3"<=50000 AND "COL4"<=50000 AND
"COL1">=1 AND "COL2">=1 AND "COL3">=1 AND "COL4">=1)3) My question is why is plan1 used while plan2 should be considered better by the optimizer regarding the cost (to make the case even more complex, plan1 is actually more efficient but this is out of the scope of my question. I know that and I know why !).
You'll find a script to generate the structures and data below. I can send you the 10053 traces if you what to go furthermore. Take care the index is a REVERSE index (Don't know if query rewrite should be enabled in order to take advantage of this type of index but it is set to "true" (and "trusted") :
drop table demo;
create table demo (col1 number not null,
col2 number,
col3 number,
col4 number,
col5 varchar2(500));
begin
for i in 1..100000 loop
insert into demo values (i,i,i,i,'This column is used to raise the High Water Mark and '||
' the cost of an TABLE ACCESS FULL operation');
end loop;
end;
commit;
create index demo_idx on demo(col1,col2,col3,col4) reverse;
exec dbms_stats.gather_table_stats(USER, 'DEMO', cascade=>true, -
method_opt=>'FOR ALL COLUMNS SIZE 254', no_invalidate=>false) Any comments are welcome ! Best Regards,
Gregory
Message was edited by:
arkzoyd... I've added the "pre" tagsI suspect this has something to do with db_file_multiblock_read_count
After running provided creation statements by you I got following results:
SQL> show parameter multiblock
NAME TYPE VALUE
db_file_multiblock_read_count integer 16
SQL> set autotrace on
SQL> select count(distinct col5)
2 from demo
3 where col1 between 1 and 50000
4 and col2=col1
5 and col3=col1
6 and col4=col1
7 /
COUNT(DISTINCTCOL5)
1
Execution Plan
Plan hash value: 2072716547
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 116 | 375 (1)| 00:00:05 |
| 1 | SORT GROUP BY | | 1 | 116 | | |
|* 2 | TABLE ACCESS FULL| DEMO | 1 | 116 | 375 (1)| 00:00:05 |
Predicate Information (identified by operation id):
2 - filter("COL2"="COL1" AND "COL3"="COL1" AND "COL4"="COL1" AND
"COL1"<=50000 AND "COL2"<=50000 AND "COL3"<=50000 AND "COL4"<=5000
0 AND
"COL1">=1 AND "COL2">=1 AND "COL3">=1 AND "COL4">=1)
Statistics
196 recursive calls
0 db block gets
1734 consistent gets
850 physical reads
0 redo size
422 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
7 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> select /*+ index(demo demo_idx)*/ count(distinct col5)
2 from demo
3 where col1 between 1 and 50000
4 and col2=col1
5 and col3=col1
6 and col4=col1
7 /
COUNT(DISTINCTCOL5)
1
Execution Plan
Plan hash value: 189561699
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| T
ime |
| 0 | SELECT STATEMENT | | 1 | 116 | 431 (1)| 0
0:00:06 |
| 1 | SORT GROUP BY | | 1 | 116 | |
|
| 2 | TABLE ACCESS BY INDEX ROWID| DEMO | 1 | 116 | 431 (1)| 0
0:00:06 |
|* 3 | INDEX FULL SCAN | DEMO_IDX | 1 | | 430 (1)| 0
0:00:06 |
Predicate Information (identified by operation id):
3 - filter("COL2"="COL1" AND "COL3"="COL1" AND "COL4"="COL1" AND
"COL1"<=50000 AND "COL2"<=50000 AND "COL3"<=50000 AND "COL4"<=5000
0 AND
"COL1">=1 AND "COL2">=1 AND "COL3">=1 AND "COL4">=1)
Statistics
1 recursive calls
0 db block gets
50426 consistent gets
428 physical reads
0 redo size
422 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
1 rows processedNow I modify multiblock_read_count and full scan cost is going up although anyway Oracle by default chooses full scan instead of index access.
SQL> alter session set db_file_multiblock_read_count = 8;
Session altered.
SQL> select count(distinct col5)
2 from demo
3 where col1 between 1 and 50000
4 and col2=col1
5 and col3=col1
6 and col4=col1
7 /
COUNT(DISTINCTCOL5)
1
Execution Plan
Plan hash value: 2072716547
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 116 | 463 (1)| 00:00:06 |
| 1 | SORT GROUP BY | | 1 | 116 | | |
|* 2 | TABLE ACCESS FULL| DEMO | 1 | 116 | 463 (1)| 00:00:06 |
Predicate Information (identified by operation id):
2 - filter("COL2"="COL1" AND "COL3"="COL1" AND "COL4"="COL1" AND
"COL1"<=50000 AND "COL2"<=50000 AND "COL3"<=50000 AND "COL4"<=5000
0 AND
"COL1">=1 AND "COL2">=1 AND "COL3">=1 AND "COL4">=1)
Statistics
1 recursive calls
0 db block gets
1697 consistent gets
850 physical reads
0 redo size
422 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> select /*+ index(demo demo_idx)*/ count(distinct col5)
2 from demo
3 where col1 between 1 and 50000
4 and col2=col1
5 and col3=col1
6 and col4=col1
7 /
COUNT(DISTINCTCOL5)
1
Execution Plan
Plan hash value: 189561699
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| T
ime |
| 0 | SELECT STATEMENT | | 1 | 116 | 431 (1)| 0
0:00:06 |
| 1 | SORT GROUP BY | | 1 | 116 | |
|
| 2 | TABLE ACCESS BY INDEX ROWID| DEMO | 1 | 116 | 431 (1)| 0
0:00:06 |
|* 3 | INDEX FULL SCAN | DEMO_IDX | 1 | | 430 (1)| 0
0:00:06 |
Predicate Information (identified by operation id):
3 - filter("COL2"="COL1" AND "COL3"="COL1" AND "COL4"="COL1" AND
"COL1"<=50000 AND "COL2"<=50000 AND "COL3"<=50000 AND "COL4"<=5000
0 AND
"COL1">=1 AND "COL2">=1 AND "COL3">=1 AND "COL4">=1)
Statistics
1 recursive calls
0 db block gets
50426 consistent gets
0 physical reads
0 redo size
422 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
1 rows processedSo I don't know what is the default value of dbfmbrc in XE and not gone too deep to understand how for example system statistics may change your situation.
Gints Plivna
http://www.gplivna.eu
P.S. BTW I used Oracle Database 10g Enterprise Edition Release 10.2.0.1.0.
Message was edited by:
gintsp
listened to Williams suggestion :)
Maybe you are looking for
-
Our company currently runs an office software equivalent comparable to Office 2003 level. I was researching options (licensing!) for stepping up our office to real Microsoft Office product ... and got stuck with that idea ... totally confused at this
-
I want to use Oracle ADF Faces in the following environment. 1) IDE - eclipse, exadel studio 3.0.5 2) Container - Tomcat 5.0.9 3) Sun RI Please tell how to use adf with above environment. I need configuration details only.
-
I have a pdf file with a bunch of form inputs that I am populating with cfpdfform, but the agency form the pdf will print to has changed slightly so I need to move the form inputs slightly. I have a copy of the new form and I thought I could just cop
-
Does not recognise ipod device
the lead works fine with a 3rd gen ipod but with my 2gb original it does not recognise the usb device Is there a difference in the cables?
-
Hi, i've accidentally deleted my imessage, how can i reinstall it?
Hi, i've accidentally deleted my imessage, how can i reinstall it?