I have a process that is performing badly due to full table scans on a particular table. I have computed statistics, rebuilt existing indices and tried adding new indices for this table but this hasn't solved the issue.
Can an implicit type conversion stop an index being used? What about other reasons? The cost of a full table scan is around 1000 greater than the index lookup should be.
EDIT:
SQL statement:
select unique_key
from src_table
where natural_key1 = :1
and natural_key2 = :2
and natural_key3 = :3;
Java code (not easily modifiable):
ps.setLong(1, oid);
This conflicts with the column datatype: varchar2
an implicit conversion can prevent an index from being used by the optimizer. Consider:
SQL> CREATE TABLE a (ID VARCHAR2(10) PRIMARY KEY);
Table created
SQL> insert into a select rownum from dual connect by rownum <= 1e6;
1000000 rows inserted
This is a simple table but the datatype is not 'right', i-e if you query it like this it will full scan:
SQL> select * from a where id = 100;
ID
----------
100
This query is in fact equivalent to:
select * from a where to_number(id) = 100;
It cannot use the index since we indexed id
and not to_number(id)
. If we want to use the index we will have to be explicit:
select * from a where id = '100';
In reply to pakr's comment: There are lots of rules concerning implicit conversions. One good place to start is the documentation. Among other things, we learn that:
During SELECT FROM operations, Oracle converts the data from the column to the type of the target variable.
It means that when implicit conversion occurs during a "WHERE column=variable"
clause, Oracle will convert the datatype of the column and NOT of the variable, therefore preventing an index from being used. This is why you should always use the right kind of datatypes or explicitly converting the variable.
From the Oracle doc:
Oracle recommends that you specify explicit conversions, rather than rely on implicit or automatic conversions, for these reasons:
- SQL statements are easier to understand when you use explicit datatype conversion functions.
- Implicit datatype conversion can have a negative impact on performance, especially if the datatype of a column value is converted to that of a constant rather than the other way around.
- Implicit conversion depends on the context in which it occurs and may not work the same way in every case. For example, implicit conversion from a datetime value to a VARCHAR2 value may return an unexpected year depending on the value of the NLS_DATE_FORMAT parameter.
- Algorithms for implicit conversion are subject to change across software releases and among Oracle products. Behavior of explicit conversions is more predictable.
Make you condition sargable, that is compare the field itself to a constant condition.
This is bad:
SELECT *
FROM mytable
WHERE TRUNC(date) = TO_DATE('2009.07.21')
, since it cannot use the index. Oracle cannot reverse the TRUNC()
function to get the range bounds.
This is good:
SELECT *
FROM mytable
WHERE date >= TO_DATE('2009.07.21')
AND date < TO_DATE('2009.07.22')
To get rid of implicit conversion, well, use explicit conversion:
This is bad:
SELECT *
FROM mytable
WHERE guid = '794AB5396AE5473DA75A9BF8C4AA1F74'
-- This uses implicit conversion. In fact this is RAWTOHEX(guid) = '794AB5396AE5473DA75A9BF8C4AA1F74'
This is good:
SELECT *
FROM mytable
WHERE guid = HEXTORAW('794AB5396AE5473DA75A9BF8C4AA1F74')
Update:
This query:
SELECT unique_key
FROM src_table
WHERE natural_key1 = :1
AND natural_key2 = :2
AND natural_key3 = :3
heavily depends on the type of your fields.
Explicitly cast your variables to the field type, as if from string.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With