index skip scan
Hi allexcerpt from the page of doc guide 11-18 of rel2 11g performance tuning:
Skip scanning is advantageous when there are few distinct
values in the leading column of the composite index and many distinct values in the
nonleading key of the index
Anyone could explain it means by "nonleading key of the index?Best regards
Val
The key to an index is all the columns included in the index. The 'leader' or keys are the first column in the index. So, with an index on col1, col2, col3, you could make a request like:
select * from table
where col1 = value
and have it use the index for a range scan. In this case, col1 is the main key. You could also do:
select * from table
where col1 = value and
col2 = value
In this case, col1 and col2 run keys. However, something like:
select * from table
where col2 = value and
col3 = value
does not use the main key to the index. According to a number of factors, Oracle may be able to skip scan this index to respond to your request.
John
Tags: Database
Similar Questions
-
Why the feature multiple column indexes using index skip scan?
Hi all
I have just been hired by a new company and I explored its database infrastructure. Interestingly, I see several function based indexed column used for all the tables. I found it strange, but they said ' we use Axapta to connect Axapta with Oracle, function index according to should be used to improve performance. Therefore, our DBAs create several indexes of feature based for each table in the database. "Unfortunately, I can not judge their business logic.
My question is, I just created similar to my local database tables in order to understand the behavior of the function index according to several columns. In order to create indexes of based function (substr and nls_lower), I have to declare the columns as varchars2. Because in my business our DBAs had created a number of columns as a varchar2 data type. I created two excatly same table for my experience. I create miltiple function according to index on the my_first table, and then I create several normal index on the my_sec table. The interesting thing is, index skip scan cannot be performed on more than one basic function index (table my_first). However, it can be performed to normal several index on my_sec table. I hope that I have to express myself clearly.
Note: I also ask the logic of the rule function based index, they said when they index a column they don't ((column length) * 2 + 1) formula. For example, I want to create indexes on the zip code column, column data type VARCHAR2 (3), so I have to use 3 * 2 + 1 = 7, (substr (nls_lower (areacode), 1, 7). substr (nls_lower ()) notation is used nested for any function function index. I know that these things are very illogical, but they told me, they use this type of implementation for Axapta.
Anyway, in this thread, my question is reletad to function function with index index skip scan, not logical bussiness, because I can not change the business logic.
Also, can you please give hints or clues for multiple function based indexes?
Thanks for your help.
SQL > create table my_first as select '201' codeZone, to_char (100 + rownum) account_num, dbms_random.st
Ring name ('A', 10) from dual connect by level < = 5000;Table created.
SQL > create table my_sec as select '201' codeZone, to_char (100 + rownum) account_num, dbms_random.st
Ring name ('A', 10) from dual connect by level < = 5000;
Table created.
SQL > alter table my_first change account_num varchar2 (12);
Modified table.
SQL > alter table my_sec change account_num varchar2 (12);Modified table.
SQL > alter table my_first change codeZone VARCHAR2 (3);
Modified table.
SQL > alter table my_sec change codeZone VARCHAR2 (3);
Modified table.
SQL > create index my_first_i on my_first (substr (nls_lower (areacode), 1, 7), substr (nls_lower (account_num), 1, 15));
The index is created.
SQL > create index my_sec_i on my_sec (area code, account_num);
The index is created.
SQL > analyze table my_first computing statistics for all columns indexed for all indexes.
Parsed table.
SQL > analyze table my_sec computing statistics for all columns indexed for all indexes.
Parsed table.
SQL > exec dbms_stats.gather_table_stats (USER, 'MY_FIRST');
PL/SQL procedure successfully completed.
SQL > exec dbms_stats.gather_table_stats (USER, 'MY_SEC');
PL/SQL procedure successfully completed.
SQL > my_first desc;
Name Null? Type
----------------------------------------- -------- ----------------------------
CODEZONE VARCHAR2 (3)
ACCOUNT_NUM VARCHAR2 (12)
NAME VARCHAR2 (4000)SQL > desc my_sec
Name Null? Type
----------------------------------------- -------- ----------------------------
CODEZONE VARCHAR2 (3)
ACCOUNT_NUM VARCHAR2 (12)
NAME VARCHAR2 (4000)SQL > select * from my_sec where account_num = '4000';
Execution plan
----------------------------------------------------------
Hash value of plan: 1838048852--------------------------------------------------------------------------------
--------| ID | Operation | Name | Lines | Bytes | Cost (% CPU). TI
me |--------------------------------------------------------------------------------
--------| 0 | SELECT STATEMENT | | 1. 19. 3 (0) | 00
: 00:01 || 1. TABLE ACCESS BY INDEX ROWID | MY_SEC | 1. 19. 3 (0) | 00
: 00:01 ||* 2 | INDEX SKIP SCAN | MY_SEC_I | 1. | 2 (0) | 00
: 00:01 |--------------------------------------------------------------------------------
--------
Information of predicates (identified by the operation identity card):
---------------------------------------------------2 - access ("ACCOUNT_NUM" = '4000')
Filter ("ACCOUNT_NUM" = '4000')
Statistics
----------------------------------------------------------
1 recursive calls
0 db block Gets
Gets 7 compatible
0 physical reads
0 redo size
543 bytes sent via SQL * Net to client
384 bytes received via SQL * Net from client
2 SQL * Net back and forth to and from the client
0 sorts (memory)
0 sorts (disk)
1 rows processedSQL > select * from my_first where substr (nls_lower (account_num), 1: 25) = '4000';
Execution plan
----------------------------------------------------------
Hash value of plan: 1110109060------------------------------------------------------------------------------
| ID | Operation | Name | Lines | Bytes | Cost (% CPU). Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1. 20. 9 (12) | 00:00:01 |
|* 1 | TABLE ACCESS FULL | MY_FIRST | 1. 20. 9 (12) | 00:00:01 |
------------------------------------------------------------------------------Information of predicates (identified by the operation identity card):
---------------------------------------------------1 Filter (SUBSTR (NLS_LOWER ("MY_FIRST". "" "" ACCOUNT_NUM")(, 1, 15) ="4000"
AND SUBSTR (NLS_LOWER ("ACCOUNT_NUM"), 1, 25) = '4000')
Statistics
----------------------------------------------------------
15 recursive calls
0 db block Gets
Gets 26 consistent
0 physical reads
0 redo size
543 bytes sent via SQL * Net to client
384 bytes received via SQL * Net from client
2 SQL * Net back and forth to and from the client
0 sorts (memory)
0 sorts (disk)
1 rows processedSQL > Select / * + INDEX_SS (MY_FIRST) * / * from my_first where substr (nls_lower (account_num), 1: 25) = '4000';
Execution plan
----------------------------------------------------------
Hash value of plan: 2466066660--------------------------------------------------------------------------------
----------| ID | Operation | Name | Lines | Bytes | Cost (% CPU).
Time |--------------------------------------------------------------------------------
----------| 0 | SELECT STATEMENT | | 1. 20. 17 (6) |
00:00:01 ||* 1 | TABLE ACCESS BY INDEX ROWID | MY_FIRST | 1. 20. 17 (6) |
00:00:01 ||* 2 | INDEX SCAN FULL | MY_FIRST_I | 1. | 16 (7) |
00:00:01 |--------------------------------------------------------------------------------
----------
Information of predicates (identified by the operation identity card):
---------------------------------------------------1 - filter (SUBSTR (NLS_LOWER ("ACCOUNT_NUM"), 1, 25) = '4000')
2 - access (SUBSTR (NLS_LOWER ("ACCOUNT_NUM"), 1, 15) = '4000')
Filter (substr (NLS_LOWER ("ACCOUNT_NUM"), 1, 15) = '4000')
Statistics
----------------------------------------------------------
15 recursive calls
0 db block Gets
857 consistent gets
0 physical reads
0 redo size
543 bytes sent via SQL * Net to client
384 bytes received via SQL * Net from client
2 SQL * Net back and forth to and from the client
0 sorts (memory)
0 sorts (disk)
1 rows processedCheck MoS for a bug with the FBI and Skip Scan - it sounds like it could be a bug.
On 11.2.0.4 with your sample code 10053 trace shows the optimizer whereas an index FULL scan to the point where she should consider an index SKIP scan for "unique table path".
A person with 12.1.0.1 practice would like to run your test and see if it's fixed in this version.
Concerning
Jonathan Lewis
-
doubt about the Index Skip Scan
Hi all
I read the setting of Oracle performance guide (Version 11.2 Chapter 11). I just want to see index skip scan with an example. I created a table called t and inserted the test data. When I asked the table optimizer did not use the index skip scan path.
Can you please let me know what mistake I am doing here.
Thanks a lot for your help in advance.
SQL > create table t (empno number
2, ename varchar2 (2000)
3, varchar2 (1) sex
4, email_id varchar2 (2000));Table created
SQL >
SQL >-test data
SQL > insert into t
2 level, select "suri" | (level), ','suri.king' | level | ' @gmail.com'
3 double
4. connect by level < = 20000
5.20000 lines inserted
SQL >
SQL > insert into t
2 Select level + 20000, 'surya ' | (level + 20000), 'F', 'surya.princess'. (level + 20000) : ' @gmail.com '
3 double
4. connect by level < = 20000
5.20000 lines inserted
SQL > create index t_gender_email_idx on t (gender, email_id);
Index created
SQL > explain the plan for
2 Select
3 t
4 where email_id = "[email protected]";He explained.
SQL > select *.
table 2 (dbms_xplan.display);PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------
Hash value of plan: 1601196873--------------------------------------------------------------------------
| ID | Operation | Name | Lines | Bytes | Cost (% CPU). Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4. 8076 | 103 (1) | 00:00:02 |
|* 1 | TABLE ACCESS FULL | T | 4. 8076 | 103 (1) | 00:00:02 |
--------------------------------------------------------------------------Information of predicates (identified by the operation identity card):
---------------------------------------------------1 - Filter ("EMAIL_ID"= "[email protected]")
Note
-----
-dynamic sample used for this survey (level = 2)17 selected lines.
See you soon,.
Suri
You have just demonstrated how your execution plan gets screwed up if you do not have your statistics
SQL > create table t
() 2
3 empno number
4, ename varchar2 (2000)
5, varchar2 (1) sex
6, email_id varchar2 (2000)
7 );Table created.
SQL > insert into t
2 Select level, "suri" | (level), ', 'suri.king'| level | ' @gmail.com'
3 double
4. connect by level<=>=>
5.20000 rows created.
SQL > insert into t
2 Select level + 20000, 'surya ' | (level + 20000), 'F', 'surya.princess'. (level + 20000) : ' @gmail.com'
3 double
4. connect by level<=>=>
5.20000 rows created.
SQL > create index t_gender_email_idx on t (gender, email_id);
The index is created.
SQL > set autotrace traceonly explain
SQL >
SQL > select *.
2 t
3 where email_id = "[email protected]";Execution plan
----------------------------------------------------------
Hash value of plan: 2153619298--------------------------------------------------------------------------
| ID | Operation | Name | Lines | Bytes | Cost (% CPU). Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3. 6057. 79 (4) | 00:00:01 |
|* 1 | TABLE ACCESS FULL | T | 3. 6057. 79 (4) | 00:00:01 |
--------------------------------------------------------------------------Information of predicates (identified by the operation identity card):
---------------------------------------------------1 - Filter ("EMAIL_ID"= "[email protected]")
Note
-----
-dynamic sampling used for this statementSQL > exec dbms_stats.gather_table_stats (user, 't', cascade-online true)
PL/SQL procedure successfully completed.
SQL > select *.
2 t
3 where email_id = "[email protected]";Execution plan
----------------------------------------------------------
Hash value of plan: 2655860347--------------------------------------------------------------------------------------------------
| ID | Operation | Name | Lines | Bytes | Cost (% CPU). Time |
--------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1. 44. 1 (0) | 00:00:01 |
| 1. TABLE ACCESS BY INDEX ROWID | T | 1. 44. 1 (0) | 00:00:01 |
|* 2 | INDEX SKIP SCAN | T_GENDER_EMAIL_IDX | 1. | 1 (0) | 00:00:01 |
--------------------------------------------------------------------------------------------------Information of predicates (identified by the operation identity card):
---------------------------------------------------2 - access ("EMAIL_ID"= '[email protected]')
filter ("EMAIL_ID"= "[email protected]")SQL >
-
INDEX RANGE SCAN against INDEX SKIP SCAN
Dear,
Let me introduce you to the model, and then I'll ask my question
So far so good.SQL> select * from v$version; BANNER ---------------------------------------------------------------- Oracle Database 10g Enterprise Edition Release 10.2.0.5.0 - 64bi PL/SQL Release 10.2.0.5.0 - Production CORE 10.2.0.5.0 Production TNS for Solaris: Version 10.2.0.5.0 - Production NLSRTL Version 10.2.0.5.0 - Production SQL> create table t1 2 as select rownum id1, 3 mod(rownum,1000) id2, 4 lpad(rownum,10,'0') small_vc, 5 rpad('x',1000) padding 6 from dual 7 connect by level <= 10000; Table created. SQL> create index t1_ind_id1 on t1(id1); Index created. SQL> create index t1_ind_id2 on t1(id2, id1); Index created. SQL> exec dbms_stats.gather_table_stats(user, 't1', cascade => true); PL/SQL procedure successfully completed. SQL> select index_name, num_rows, clustering_factor 2 from user_indexes 3 where index_name in ('T1_IND_ID1','T1_IND_ID2'); INDEX_NAME NUM_ROWS CLUSTERING_FACTOR ------------------------------ ---------- ----------------- T1_IND_ID1 10000 1429 T1_IND_ID2 10000 10000 SQL> select * 2 from t1 3 where id1=6; Execution Plan ---------------------------------------------------------- Plan hash value: 2367654148 ------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | 1019 | 2 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| T1 | 1 | 1019 | 2 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | T1_IND_ID1 | 1 | | 1 (0)| 00:00:01 | ------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("ID1"=6)
What I want is to know how I can reproduce an example of real life where an index skip scan has been chosen by the CBO despite the presence of the index 'adequate '.
Here, below, I tried several examples
It's predictable. Let replace them the usable index and change its grouping factorSQL> alter index t1_ind_id1 unusable; Index altered. SQL> select * 2 from t1 3 where id1=6; Execution Plan ---------------------------------------------------------- Plan hash value: 2497247906 ------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | 1019 | 1004 (1)| 00:00:03 | | 1 | TABLE ACCESS BY INDEX ROWID| T1 | 1 | 1019 | 1004 (1)| 00:00:03 | |* 2 | INDEX SKIP SCAN | T1_IND_ID2 | 1 | | 1003 (1)| 00:00:03 | ------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("ID1"=6) filter("ID1"=6)
Still without success to produce an INDEX SKIP SCAN on T1_IND_ID2 in the presence of the T1_IND_ID1 indexSQL> alter index t1_ind_id1 rebuild; Index altered. SQL> select * 2 from t1 3 where id1=6; Execution Plan ---------------------------------------------------------- Plan hash value: 2367654148 ------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | 1019 | 2 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| T1 | 1 | 1019 | 2 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | T1_IND_ID1 | 1 | | 1 (0)| 00:00:01 | ------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("ID1"=6) SQL> exec dbms_stats.set_index_stats(user, 'T1_IND_ID1',clstfct => 20000); PL/SQL procedure successfully completed. SQL> select index_name, num_rows, clustering_factor 2 from user_indexes 3 where index_name in ('T1_IND_ID1','T1_IND_ID2'); INDEX_NAME NUM_ROWS CLUSTERING_FACTOR ------------------------------ ---------- ----------------- T1_IND_ID1 10000 20000 T1_IND_ID2 10000 10000 SQL> select * 2 from t1 3 where id1=6; Execution Plan ------------------------------------------------------------------------------------------ Plan hash value: 2367654148 ------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | 1019 | 3 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| T1 | 1 | 1019 | 3 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | T1_IND_ID1 | 1 | | 1 (0)| 00:00:01 | ------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("ID1"=6)
Any suggestions?
Thank you
Mohamed Houri
www.hourim.WordPress.comWhat I want is to know how I can reproduce an example of real life where an index skip scan has been chosen by the CBO despite the presence of the 'adequate' index
If, on behalf of the investigation, trying to 'force' the index skip scan, you must do two things:
1. change the factor of grouping of TI_IND_ID1 to make it more expensive.
While Hemant and Nikolay make good points on the fact that the grouping factor SHOULD BE irrelevant for a search of a single line, you are using a non-unique index is still part of the calculation of costs for a range scan.
It had been a unique index so the factor of grouping of piracy would have been ineffective.
But because only the cost calculation involves selectivity * factor clustering, you must change it by an order of magnitude (relevant to num_distinct obviously) to make significant change.
For example:
SQL> exec dbms_stats.set_index_stats(user, 'T1_IND_ID1',clstfct => 20000000); PL/SQL procedure successfully completed. SQL> explain plan for 2 select /*+ index(t1 t1_ind_id1) */ * 3 from t1 4 where id1=6; Explained. SQL> select * from table(dbms_xplan.display); PLAN_TABLE_OUTPUT --------------------------------------------------------------------------------------------------------- Plan hash value: 3180815200 ------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | 1019 | 2002 (1)| 00:00:25 | | 1 | TABLE ACCESS BY INDEX ROWID| T1 | 1 | 1019 | 2002 (1)| 00:00:25 | |* 2 | INDEX RANGE SCAN | T1_IND_ID1 | 1 | | 1 (0)| 00:00:01 | ------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("ID1"=6) 14 rows selected. SQL>
This pushes the cost of analysis of the range up above the table scan complete:
SQL> explain plan for 2 select * 3 from t1 4 where id1=6; Explained. SQL> select * from table(dbms_xplan.display); PLAN_TABLE_OUTPUT ----------------------------------------------------------------------------------------------- Plan hash value: 3617692013 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 1019 | 322 (1)| 00:00:04 | |* 1 | TABLE ACCESS FULL| T1 | 1 | 1019 | 322 (1)| 00:00:04 | -------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("ID1"=6) 13 rows selected. SQL>
So, now to the next step.
2. we need to artificially reduce the cost of the analysis of Skip - and the best way to do that is by changing the separate issue of the main column in the index (currently 1000):
SQL> begin 2 DBMS_STATS.SET_COLUMN_STATS 3 (ownname => USER, 4 tabname => 'T1', 5 colname => 'ID2', 6 partname => NULL, 7 stattab => NULL, 8 statid => NULL, 9 distcnt => 1, 10 density => 1, 11 nullcnt => 0, 12 srec => NULL, 13 avgclen => 4, 14 flags => NULL, 15 statown => NULL, 16 no_invalidate => FALSE, 17 force => TRUE); 18 end; 19 / PL/SQL procedure successfully completed. SQL>
As a Skip Scan is now taken over by default:
SQL> explain plan for 2 select * 3 from t1 4 where id1=6; Explained. SQL> select * from table(dbms_xplan.display); PLAN_TABLE_OUTPUT --------------------------------------------------------------------------------------------------- Plan hash value: 3198394326 ------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | 1019 | 3 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| T1 | 1 | 1019 | 3 (0)| 00:00:01 | |* 2 | INDEX SKIP SCAN | T1_IND_ID2 | 1 | | 2 (0)| 00:00:01 | ------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("ID1"=6) filter("ID1"=6) 15 rows selected. SQL>
Hope this helps
Published by: Dom Brooks on October 24, 2012 12:49
Reformulated -
Question on the composite index and index skip scan
Hello
I have a confusion.
I read the post of Burleson on the column of the composite index command (http://www.dba-oracle.com/t_composite_index_multi_column_ordering.htm) where he writes that
«.. . for composite indexes the most restrictive value of the column (the column with the highest unique values) should be made first to cut down the result set in... »
But 10g performance tuning book tells the subject INDEX SKIP SCAN:
"... Index scan Skip allows a composite index that is logically divided into smaller subindex. In Dumpster
scanning, the first column in the composite index is not specified in the query. In other words, it is ignored.
The number of logic subindex is determined by the number of distinct values in the first column.
Skip scanning is advantageous if there are few distinct values in the main column of the composite index and many distinct values in the key do not tip of the index... »
If design us a composite index according to what said Burleson, then how can we take advantage of index skip scan. These two staements to oppose each other, Don't they?
Can someone explain this?Even if you're not skip scanning, it is best to put the column with less distinct values in the main column of the index.
If a query specifies two key as predicates of equality columns, it doesn't really matter how columns are sorted in the index.
If a query specifies a range on a key column, it is most likely on the second column of the index.BTW, sometimes even a column 3 or the index of the column 4 is useful. In order to not restrict simply yourself in 2 columns. However, do not create too many clues - especially if there is overlap between the index.
Hemant K Collette
-
Hello
I have a very basic question.
I use Autotrace to check the Plan for this query
Table definition:
------------------------------------
create table tb_emp)
sextype varchar2 (1).
EmpID number
);
Array of values
-----------------------------------------------
insert into tb_emp values ('F', 98);
insert into tb_emp values ('F', 100);
insert into tb_emp values ('F', 102);
insert into tb_emp values ('F', 104);
insert into tb_emp values('M',101);
insert into tb_emp values('M',103);
insert into tb_emp values('M',105);
commit;
Index:
-----------------------------------------------------------------------------
create index EMP_SEXTYPE_EMP_IDX on tb_emp (SEXTYPE, empid);
Query:
--------------------------------------------------------------------------------------------------------------
Select * from tb_emp where empid = 101;
---------------------------------------------------------------------------------------------------------------
Execution plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer = ALL_ROWS (cost = 0 card = 1 bytes = 15)
1 INDEX 0 (COMPLETE ANALYSIS) OF 'EMP_SEXTYPE_EMP_IDX' (INDEX) (cost = 0 card = 1 bytes = 15)
According to b14211 this should translate into an index Skip Scan,
A pointer to what am I missing or other parameters that could affect the execution plan.
Thank you and best regards,
Ashish.The case of test used by you is not a real. With 7 records in a table is important if the optimizer goes for a systematic index scan or a full scan?
make it a little big and try
SQL> truncate table tb_emp 2 / Table truncated. SQL> set autotrace off SQL> edit Wrote file afiedt.buf 1 insert into tb_emp 2 select decode(mod(level,2),0,'M','F'), level 3 from dual 4* connect by level <= 10000 SQL> / 10000 rows created. SQL> commit 2 / Commit complete. SQL> select sextype, count(*) from tb_emp group by sextype 2 / S COUNT(*) - ---------- M 5000 F 5000 SQL> exec dbms_stats.gather_table_stats(user,'TB_EMP',cascade=>true) PL/SQL procedure successfully completed. SQL> set autotrace traceonly explain SQL> select * from tb_emp where empid = 3000 2 / Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=3 Card=1 Bytes=5) 1 0 INDEX (SKIP SCAN) OF 'EMP_SEXTYPE_EMP_IDX' (INDEX) (Cost=3 Card=1 Bytes=5)
-
Estimates of cardinality for index range scan with bind variables
Oracle 11.2.0.4
I am struggling to explain that the cardinality estimates for a scan of the index systematic range when using the bind variable.
Consider the following query:
SELECT /*+ INDEX(t1) */ * FROM t1 WHERE source_id <= ?;
Cardinalities for the INDEX RANGE SCAN and ACCESS of the TABLE are the same for different literal predicates, for example, source_id < = 5:
------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 50 | 350 | 12 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| T1 | 50 | 350 | 12 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | IX1 | 50 | | 2 (0)| 00:00:01 | ------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("SOURCE_ID"<=5)
If a variable binding is used instead of a literal, the overall selectivity is 5%. However, why the optimizer based on CSSTidy gives a cardinality estimated 11 for the scan of the index systematic range? As with the predicates literal, surely the cardinalities of the index range scan and access table should be the same?
------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 50 | 350 | 5 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| T1 | 50 | 350 | 5 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | IX1 | 11 | | 2 (0)| 00:00:01 | ------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("SOURCE_ID"<=TO_NUMBER(:A))
Unit test code:
CREATE TABLE t1 ( id NUMBER , source_id NUMBER ); CREATE INDEX ix1 ON t1 (source_id); INSERT INTO t1 SELECT level , ora_hash(level,99)+1 FROM dual CONNECT BY level <= 1000; exec DBMS_STATS.GATHER_TABLE_STATS(user,'T1') EXPLAIN PLAN FOR SELECT /*+ INDEX(t1) */ * FROM t1 WHERE source_id <= 5; SELECT * FROM TABLE(dbms_xplan.display); EXPLAIN PLAN FOR SELECT /*+ INDEX(t1) */ * FROM t1 WHERE source_id <= :a; SELECT * FROM TABLE(dbms_xplan.display);
There are various places where the optimizer uses an assumption, and lie unpeekable (and of Villa "unknowable value") introduced guess.
For unpeekable binds the conjecture for column<= {unknown}="" is="" 5%="" for="" table="" access="" (hence="" 50="" rows="" out="" of="" 1,000),="" but="" it's="" 0.009="" for="" index_column="">=><= {unknown},="" which="" means="" i="" was="" expecting="" to="" see="" 9="" as="" the="" row="" estimate="" on="" the="" index="" range="">=>
I just ran some quick tests, and EXPLAIN the PLAN seems to just use 0.011 selectivity in this case (in different versions of Oracle) although if we do the bind variable unpeekable at run time (and sample dynamic block etc.) optimization for execution is 0.009%.
Concerning
Jonathan Lewis
Update: and this is a very old reference to the 0.009 (and 0.0045 for ' between the ' when it is applied to a clue: cost based Oracle - access Chapter 4 single B-tree )
-
Difference between Index Full Scan, and Scan select Index Full
Quick Index Full Scan is an example of Index Full Scan, then what are the differences between Fast Full Index Scan and Index Full Scan. I have traveled the official documentation, but found it a bit complex, that no simple explanation will be great. Thanks in advance!
Go to http://tahiti.oracle.com, select database Oracle 11g Release 2 (11.2) enter fast full scan small index in the 'Search' box, you may decide to read the results of three or four, but the fourth is setting performance Guide: the query optimizer
Repeat the process for the analysis of comprehensive index of search term.
Concerning
Jonathan Lewis
-
Explain plan - index range scan lines increase while access to the table by the row id
I use Oracle9i Enterprise Edition Release 9.2.0.7.0 - 64 bit Production. Please help me understand why the rows returned from the index range scan is 3 but access the table by row index 10155 id. Please refer to explain the plan ID 7 and 8.
Thanks a lot for all the help...PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost | --------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 8308 | 446K| 4408 | | 1 | SORT ORDER BY | | 8308 | 446K| 4408 | |* 2 | HASH JOIN | | 8308 | 446K| 4316 | |* 3 | HASH JOIN | | 8189 | 255K| 2256 | |* 4 | INDEX FAST FULL SCAN | TUNE_CHD_07 | 8071 | 72639 | 199 | |* 5 | TABLE ACCESS BY INDEX ROWID| CLM_HDR_CLM_LN_STATUS | 10155 | 228K| 2055 | |* 6 | INDEX RANGE SCAN | XIF3CLM_HDR_CLM_LN_STATUS | 3 | | 120 | |* 7 | TABLE ACCESS BY INDEX ROWID | CLM_HDR_CLM_LN_STATUS | 10155 | 228K| 2055 | |* 8 | INDEX RANGE SCAN | XIF3CLM_HDR_CLM_LN_STATUS | 3 | | 120 | --------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("CHCLS"."CLAIM_HEADER_SID"="CHCLS1"."CLAIM_HEADER_SID") 3 - access("CHD"."CLAIM_HEADER_SID"="CHCLS"."CLAIM_HEADER_SID") 4 - filter("CHD"."CLM_TYPE_CID"=2) 5 - filter("CHCLS"."CLAIM_LINE_SID" IS NULL AND "CHCLS"."TO_DATE" IS NULL) 6 - access("CHCLS"."STATUS_TYPE_CID"=8 AND "CHCLS"."STATUS_CID"=71) 7 - filter("CHCLS1"."CLAIM_LINE_SID" IS NULL AND "CHCLS1"."TO_DATE" IS NULL) 8 - access("CHCLS1"."STATUS_TYPE_CID"=2 AND "CHCLS1"."STATUS_CID"=130) Note: cpu costing is off
-
Hi guys, I want to know how a Full Index Scan works in detail. It always parses the first block of sheets to the last block of sheets (all blocks) in the index, regardless of the place where the requirement is to say even if I have only one line satisfying the condition he analyzes all the index blocks?
You actually store what appear to be of the numbers in a column of type char?
My guess is that maybe done GOLD optimizer based on CSSTidy think that he cannot do a scan of the index systematic range
-
index range scan and full scan limited index
Hi master,
I always think to what is the difference between index scan and scan of comprehensive systematic index range...
comprehensive index analysis applied to the full index sheet, block and root structure.
How systematic index scan range works internally? How is it different from complete systematic index scan? When to use the scan of the index systematic range? which is expensive?
I like what internals discuss some docs on these, but nobody... someone knows about any link lewis j. wrote about these scans?
will be useful
Thanks and greetings
VDVikrant dixit says:
I always think to what is the difference between index scan and scan of comprehensive systematic index range...There is essentially no difference.
Based on a seed value, Oracle checks the root block using the partial keys stored to select which block from the next down level (typically a layer of blocks of branch) to go to.
Since the relevant branch block, she uses the partial keys to identify which block in the level down to go to (usually a block of sheets).
When he reached a block of sheets, it can find the first relevant key value, then scroll through the list of keys to jump to the table. If it reaches the end of the block of sheets, it uses the "next" pointer to reach the next block of relevant leaves.
Because the optimizer has enough information to establish a baseline and a final value for the analysis, the runtime can keep journal journal moving until it hits the sheet "stop".
The only difference between the full analysis and analysis of the range is the full scan down through the branches to the first sheet of the index and traverses the index to the last sheet. (Indeed, the starting value is less "Infinity" and the end value is "more Infinity".)
Concerning
Jonathan Lewis
http://jonathanlewis.WordPress.com
http://www.jlcomp.demon.co.UK"Science is more than a body of knowledge; It's a way of thinking"Carl Sagan
-
How to Auto poplulated fields of index for scanning profiles
HelloI worked on Webcenter Capture 11.1.1.8.0, we have recently configured profiles customer capture and we have also set up Email profiles and analyze the profile.
My concerns here, how to index get fields automatically filled for individual profiles of customers during the analysis of the images of the invoice.
currently I feed the index on manual work fields. We want to avoid the manual work and it must be filled by full Auto the index fields in the analysis of the invoice for each individual customer profiles. Different index values should appearance for differnent customer profiles.
the above requirement, is there configure everything can be done in Capture console. We must make this resolution with Console to capture only not to provide all the scripts. We do not want to use Scripts for this requirement.
Please help me. This something urgent for the business scenario.
If your question is: "How can I apply different default values of metadata based on the customer profile?" then I think that you will have to do so via the import processor (if you use is not a scanner), recognition or scripts custom.
You can set up a default for each metadata field, but this won't cut it for you.
You can probably do this through recognition jobs processor by creating a different one for each customer profile and defining your customer post-processor on his work of processor rcgn correspondent.
Hope this helps,
-ryan
-
scan of the index systematic range
Hello
I read about the differences between the systematic index scan range, single scan, skip scan.
According to the docs, to how the CBO Evaluates in-list of iterators, http://docs.oracle.com/cd/B10500_01/server.920/a96533/opt_ops.htm
, I can see that
"The
IN
-list iterator is used when a query contains aIN
clause with values." The execution plan is the same which would result for a statement of equality clause instead ofIN
with the exception of an extra step. This step occurs when theIN
-list iterator feeds section of equality with the unique values of theIN
-list. »Of course, the doc is Oracle9i Database. (I do not find it in the docs of 11 g)
And the example 2-1 list iterators initial statement, shows that is used in the INDEX RANGE SCAN.
On my Oracle 11 GR 2 database, if I issue a statement similar to the example of the doc, so: select * from employees where employee_id in (7076, 7009, 7902), I see that it uses a SINGLE SCAN
On Oracle Performance Tuning: the Index access methods: Oracle Tuning Tip #11: Unique Index Scan , I read that
If Oracle should follow the Index Unique Scan, and then in SQL, equality operator (=) must be used. If any operator is used in other than op_Equality, then Oracle cannot impose this Unique Index Scan.
(and I think this sentence is somewhere in the docs also).
Thus, when using predicates in the list, why in my case Oracle used the unique scan on primary key column index? Because it wasn't a level playing field.
Thank you.
It is Internet... find us a lot of information a lot but don't know who to trust.
Exactly! It is thought, you should ALWAYS have in the back of your mind when you visit ANY site (no matter the author), read a book or document, listen to no matter WHAT presentation or read responses from forum (that's me included).
All sources of information can and will be errors, omissions and inaccuracies. An example which is used to illustrate a point can involve/suggest that it applies to the related points as well. It's just not possible to cover everything.
Your post doc 9i is a good example. The earliest records (even 7.3 always available online docs) often have a LOT of better explanations and examples of basic concepts. One of the reasons is that there were not nearly that many advanced concepts that explaining necessary; they did not exist.
michaelrozar17 just posted a link to a 12 c doc to refute my statement that the article you used was bad. No problem. Maybe this doc has been published because of these lines:
The database performs a unique sweep when the following conditions apply:
- A query predicate refers to all columns in a unique index using an equality operator key, such as
WHERE prod_id=10
. - A SQL statement contains a predicate of equality on a column referenced in an index created with the
CREATE UNIQUE INDEX
statement.
The authors mean that a single scan is ONLY performed for these conditions? We do not know. There could be several reasons that an INLIST ITERATOR has not been included in this list:
1. a LIST is NOT for this use case (what michaelrozar might suggest)
2. the authors were not aware that the CBO may also consider a unique analysis for a predicate INLIST
3. the authors WERE aware but forgot to include INLIST in the document
4. the authors were simply provide the conditions most common where a single sweep would be considered
We have no way of knowing what was the real reason. This does not mean that the document is not reliable.
In the other topic, I posted on the analysis of hard steps, site of BURLESON, and Jonathan contradicted me. If neither Burleson isn't reliable, do not know which author have sufficient credibility... of course, the two Burleson and Jonathan can say anything, it's true I can say anything, of course.
If site X is false, site is fake, Z site is fake... all people should read the documentation only and not other sites?
This is the BEST statement of reality to find the info I've seen displayed.
No matter who is the author, and what credibility that they could rely on the spent items you should ALWAYS keep these statements you comes to mind.
This means you need to do ' trust and verify. " You of 'trust', and then you "checked" and now have a conflict between WORDS and REALITY.
On those which is correct. If your reality is correct, the documentation is wrong. Ok. If your reality is wrong, then you know why.
Except that nobody has posted ANY REALITY that shows that your reality is wrong. IMHO, the reason for this is because the CBO probably MUCH, done a LOT of things that are not documented and that are never explored because there is never no reason to spend time exploring other than of curiosity.
You have not presented ANY reason to think that you are really concerned that a single scan is used.
Back to your original question:
Thus, when using predicates in the list, why in my case Oracle used the unique scan on primary key column index? Because it wasn't a level playing field.
1. why not use a single sweep?
2. what you want Oracle to use instead? A full table scan? A scan of the index systematic range? An index skip scan? A Full Scan index? An analysis of index full?
A full table scan? For three key values? When there is a unique index? I hope not.
A scan of the index systematic range? Look a the doc 12 c provided for those other types of indexes
How the Index range scans work
In general, the process is as follows:
- Read the root block.
- Read the bundle branch block.
- Replacing the following steps until all data is retrieved:
Read a block of sheets to get a rowid.
- Read a block to retrieve a table row.
. . .
For example, to analyze the index, the database moves backward or forward through the pads of sheets. For example, an analysis of identifications between 20 and 40 locates the first sheet block that has the lowest value of key that is 20 or more. The analysis produced horizontally through the linked list nodes until it finds a value greater than 40 and then stops.If that '20' was the FIRST index value and the '40' was the LAST one who reads ALL of the terminal nodes. That doesn't look good for me.
How to index full scans of work
The database reads the root block and then sailed on the side of the index (right or left hand if do a descending full scan) until it reaches a block of sheets. The database then reads down the index, one block at a time, in a sorted order. The analysis uses single e/s rather than I/O diluvium.
Which is about as the last example is not?
How to index Fast Full Scans work
The database uses diluvium I/O to read the root block and all the blocks of leaf and branch. Databases don't know branch blocks and the root and reads the index on blocks of leaves entries.
Seems not much better than the last one for your use case.
Skip index scans
An index skip scan occurs when the first column of a composite index is "skipped" or not specified in the query.
. . .
How Index Skip scan work
An index skip scan logically divides a composite index in smaller subindex. The number of distinct values in the main columns of the index determines the number of logical subindex. The more the number, the less logical subindex, the optimizer should create, and becomes the most effective analysis. The scan reads each logical index separately and "jumps" index blocks that do not meet the condition of filter on the column no leader.
Which does not apply to your use cases; you do not have a composite index, and there is nothing to jump. If Oracle were to 'jump' between the values of the list in it would be still reads these blocks 'inbetween' and them to jump.
Which brings back us to the using a single scan, one at a time, for each of the values in the list in. The root index block will be in the cache after the first value lies, so it only needs to be read once. After that just Oracle detects that the entry of only ONE necessary index. Sounds better than any other variants for me if you are only dealing with a small number of values in the IN clause.
- A query predicate refers to all columns in a unique index using an equality operator key, such as
-
The doc is correct on the constraint not null and scan limited index full?
Gave birth to the large [url http://forums.oracle.com/forums/thread.jspa?messageID=9313643] another thread:
Jonathan Lewis wrote:
Just below where Hemant pointed to in the other thread, http://download.oracle.com/docs/cd/E11882_01/server.112/e16508/indexiot.htm#sthref314
>
I wasn't expecting to see because the doc said about scan limited index full "...". and at least one column in the index key has the NOT NULL constraint,"which would be foolish to say if the rowid was what filled that. There are currently only 2 factory codes and code 1 company (not nulls - Oracle does know that?), so I was kind of expected Oracle to reorder the predicates with an index skip scan. Take a fresh look on the doc, I wonder if I should not specify the company code in the query and maybe spend employee and job_number in the index. I hope it's obvious that this index has been added for other queries. This request could be taken out a change in the requirements of anyway, but I don't know when.
If you wear it as a separate thread, I'll take a look.
Can you give a reference to the manual - the comment you quoted may not be correct.
(Somehow I have the feeling that we had this conversation before, perhaps in a forum that no longer exists. "(Or was it all just a dream)."
Edit: Also seen in
http://download.Oracle.com/docs/CD/B28359_01/server.111/b28274/optimops.htm#i52044
http://download.Oracle.com/docs/CD/B14117_01/server.101/b10752/optimops.htm#51111
http://download.Oracle.com/docs/CD/F49540_01/doc/server.815/a67781/c20b_ops.htm#11004
http://download.Oracle.com/docs/CD/B19306_01/server.102/b14211/optimops.htm#i52044
and everything on the net.
Edited by: jgarry 26 January 2011 17:41
2nd edition: link fix that edit may 1 have ransacked.
Edited by: jgarry January 27, 2011 10:40Joel,
I just had this 'already seen' (new) sense to speak of it.
Mentioning the reference 11.1 gave you:
+ "Index full scans are an alternative to a full table scan when the index contains all the columns needed for the query, and at least in the index key column has the constraint NOT NULL. A full scan can access the data of the index itself, without access to the table ' + '.
This so obviously must be bad that I couldn't decide if I was proven wrong or was amazed to find that I couldn't he show the falsity. (Just because something is obvious, it does not mean it is true – Terry Pratchett.)
However, here is the obvious counter-example - that I came across 8.1.7.4 because it's the oldest version of Oracle that I have now:
create table t1 as select rownum id1, rownum id2, rownum id3, lpad(rownum,10,'0') small_vc, rpad('x',100) padding from all_objects where rownum <= 10000 ; create index t1_i1 on t1(id1, id2, id3); begin dbms_stats.gather_table_stats( ownname => user, tabname =>'T1', cascade => true ); end; / set autotrace traceonly explain select /*+ index_ffs(t1) */ id1, id3 from t1 where id2 = 99 ;
No 'NOT NULL columns". But any line I will have a (non-null) value for id2, then it should be in the index - then Oracle should be able to do a full scan and get the right answer. Here is the map (I have no need of Council - but your configuration may be different):
Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=4 Card=1 Bytes=12) 1 0 INDEX (FAST FULL SCAN) OF 'T1_I1' (NON-UNIQUE) (Cost=4 Card=1 Bytes=12)
If you change the predicate to: "id2 is zero", then the only legal path is an analysis.
Concerning
Jonathan Lewis
http://jonathanlewis.WordPress.com
http://www.jlcomp.demon.co.UK+ "I believe in the evidence. I believe in observation, measurement and reasoning, confirmed by independent observers. I'll believe anything, no matter how wild and ridiculous, if there is evidence for it. The wildest and most ridiculous something is, however, the firmer and more solid, the evidence should be. » +
Isaac Asimov -
Version of DB: database Oracle 11 g Enterprise Edition Release 11.2.0.3.0 - 64 bit Production
I have a table my_table as below:
create table my_table
(
my_code varchar2 (6).
my_id varchar2 (24).
forced pk_1 primary key (my_code, my_id)
);
Primary_key here's a composite key that contains columns 1 (my_code) and 2 (my_id).
Is there that a difference in the way below queries is executed in terms of performance (use of indexing in the extraction).(a) select * from my_table where my_code = '123' and my_id = "456";
(b) select * from my_table where my_id = '456' and my_code = '123';
The understanding I have the order of the column in the where clause should be identical to the sequence in
What primary key draws for indexing to be used by oracle in oracle other DML queries ignores indexing
However when I used explain plain both show the same query cost with single scan with index rowid.
so I don't know if I'm wrong in the concept that I have. Kindly help.Thanks in advance,
GerardYour question is answered in the Performance Tuning Guide
14.1.4 choosing composite indexes
A composite index contains several key columns. Composite indexes can provide additional benefits compared to the index to single column:
- Improved selectivity
Sometimes the two or more columns or expressions, each with a low selectivity can be combined to form a composite with a high selectivity.
- Reduced IO
If all columns selected by a query are a composite index, then Oracle may return these values in the index without access to the table.
A SQL statement can use a path on a composite index if the statement contains constructions that use a main part of the index.
Note:
This is no longer the case with the skip index scans. See "Index Skip Scans".
A main part of an index is a set of one or more columns that have been specified first and consecutively in the list of columns in the
CREATE
INDEX
statement that created the index. - Improved selectivity
Maybe you are looking for
-
Favorites bar photostream missing links to explore
Nice day! I accidentally deleted icloud / photostream links in the "Favorites" in the Explorer section - and there is no way to recover them. I tried everything, even complete wipe iTunes and all the remaining registry entries, but no luck. I often u
-
How to leave a Web site without closing FireFox?
When I want to close a page of the Web site at the top of the screen, it closes Firefox instead, and I have toreopen it. How can I close only the current web page and not Firefox?
-
I use Firefox 5.0 on a MacBook with Snow Leopard. I have always used the latest version of Firefox, but I'm not 100% sure if the problem is with the update to 5.0 or later.I can't uninstall or update the modules in this way, which is quite annoying.
-
Satellite P750-114 - extension of battery?
Hello I was wondering if there is an extended battery available for Satellite P750-114. I can't find one on the Toshiba site. Are there any other sources I was able to find one?Thank you
-
Satellite A200-1 to 9 - not possible to read the 2 GB SD card
Hi all I have a new laptop Satellite A200 from 1 to 9 on Vista premium, with a multicard reader. I am using a 2 GB SD card, which, according to the user's guide, must be supported. However, when I put in, it is not upward on explore, even if the comp