Why it is taking full table scan when index is available
Hi all,
I am facing a strange problem with index.
I created index on a column like
1. CREATE INDEX ASSETS_ARTIST_IDX2 ON ASSETS(artist).
SELECT asset.artist AS NAME FROM ASSETS asset WHERE asset.artist LIKE 'J%'
Explain Plan : INDEX RANGE SCAN
2. CREATE INDEX ASSETS_ARTIST_IDX2 ON ASSETS(UPPER (TRANSLATE (artist, ',;:"', ' ')));
SELECT asset.artist AS NAME FROM ASSETS asset WHERE UPPER (TRANSLATE (artist, ',;:"', ' ')) LIKE 'J%'
Explain Plan : TABLE ACCESS FULL
first time it is taking index range scan,but in second situation scaning full table.Please let me know how to avoid the full table scan.
Regards,
Rajasekhar
Actually, I misseunderstood damorgan' s statement about NULL and OP did not provide table definition. So based on FTS I would say it is more likely column is NULLable, otherwise I would expect INDEX FAST SCAN:
SQL> create table emp1 as select * from emp
2 /
Table created.
SQL> create index emp1_idx1 on emp1(empno)
2 /
Index created.
SQL> exec dbms_stats.gather_table_stats('SCOTT','EMP1');
PL/SQL procedure successfully completed.
SQL> desc emp1
Name Null? Type
EMPNO NUMBER(4)
ENAME VARCHAR2(10)
JOB VARCHAR2(9)
MGR NUMBER(4)
HIREDATE DATE
SAL NUMBER(7,2)
COMM NUMBER(7,2)
DEPTNO NUMBER(2)
SQL> explain plan for
2 select empno
3 from emp1 where UPPER(TRANSLATE(empno, ',;:"', ' ')) LIKE '7%'
4 /
Explained.
SQL> @?\rdbms\admin\utlxpls
PLAN_TABLE_OUTPUT
Plan hash value: 2226897347
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 4 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| EMP1 | 1 | 4 | 3 (0)| 00:00:01 |
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
1 - filter(UPPER(TRANSLATE(TO_CHAR("EMPNO"),',;:"',' ')) LIKE '7%')
13 rows selected.
SQL> alter table emp1 modify empno not null
2 /
Table altered.
SQL> explain plan for
2 select empno
3 from emp1 where UPPER(TRANSLATE(empno, ',;:"', ' ')) LIKE '7%'
4 /
Explained.
SQL> @?\rdbms\admin\utlxpls
PLAN_TABLE_OUTPUT
Plan hash value: 2850860361
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 4 | 1 (0)| 00:00:01 |
|* 1 | INDEX FULL SCAN | EMP1_IDX1 | 1 | 4 | 1 (0)| 00:00:01 |
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
1 - filter(UPPER(TRANSLATE(TO_CHAR("EMPNO"),',;:"',' ')) LIKE '7%')
13 rows selected.
SQL> SY.
Similar Messages
-
How to avoid full Table scan when using Rule based optimizer (Oracle817)
1. We have a Oracle 8.1.7 DB, and the optimizer_mode is set to "RULE"
2. There are three indexes on table cm_contract_supply, which is a large table having 28732830 Rows, and average row length 149 Bytes
COLUMN_NAME INDEX_NAME
PROGRESS_RECID XAK11CM_CONTRACT_SUPPLY
COMPANY_CODE XIE1CM_CONTRACT_SUPPLY
CONTRACT_NUMBER XIE1CM_CONTRACT_SUPPLY
COUNTRY_CODE XIE1CM_CONTRACT_SUPPLY
SUPPLY_TYPE_CODE XIE1CM_CONTRACT_SUPPLY
VERSION_NUMBER XIE1CM_CONTRACT_SUPPLY
CAMPAIGN_CODE XIF1290CM_CONTRACT_SUPPLY
COMPANY_CODE XIF1290CM_CONTRACT_SUPPLY
COUNTRY_CODE XIF1290CM_CONTRACT_SUPPLY
SUPPLIER_BP_ID XIF801CONTRACT_SUPPLY
COMMISSION_LETTER_CODE XIF803CONTRACT_SUPPLY
COMPANY_CODE XIF803CONTRACT_SUPPLY
COUNTRY_CODE XIF803CONTRACT_SUPPLY
COMPANY_CODE XPKCM_CONTRACT_SUPPLY
CONTRACT_NUMBER XPKCM_CONTRACT_SUPPLY
COUNTRY_CODE XPKCM_CONTRACT_SUPPLY
SUPPLY_SEQUENCE_NUMBER XPKCM_CONTRACT_SUPPLY
VERSION_NUMBER XPKCM_CONTRACT_SUPPLY
3. We are querying the table for a particular contract_number and version_number. We want to avoid full table scan.
SELECT /*+ INDEX(XAK11CM_CONTRACT_SUPPLY) */
rowid, pms.cm_contract_supply.*
FROM pms.cm_contract_supply
WHERE
contract_number = '0000000000131710'
AND version_number = 3;
However despite of giving hint, query results are fetched after full table scan.
Execution Plan
0 SELECT STATEMENT Optimizer=RULE (Cost=1182 Card=1 Bytes=742)
1 0 TABLE ACCESS (FULL) OF 'CM_CONTRACT_SUPPLY' (Cost=1182 Card=1 Bytes=742)
4. I have tried giving
SELECT /*+ FIRST_ROWS + INDEX(XAK11CM_CONTRACT_SUPPLY) */
rowid, pms.cm_contract_supply.*
FROM pms.cm_contract_supply
WHERE
contract_number = '0000000000131710'
AND version_number = 3;
and
SELECT /*+ CHOOSE + INDEX(XAK11CM_CONTRACT_SUPPLY) */
rowid, pms.cm_contract_supply.*
FROM pms.cm_contract_supply
WHERE
contract_number = '0000000000131710'
AND version_number = 3;
But it does not work.
Is there some way without changing optimizer mode and without creating an additional index, we can use the index instead of full table scan?David,
Here is my test on a Oracle 10g database.
SQL> create table mytable as select * from all_tables;
Table created.
SQL> set autot traceonly
SQL> alter session set optimizer_mode = choose;
Session altered.
SQL> select count(*) from mytable;
Execution Plan
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (FULL) OF 'MYTABLE' (TABLE)
Statistics
1 recursive calls
0 db block gets
29 consistent gets
0 physical reads
0 redo size
223 bytes sent via SQL*Net to client
276 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> analyze table mytable compute statistics;
Table analyzed.
SQL> select count(*) from mytable
2 ;
Execution Plan
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=11 Card=1)
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (FULL) OF 'MYTABLE' (TABLE) (Cost=11 Card=1
788)
Statistics
1 recursive calls
0 db block gets
29 consistent gets
0 physical reads
0 redo size
222 bytes sent via SQL*Net to client
276 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> disconnect
Disconnected from Oracle Database 10g Enterprise Edition Release 10.1.0.2.0 - 64bit Production
With the Partitioning, Oracle Label Security, OLAP and Data Mining options -
How to avoid this full table scan (and index FFS) ?
Hi All,
Oracle 11.2 on Linux.
See this query and its plan below
SQL> DELETE
2 FROM TABLEA APE
3 WHERE NOT EXISTS
4 (SELECT 1
5 FROM TABLEB AP
6 WHERE AP.col1 = APE.col1
7 AND AP.col2 = APE.col2
8 AND AP.col3 = APE.col3)
9 AND ROWNUM < 51 ;
50 rows deleted.
Elapsed: 00:12:01.07
Execution Plan
Plan hash value: 1740911877
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
| 0 | DELETE STATEMENT | | 50 | 2650 | | 573K (1)| 01:54:40 |
| 1 | DELETE | TABLEA | | | | | |
|* 2 | COUNT STOPKEY | | | | | | |
|* 3 | HASH JOIN RIGHT ANTI | | 80M| 4059M| 1775M| 573K (1)| 01:54:40 |
| 4 | INDEX FAST FULL SCAN| TABLEB_UK | 47M| 1228M| | 96480 (1)| 00:19:18 |
| 5 | TABLE ACCESS FULL | TABLEA | 80M| 1991M| | 243K (1)| 00:48:42 |
---------------------------------------------------------------------------------------------------------In both tables, TABLEA and TABLEB, there is index on columns col1-col2-col3 as leading columns (TABLEB has few more columns in the index, but after these 3 columns).
Requirement is, I want to delete first 50 records in TABLEA, which does not exist in TABLEB.
I tried with various hints, but Oracle is always doing a full scan on one of the tables and index FFS on other. In some cases, Oracle did full scan on both tables and then deleted 50 records. Stats is up-to-date. Doing a full scan on tables with 80 million and 47 million rows is a bit too much for deleting 50 rows.
How I can make Oracle do
1) Read TABLEA row-by-row
2) for each row, check if it exists in TABLEB
3) If not exists, then delete row from TABLEA, else continue
4) Stop reading TABLEA after we have deleted 50 records
Thanks in advance>
>
Oracle 11.2 on Linux.
SQL> DELETE
2 FROM TABLEA APE
3 WHERE NOT EXISTS
4 (SELECT 1
5 FROM TABLEB AP
6 WHERE AP.col1 = APE.col1
7 AND AP.col2 = APE.col2
8 AND AP.col3 = APE.col3)
9 AND ROWNUM < 51 ;
50 rows deleted.
Elapsed: 00:12:01.07
Execution Plan
Plan hash value: 1740911877
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
| 0 | DELETE STATEMENT | | 50 | 2650 | | 573K (1)| 01:54:40 |
| 1 | DELETE | TABLEA | | | | | |
|* 2 | COUNT STOPKEY | | | | | | |
|* 3 | HASH JOIN RIGHT ANTI | | 80M| 4059M| 1775M| 573K (1)| 01:54:40 |
| 4 | INDEX FAST FULL SCAN| TABLEB_UK | 47M| 1228M| | 96480 (1)| 00:19:18 |
| 5 | TABLE ACCESS FULL | TABLEA | 80M| 1991M| | 243K (1)| 00:48:42 |
---------------------------------------------------------------------------------------------------------Requirement is, I want to delete first 50 records in TABLEA, which does not exist in TABLEB.
Such requirements usually make me curious - what's special about a randomly selected 50 rows ?
Is this trying to delete the data in batches of 50 rows at a time.
How I can make Oracle do
1) Read TABLEA row-by-row
2) for each row, check if it exists in TABLEB
3) If not exists, then delete row from TABLEA, else continue
4) Stop reading TABLEA after we have deleted 50 records
It look's as if a 'no_unnest' hint in the subquery should do what you want. It should make Oracle run the quey with a FILTER subquery. You could then choose to drive the delete through a tablescan of tableA or an index range scan of the index on tableA. Have you considered the effect of (and requirements relating to) nulls in the three columns of either table ?
Regards
Jonathan Lewis
http://jonathanlewis.wordpress.com
Author: <b><em>Oracle Core</em></b> -
VARRAY bind parameter in IN clause causes Full Table Scan
Hi
My problem is that Oracle elects to perform a full table scan when I want it to use an index.
The situation is this: I have a single table SQL query with an IN clause such as:
SELECT EMPNO, ENAME, JOB FROM EMP WHERE ENAME IN (...)
Since this is running in an application, I want to allow the user to provide a list of ENAMES to search. Because IN clauses don't accept bind parameters I've been using the Tom Kyte workaround which relies on setting a bind variable to an array-valued scalar, and then casting this array to be a table of records that the database can handle in an IN clause:
SELECT *
FROM EMP
WHERE ENAME IN (
SELECT *
FROM TABLE(CAST( ? AS TABLE_OF_VARCHAR)))
This resulted in very slow performance due to a full table scan. To test, I ran the SQL in SQL*Plus and provided the IN clause values in the query itself. The explain plan showed it using my index...ok good. But once I changed the IN clause to the 'select * from table...' syntax Oracle went into Full Scan mode. I added an index hint but it didn't change the plan. Has anyone had success using this technique without a full scan?
Thanks
John
p.s.
Please let me know if you think this should be posted on a different forum. Even though my context is a Java app developed with JDev this seemed like a SQL question.Justin and 3360 - that was great advice and certainly nothing I would have come up with. However, as posted, the performance still wasn't good...but it gave me a term to Google on. I found this Ask Tom page http://asktom.oracle.com/pls/ask/f?p=4950:8:::::F4950_P8_DISPLAYID:3779680732446#15740265481549, where he included a seemingly magical 'where rownum >=0' which, when applied with your suggestions, turned my query from minutes into seconds.
My plans are as follows:
1 - Query with standard IN clause
SQL> explain plan for
2 select accession_number, protein_name, sequence_id from protein_dim
3 where accession_number in ('33460', '33458', '33451');
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
| Id | Operation | Name | Rows | Bytes | Cost |
| 0 | SELECT STATEMENT | | 7 | 336 | 4 |
| 1 | INLIST ITERATOR | | | | |
| 2 | TABLE ACCESS BY INDEX ROWID| PROTEIN_DIM | 7 | 336 | 4 |
| 3 | INDEX RANGE SCAN | IDX_PROTEIN_ACCNUM | 7 | | 3 |
Note: cpu costing is off, 'PLAN_TABLE' is old version
11 rows selected.
2 - Standard IN Clause with Index hint
SQL> explain plan for
2 select /*+ INDEX(protein_dim IDX_PROTEIN_ACCNUM) */
3 accession_number, protein_name, sequence_id, taxon_id, organism_name, data_source
4 from pdssuser.protein_dim
5 where accession_number in
6 ('33460', '33458', '33451');
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
| Id | Operation | Name | Rows | Bytes | Cost |
| 0 | SELECT STATEMENT | | 7 | 588 | 4 |
| 1 | INLIST ITERATOR | | | | |
| 2 | TABLE ACCESS BY INDEX ROWID| PROTEIN_DIM | 7 | 588 | 4 |
| 3 | INDEX RANGE SCAN | IDX_PROTEIN_ACCNUM | 7 | | 3 |
Note: cpu costing is off, 'PLAN_TABLE' is old version
11 rows selected.
3 - Using custom TABLE_OF_VARCHAR type
CREATE TYPE TABLE_OF_VARCHAR AS
TABLE OF VARCHAR2(50);
SQL> explain plan for
2 select
3 accession_number, protein_name, sequence_id, taxon_id, organism_name, data_source
4 from pdssuser.protein_dim
5 where accession_number in
6 (select * from table(cast(TABLE_OF_VARCHAR('33460', '33458', '33451') as TABLE_OF_VARCHAR)) t);
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
| Id | Operation | Name | Rows | Bytes | Cost |
| 0 | SELECT STATEMENT | | 2 | 168 | 57M|
| 1 | NESTED LOOPS SEMI | | 2 | 168 | 57M|
| 2 | TABLE ACCESS FULL | PROTEIN_DIM | 5235K| 419M| 13729 |
| 3 | COLLECTION ITERATOR CONSTRUCTOR FETCH| | | | |
Note: cpu costing is off, 'PLAN_TABLE' is old version
11 rows selected.
4 - Using custom TABLE_OF_VARCHAR type w/ Index hint
SQL> explain plan for
2 select /*+ INDEX(protein_dim IDX_PROTEIN_ACCNUM) */
3 accession_number, protein_name, sequence_id, taxon_id, organism_name, data_source
4 from pdssuser.protein_dim
5 where accession_number in
6 (select * from table(cast(TABLE_OF_VARCHAR('33460', '33458', '33451') as TABLE_OF_VARCHAR)) t);
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
| Id | Operation | Name | Rows | Bytes | Cost |
| 0 | SELECT STATEMENT | | 2 | 168 | 57M|
| 1 | NESTED LOOPS SEMI | | 2 | 168 | 57M|
| 2 | TABLE ACCESS BY INDEX ROWID | PROTEIN_DIM | 5235K| 419M| 252K|
| 3 | INDEX FULL SCAN | IDX_PROTEIN_ACCNUM | 5235K| | 17255 |
| 4 | COLLECTION ITERATOR CONSTRUCTOR FETCH| | | | |
PLAN_TABLE_OUTPUT
Note: cpu costing is off, 'PLAN_TABLE' is old version
12 rows selected.
5 - Using custom TABLE_OF_VARCHAR type w/ cardinality hint
SQL> explain plan for
2 select
3 accession_number, protein_name, sequence_id, taxon_id, organism_name, data_source from protein_dim
4 where accession_number in (select /*+ cardinality( t 10 ) */
5 * from TABLE(CAST (TABLE_OF_VARCHAR('33460', '33458', '33451') AS TABLE_OF_VARCHAR)) t);
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
| Id | Operation | Name | Rows | Bytes | Cost |
| 0 | SELECT STATEMENT | | 2 | 168 | 57M|
| 1 | NESTED LOOPS SEMI | | 2 | 168 | 57M|
| 2 | TABLE ACCESS FULL | PROTEIN_DIM | 5235K| 419M| 13729 |
| 3 | COLLECTION ITERATOR CONSTRUCTOR FETCH| | | | |
Note: cpu costing is off, 'PLAN_TABLE' is old version
11 rows selected.
6 - Using custom TABLE_OF_VARCHAR type w/ cardinality hint
and rownum >= 0 constraint
SQL> explain plan for
2 select
3 accession_number, protein_name, sequence_id, taxon_id, organism_name, data_source from protein_dim
4 where accession_number in (select /*+ cardinality( t 10 ) */
5 * from TABLE(CAST (TABLE_OF_VARCHAR('33460', '33458', '33451') AS TABLE_OF_VARCHAR)) t
6 where rownum >= 0);
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
| Id | Operation | Name | Rows | Bytes | Cost |
| 0 | SELECT STATEMENT | | 25 | 2775 | 43 |
| 1 | TABLE ACCESS BY INDEX ROWID | PROTEIN_DIM | 2 | 168 | 3 |
| 2 | NESTED LOOPS | | 25 | 2775 | 43 |
| 3 | VIEW | VW_NSO_1 | 10 | 270 | 11 |
| 4 | SORT UNIQUE | | 10 | | |
| 5 | COUNT | | | | |
| 6 | FILTER | | | | |
PLAN_TABLE_OUTPUT
| 7 | COLLECTION ITERATOR CONSTRUCTOR FETCH| | | | |
| 8 | INDEX RANGE SCAN | IDX_PROTEIN_ACCNUM | 2 | | 2 |
Note: cpu costing is off, 'PLAN_TABLE' is old version
16 rows selected.
I don't understand why performance improved so dramatically but happy that it did.
Thanks a ton!
John -
Data Federator Full Table scan
Hi,
Is it possible to prevent a Full table scan when creating a join between tables of 2 catalogues in a Data Federator?
This is seriously hampering the development time within Data Federator Development.
I am working with IDT Beta to create a Universe based on Multiple Source. The delay is so huge when creating joins that we could revert to Universe Design Tool. I have posted it here as Data Federator gurus will have tweak about IDT as it incorporates DF within itself in BI 4.0.
Any inputs will be great.. In case this is in the wrong forums, then please move it accordingly.
VFernandesThe issue was fixed when the GA was released. This was present in Beta
-
Function based indexes doing full table scan
Guys,
I am testing function based indexes and whatever I do
it is doing a full table scan.
1)I have set the following init parameters as
QUERY_REWRITE_ENABLED=TRUE
QUERY_REWRITE_INTEGRITY=TRUSTED
2)CREATE INDEX i3 ON emp(UPPER(ename));
3) ANALYZE TABLE emp COMPUTE STATISTICS
ANALYZE INDEX I3 COMPUTE STATISTICS
4) DELETE plan_table;
5) EXPLAIN PLAN SET statement_id='Test1' FOR
SELECT ename FROM emp WHERE UPPER(ename) = 'KING';
6) SELECT LPAD(' ',2*level-2)||operation||' '||options||' '||object_name
query_plan
FROM plan_table
WHERE statement_id='Test1'
CONNECT BY prior id = parent_id
START WITH id = 0 order by id
7) And the query plan shows as
SELECT STATEMENT
TABLE ACCESS FULL EMP
I am using 9.0.1.4 !!!
Any help is appreciated !!!
Regards,
A.KishoreOne of the many new features in Oracle 8i is the Function-Based Index (we will refrain from using FBI, but only just). This allows the DBA to create indexes on functions or expressions; these functions can be user generated pl/sql functions, standard SQL functions (non-aggregate only) or even a C callout.
A classic problem the DBA faces in SQL Tuning is how to tune those queries that use function calls in the where clause, and result in indexes created on these columns not to be used.
Example
Standard B-Tree index on SURNAME with cost based optimizer
create index non_fbi on sale_contacts (surname);
analyze index non_fbi compute statistics;
analyze table sale_contacts compute statistics;
SELECT count(*) FROM sale_contacts
WHERE UPPER(surname) = 'ELLISON';
Execution Plan
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=3 Card=1 Bytes=17)
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (FULL) OF 'SALES_CONTACTS' (Cost=3 Card=16 Bytes=272)
Now we use a function based index
create index fbi on sale_contacts (UPPER(surname));
analyze index fbi compute statistics;
analyze table sale_contacts compute statistics;
SELECT count(*) FROM sale_contacts WHERE UPPER(surname) = 'ELLISON';
Execution Plan
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=17)
1 0 SORT (AGGREGATE)
2 1 INDEX (RANGE SCAN) OF 'FBI' (NON-UNIQUE) (Cost=2 Card=381 Bytes=6477)
The function-based index has forced the optimizer to use index range scans (retuning zero or more rowids) on the surname column rather than doing a full table scan (non-index lookup). Optimal performance does vary depending on table size, uniqueness and selectivity of columns, use of fast full table scans etc. Therefore try both methods to gain optimal performance in your database.
It is important to remember that the function-based B*Tree index does not store the expression results in the index but uses an "expression tree". The optimizer performs expression matching by parsing the expression used in the SQL statement and comparing the results against the expression-tree values in the function-based index. This comparison IS case sensitive (ignores spaces) and therefore your function-based index expressions should match expressions used in the SQL statement where clauses.
Init.ora Parameters
The following parameter must be set in your parameter file: QUERY_REWRITE_INTEGRITY = TRUSTED
QUERY_REWRITE_ENABLED = TRUE
COMPATIBLE = 8.1.0.0.0 (or higher)
Grants
Grants To create function-based indexes the user must be granted CREATE INDEX and QUERY REWRITE, or alternatively be granted CREATE ANY INDEX and GLOBAL QUERY REWRITE. The index owner must have EXECUTE access on the function used for the index. If execute access is revoked then the function-based index will be "disabled" (see dba_indexes).
Disabled Indexes
If your function-based index has a status of "disabled" the DBA can do one of the following:
a) drop and create the index (take note of its current settings)
b) alter index enable, function-based indexes only, also use disable keyword as required
c) alter index unusable.
Queries on a DISABLED index fail if the optimizer chooses to use the index.Here is an example ORA error:
ERROR at line 1: ORA-30554: function-based index MYUSER.FBI is disabled.
All DML operations on a DISABLED index also fail unless the index is also marked UNUSABLE and the initialization parameter SKIP_UNUSABLE_INDEXES is set to true.
Some more Examples
CREATE INDEX expression_ndx
ON mytable ((mycola + mycolc) * mycolb);
SELECT mycolc FROM mytable
WHERE (mycola + mycolc) * mycolb <= 256;
..or a composite index..
CREATE INDEX example_ndx
ON myexample (mycola, UPPER(mycolb), mycolc);
SELECT mycolc FROM myexample
WHERE mycola = 55 AND UPPER(mycolb) = 'JONES';
Restriction & Rule Summary
The following restrictions apply to function based indexes. You may not index:
a) LOB columns
b) REF
c) Nested table column
d) Objects types with any of the above data types.
Function-based indexes must always follow these rules:
a) Cost Based optimizer only, must generate statistics after the index is created
b) Can not store NULL values (function can not return NULL under any circumstance)
c) If a user defined pl/sql routine is used for the function-based index, and is invalidated, the index will become "disabled"
d) Functions must be deterministic (always return the same value for a known input)
e) The index owner must have "execute" access on function used in the function-based index. Revocation of the privilege will render the index "disabled"
f) May have a B-Tree and Bitmap index type only
g) Can not use expressions that are based on aggregate functions, ie. SUM, AVG etc.
h) To alter a function-based index as enabled, the function used must be valid, deterministic and the signature of the function matches the signature of the function when it was created.
Joel P�rez -
Bitmap index column goes for full table scan
Hi all,
Database : 10g R2
OS : Windows xp
my select query is :
SELECT tran_id, city_id, valid_records
FROM transaction_details
WHERE type_id=101;
And the Explain Plan is :
Plan
SELECT STATEMENT ALL_ROWSCost: 29 Bytes: 8,876 Cardinality: 634
1 TABLE ACCESS FULL TABLE TRANSACTION_DETAILS** Cost: 29 Bytes: 8,876 Cardinality: 634
total number of rows in the table = 1800 ;
distinct value of type_ids are 101,102,103
so i created a bit map index on it.
CREATE BITMAP INDEX btmp_typeid ON transaction_details
(type_id)
LOGGING
NOPARALLEL;
after creating the index, the explain plan shows the same. why it goes for full table scan?.
Kindly share ur idea on this.
Edited by: 887268 on Apr 3, 2013 11:01 PM
Edited by: 887268 on Apr 3, 2013 11:02 PM>
I am sorry for being ignorant, can you please cite any scenario of locking due to bitmap indices? A link can be useful as well.
>
See my full reply in this thread
Bitmap index for FKs on Fact tables
>
ETL is affected because DML operations (INSERT/UPDATE/DELETE) on tables with bitmapped indexes can have serious performance issues due to the serialization involved. Updating a single bit-mapped column value (e.g. from 'M' to 'F' for gender) requires both bitmapped index blocks to be locked until the update is complete. A bitmap index stored ROWID ranges (min rowid - max rowid) than can span many, many records. The entire 'range' of rowids is locked in order to change just one value.
To change from 'M' the 'M' rowid range for that one row is locked and the ROWID must be removed from the range byt clearing the bit. To change to 'F' the 'F' rowid id range needs to be found, locked and the bit set that corresponds to that rowid. No other rows with rowids in the range can be changed since this is a serial operation. If the range includes 1000 rows and they all need changed it takes 1000 serial operations. -
Source(oracle 11g) with oracle 8i using db link with full table scan
Hi,
I'm using oracle 8i version and i'm facing some issue while using DBlinks.
SourceDB1 I'm using oracle 8i(Source)
select * from tab1
tabl where id in
(select id from stab1@SourceDB1 where updt_seq_num > 167720 and work_grp_id in (2900,2901))
For this, I could able to retrive the data.
but, today we have migrated one of our source from oracle 8i to oracle 11G
when I'm executing
select * from tab2
tabl where id in
(select id from stab2@SourceDB2 where updt_seq_num > 167720 and work_grp_id in (2900,2901))
we couldn't able to retrive data as it's scaning full table scan.
when oracle 8i source it's scanning using INDEX scan but if the source oracle 11 h it's scanning full table scan.
Could you please advise how to resolve this issue for source oracle 11i ?
Please let us know, if you need any information.Blocks that are read via full table scans are stored in the buffer cache, but putting them at the MRU end ensures that they don't push the rest of the useful blocks out of the buffer cache. In your example, if you're full scanning a 2 GB table (T) with a 500 MB buffer cache, the first block that is read from T is put at the MRU end of the buffer cache, displacing the previous block that was at the MRU end of the cache. The next block that is read from T is also put at the MRU end of the buffer cache, displacing the previous block that was at the MRU end of the cache, so block #2 from T displaces block #1 from T. So, you're reading 2 GB of data, but you're constantly purging the older blocks, so you're only really using that last block of the buffer cache.
Justin -
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? -
Why does not a query go by index but FULL TABLE SCAN
I have two tables;
table 1 has 1400 rwos and more than 30 columns , one of them is named as 'site_code' , a index was created on this column;
table 2 has more 150 rows than 20 column , this primary key is 'site_code' also.
the two tables were analysed by dbms_stats.gather_table()...
when I run the explain for the 2 sqls below:
select * from table1 where site_code='XXXXXXXXXX';
select * from table1 where site_code='XXXXXXXXXX';
certainly the oracle explain report show that 'Index scan'
but the problem raised that
I try to explain the sql
select *
from table1,table2
where 1.'site_code'=2.'site_code'
the explain report that :
select .....
FULL Table1 Scan
FULL Table2 Scan
why......Nikolay Ivankin wrote:
BluShadow wrote:
Nikolay Ivankin wrote:
Try to use hint, but I really doubt it will be faster.No, using hints should only be advised when investigating an issue, not recommended for production code, as it assumes that, as a developer, you know better than the Oracle Optimizer how the data is distributed in the data files, and how the data is going to grow and change over time, and how best to access that data for performance etc.Yes, you are absolutly right. But aren't we performing such an investigation, are we? ;-)The way you wrote it, made it sound that a hint would be the solution, not just something for investigation.
select * from .. always performs full scan, so limit your query.No, select * will not always perform a full scan, that's just selecting all the columns.
A select without a where clause or that has a where clause that has low selectivity will result in full table scans.But this is what I have ment.But not what you said. -
Why does query do a full table scan?
I have a simple select query that filters on the last 10 or 11 days of data from a table. In the first case it executes in 1 second. In the second case it is taking 15+ minutes and still not done.
I can tell that the second query (11 days) is doing a full table scan.
- Why is this happening? ... I guess some sort of threshold calculation???
- Is there a way to prevent this? ... or encourage Oracle to play nice.
I find it confusing from a front end/query perspective to get vastly different performance.
Jason
Oracle 10g
Quest Toad 10.6
CREATE TABLE delme10 AS
SELECT *
FROM ed_visits
WHERE first_contact_dt >= TRUNC(SYSDATE-10,'D');
Plan hash value: 915912709
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | CREATE TABLE STATEMENT | | 4799 | 5534K| 4951 (1)| 00:01:00 |
| 1 | LOAD AS SELECT | DELME10 | | | | |
| 2 | TABLE ACCESS BY INDEX ROWID| ED_VISITS | 4799 | 5534K| 4796 (1)| 00:00:58 |
|* 3 | INDEX RANGE SCAN | NDX_ED_VISITS_020 | 4799 | | 15 (0)| 00:00:01 |
Predicate Information (identified by operation id):
3 - access("FIRST_CONTACT_DT">=TRUNC(SYSDATE@!-10,'fmd'))
CREATE TABLE delme11 AS
SELECT *
FROM ed_visits
WHERE first_contact_dt >= TRUNC(SYSDATE-11,'D');
Plan hash value: 1113251513
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | TQ |IN-OUT| PQ Distrib |
| 0 | CREATE TABLE STATEMENT | | 25157 | 28M| 14580 (1)| 00:02:55 | | | |
| 1 | LOAD AS SELECT | DELME11 | | | | | | | |
| 2 | PX COORDINATOR | | | | | | | | |
| 3 | PX SEND QC (RANDOM) | :TQ10000 | 25157 | 28M| 14530 (1)| 00:02:55 | Q1,00 | P->S | QC (RAND) |
| 4 | PX BLOCK ITERATOR | | 25157 | 28M| 14530 (1)| 00:02:55 | Q1,00 | PCWC | |
|* 5 | TABLE ACCESS FULL | ED_VISITS | 25157 | 28M| 14530 (1)| 00:02:55 | Q1,00 | PCWP | |
Predicate Information (identified by operation id):
5 - filter("FIRST_CONTACT_DT">=TRUNC(SYSDATE@!-11,'fmd'))Hi Jason,
I think you're right with kind of "threshold". You can verify CBO costing with event 10053 enabled. There are many possible ways to change this behaviour. Most straightforward would be probably INDEX hint, but you can also change some index-cost related parameters, check histograms, decrease degree of paralellism on table, create stored outline, etc.
Lukasz -
Why full index scan is faster than full table scan?
Hi friends,
In the where clause of a query,if we give a column that contains index on it,then oracle uses index to search data rather than a TABLE ACCESS FULL Operation.
Why index searching is faster?Sometimes it is faster to use index and sometimes it is faster to use full table scan. If your statistics are up to date Oracle is far more likely to get it right. If the query can be satisfied entirely from the index, then an index scan will almost always be faster as there are fewer blocks to read in the index than there would be if the table itself were scanned. However if the query must extract data from the table when that data is not in te index, then the index scan will be faster only if a small percentage of the rows are to be returned. Consiter the case of an index where 40% of the rows are returned. Assume the index values are distributed evenly among the data blocks. Assume 10 rows will fit in each data block thus 4 of the 10 rows will match the condition. Then the average datablock will be fetched 4 times since most of the time adjacent index entries will not be in the same block. The number of single datablock fetches will be about 4 times the number of datablocks. Compare this to a full table scan that does multiblock reads. Far fewer reads are required to read the entire table. Though it depends on the number of rows per block, a general rule is any query returning more than about 10% of a table is faster NOT using an index.
-
"db file scattered read" too high and Query going for full table scan-Why ?
Hi,
I had a big table of around 200mb and had a index on it.
In my query I am using the where clause which has to use the
index. I am neither using any not null condition
nor using any function on the index fields.
Still my query is not using the index.
It is going for full table scan.
Also the statspack report is showing the
"db file scattered read" too high.
Can any body help and suggest me why this is happenning.
Also tell me the possible solution for it.
Thanks
Arun Tayal"db file scattered read" are physical reads/multi block reads. This wait occurs when the session reading data blocks from disk and writing into the memory.
Take the execution plan of the query and see what is wrong and why the index is not being used.
However, FTS are not always bad. By the way, what is your db_block_size and db_file_multiblock_read_count values?
If those values are set to high, Optimizer always favour FTS thinking that reading multiblock is always faster than single reads (index scans).
Dont see oracle not using index, just find out why oracle is not using index. Use the INDEX hint to force optimizer to use index. Take the execution with/witout index and compare the cardinality,cost and of course, logical reads.
Jaffar
Message was edited by:
The Human Fly -
Why the full table scans in this query on a complex view?
Does someone have an idea of why the FTSs are in here? As I mentioned before, it seems to be using the indexes where I figured it would. I just don't see why it needs to FTS ALL tables involved in the view to put the combined result sets together.
Thanks
Here's the plan
PLAN_TABLE_OUTPUT
Plan hash value: 4040654044
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 3060 | 116K| 1404 (2)| 00:00:17 |
|* 1 | FILTER | | | | | |
| 2 | VIEW | V_MOD2_V3 | 305K| 11M| 1259 (2)| 00:00:16 |
| 3 | UNION-ALL | | | | | |
| 4 | TABLE ACCESS FULL | MOD_TAB1 | 101K| 4880K| 420 (2)| 00:00:06 |
| 5 | TABLE ACCESS FULL | MOD_TAB2 | 101K| 4880K| 420 (2)| 00:00:06 |
| 6 | TABLE ACCESS FULL | MOD_TAB3 | 101K| 4880K| 420 (2)| 00:00:06 |
|* 7 | VIEW | V_MOD2_V3 | 3 | 156 | 6 (0)| 00:00:01 |
| 8 | UNION-ALL | | | | | |
|* 9 | TABLE ACCESS BY INDEX ROWID| MOD_TAB1 | 1 | 53 | 2 (0)| 00:00:01 |
|* 10 | INDEX UNIQUE SCAN | MOD_TAB1_PK | 1 | | 1 (0)| 00:00:01 |
|* 11 | TABLE ACCESS BY INDEX ROWID| MOD_TAB2 | 1 | 53 | 2 (0)| 00:00:01 |
|* 12 | INDEX UNIQUE SCAN | MOD_TAB2_PK | 1 | | 1 (0)| 00:00:01 |
|* 13 | TABLE ACCESS BY INDEX ROWID| MOD_TAB3 | 1 | 53 | 2 (0)| 00:00:01 |
|* 14 | INDEX UNIQUE SCAN | MOD_TAB3_PK | 1 | | 1 (0)| 00:00:01 |
| 15 | SORT AGGREGATE | | 1 | 13 | | |
| 16 | VIEW | V_MOD2_V3 | 219K| 2792K| 139 (6)| 00:00:02 |
| 17 | UNION-ALL | | | | | |
|* 18 | INDEX FAST FULL SCAN | MOD_TAB1_ST_IDX | 101K| 398K| 51 (6)| 00:00:01 |
|* 19 | INDEX FAST FULL SCAN | MOD_TAB2_ST_IDX | 101K| 398K| 52 (6)| 00:00:01 |
|* 20 | INDEX RANGE SCAN | MOD_TAB3_ST_IDX | 16000 | 64000 | 35 (0)| 00:00:01 |
Message was edited by:
GaffAlas, ALL of that was in the original post I put up a few weeks ago. I meant to reply to it in the message you saw but instead I "edited" it and the original post is now gone!
Suffice it to say that the 3 tables that make up the view are identical, have the proper columns indexed and have statistics generated. The view you see the explain plan for is a view that just does a "UNION ALL" of each of the 3 mod_tab tables.
As I figured it would, a query on the view uses the indexes to figure out which rows of each underlying table have data for the result set based on the "where" clause , and that is where you see the index range scan, etc. What I don't understand is the part in bold. Assuming all rows in all tables that make up the view have been indentified by these index range scans, what requires the 3 full table scans at the end? The explain plan in SQL Developer (Raptor) will show why each of the other things is there, but not the full table scans.
I am getting a few hundred result set rows out of 100,000-200,000 rows altogether so I can't imagine a full table scan on any of these underlying tables being the right way to go (and look at the cost in the plan).
Thanks -
Update doing full table scan and taking long time
Hi All,
I am running an update statement which is doing a full table scan.
UPDATE Database.TABLE AS T
SET COMMENTS = CAST(CAST(COALESCE(T.COMMENTS,0) AS INTEGER) + 1 AS
CHARACTER)
WHERE T.TRACKINGPOINT = 'NDEL'
AND T.REFERENCENUMBER =
SUBSTRING(Root.XML.EE_EAI_MESSAGE.ReferenceNumber || '
' FROM 1 FOR 32);
Any advice.
Regards,
UmairMustafa,
No Developer is writing it in his program.
Regards,
Umair
Maybe you are looking for
-
How can I connect a laptop with DVI to an Apple LED Cinema Display 27"
I have an old Mac Book Pro 2007 and a PC laptop, both with DVI. I simply can't find a DVI to mini display adapter. Can this be true?
-
I was able to get the program to install last weekend but I had to do a refresh on my computer and THe program will not install. Please help
-
Cisco ASA 8.2, cant access internet,
Hi All, Hope some one can help me. I have spent the last two days trying to resolve this problem but had no luck. When I configure the ASA5520 from scratch every thin works fine, I can access the internet and surf with out a problem. The problem is w
-
i just got a brand new macbook and so far it works great. the wireless internet connection is fast & flawless. i just downloaded mozilla firefox for mac os x and it too works really well. the only trouble is, whenever i shut down my computer and come
-
HT3819 Can you share photos using home sharing?
Can you share photos using home sharing?