2. Healthy CodeMay 2014 21
= FASTER ACCESS
Ankit Kumar Katiyar & N.S.Sekar
O
ne of the frequently encountered solutions
that application developers are offered, while
dealing with performance issues with the
oracle database is: “create an index on that column”.
This may enhance the performance in some cases if
you know your index well enough. However this can
actually degrade or not have any significant impact
on the SQL performance in the application at all.
Therefore it’s important to be aware of the behavior
of index if you want to leverage its true potential. We
have identified a bunch of issues while working with
index in Oracle and discussed them in this article.
Here’s a list of concerns raised by developers and our
response to them.
Concern #1:
I have created an appropriate index on particular
column. But why is the query engine not picking up
the index?
This may happen due to bad or incomplete statistics.
In the absence of statistics, the optimizer (Cost based
optimization) may choose a full table scan (FTS) as
compared to indexed access.
Recommendations:
Prior to testing queries, just make sure you re-analyze
the table and index with dbms_stats. This provides
the optimizer with good metadata.
You can use the following queries to check the last
analyzed status.
You can use the following queries to execute the dms_
stats procedure to analyze objects.
Concern #2:
I have created an appropriate index on a particular
column and I have also verified the earlier step
discussed in Concern#1. I still see that oracle is not
using that index.
This may happen if the number of rows in that table
is less or your query is returning almost all the data
in a table.
Recommendations:
If table is small that it can be read in a single I/O call,
then a full table scan of table might be cheaper than
an index range scan. Single I/O call can be defined by
3. Healthy Code May 201422
DB_FILE_MULTIBLOCK_READ_COUNT parameter
and value defined by blocks.
If your query is returning the majority of the data in a
table, then a full table scan is probably going to be the
most efficient way to access the table and optimizer
may choose to decide that it would be more efficient
not to use the index.
Concern #3:
I have created proper B-Tree Index on the particular
column and have also analyzed the table and index.
I still don’t find oracle using that index.
Oracle B-TREE Indexes can surely help in improving
the query performance provided there is optimal
selectivity on that column. The ratio of the number
of distinct values in the indexed column/columns
to the number of records in the table represents the
selectivity of an index. Ideal selectivity is 1 in case of
primary key and unique key.
While optimizing, oracle takes a decision of choosing
an index based on I/O. As discussed earlier, if the
query is returning the majority of the data in a table,
then a full table scan is probably going to be the most
efficient way to access the table.
Recommendations:
We should create indexes on tables that are
often queried for less than 15% of the table’s rows.
This value may be higher in situations where all
data can be retrieved from an index, or where the
indexed columns can be used for joining to other
tables.
Please check if you have right index on that
column. In other words, in oracle while standard
B-tree indexes are most effective for columns
containing a high number of different values
(good selectivity), bitmapped indexes are most
appropriate for columns with a limited number
(poor selectivity) of possible values.
In general, B-tree indices are good for OLTP
and Bitmapped indices are good for OLAP systems.
Factor in your usage, prior to creating the index.
Concern #4:
I have a query
4. Healthy CodeMay 2014 23
The query engine is still not using the index.
If you are using the SQL “like” clause then it can
be tricky because the wildcard “%” operator can
invalidate the index.
Recommendations:
STRING% will do INDEX RANGE SCAN
data because optimizer knows where the string
gets started.
% STRING will do the INDEX FULL table
because LIKE expression that starts with a
wildcard.
%STRING% will perform the FULL table scan
because optimizer doesn’t know from which letter
the String get started.
Concern #5:
I have a query,
I also have a proper index on id column. Why is the
query engine still not using the index?
If you have got a WHERE clause which contains
something like “id is null” then query engine will
always perform the full-table scan because NULL
values cannot be indexed. If you have no choice, but to
have this condition in your query, consider replacing
it with a NVL function.
Recommendations:
If you have a null in your where clause you may
have to keep the following in mind:
When you have “IS NOT NULL” type
WHERE clause will use an index
When you have “IS NULL” type WHERE
doesn’t use an index
Concern #6:
I have a query,
I have proper index on name column then why is the
query engine not utilizing an index?
5. Healthy Code May 201424
Even though the name column has an index, the upper
functions will invalidate the index and WHERE clause
predicates might invoke FTS (unnecessary I/O).
Recommendations:
In such cases, use Function-Based index on that
column. Function-Based indexes give the ability to
index computed columns and use theses indexes in a
query as shown here.
Concern #7:
I have created a Function-based index on a table
column, yet when I check my execution plan, the
optimizer ignores the Function-based index?
Typically, function-based indexes or any index
are ignored when analyze the index has not been
performed.
Recommendations:
After creating a function-based index, don’t forget to
re-gather table statistics and get extended statistics on
the function.
Concern #8:
I have a query,
I have a proper index on these columns but no use
of the index.
This may happen if you are performing mathematical
operations on the indexed column then oracle will
invalidate the index and will go for the full table scan.
Concern #9:
I have a following query
In this case name column is indexed but oracle is not
using an index. Why?
When an indexed column appears on both sides of an
operator, the index for that column is disabled.
Recommendations:
You can rewrite the above-mentioned query as
Concern #10:
I have following query
Inspite of having a proper index on these columns
why doesn’t oracle use it?
If we use the NOT EXISTS then nested index scans
will be used in the sub query for each row in the
DEPARTMENT table. The only records that will be
returned from DEPARTMENT are those that return
no rows from the sub query, and no full table scans
are performed by the sub query.
Recommendations:
The following query statement is more efficient.
department.department_id=employee.
department_id)
Concern #11:
In my query, I have an index on a DATE column
but oracle is not using index if I fetch results using
JDBC driver?
This might happen due to data type conversion
between Date and TimeStamp. Developers, typically
use the setTimestamp method in order to set time.
When this is done, the index on the DATE column
will not be used. This is because, oracle internally
converts/casts datatypes (of date to timestamp) .
Recommendations:
You can address this problem with the following:
6. Healthy CodeMay 2014 25
Concern #12:
In spite of having index on “first_name” and “last_
name” columns the query
“
takes much longer than expected.
The use of ‘OR’ statements confuses the optimizer
(Cost Based Optimizer). It will rarely choose to use an
index on column referenced using an OR statement.
Recommendations:
You can work around this issue by using UNION
ALL as shown here.
Concern #13:
I have created composite index on the column but
how does it work with my query?
A composite index contains more than one key
column. Composite indexes can provide additional
advantages over single column indexes. Consider
creating a composite index on columns that are
frequently used together in WHERE clause conditions
combined with AND operators, especially if their
combined selectivity is better than the selectivity
of either column individually. Even If you do not
include the first column of a concatenated index in the
WHERE clause of your statement then also Index Skip
Scanning will be used.
Summary
This article was just a brief overview at database
indexing with some light on b-tree index, bitmap
indexes, function-based indexes, and composite
indexes. Index efficiency is hard and finding
appropriate index even harder. We hope that these
tips when used appropriately may help you debug
performance issues, even after you have created the
index on the relevant columns.
In general, when things are really slow due to a SQL
statement, in your application, use the EXPLAIN
PLAN to look at the execution plan of the statement.
Following this, make the changes in your SQL based
on cost estimation.
Remember that “FULL TABLE SCANS ARE NOT
ALWAYS BAD” and “SQL INDEX != FASTER
ACCESS” in all scenarios.
Happy indexing!!!
Ankit Kumar is currently serving Successfactors
(SAP Cloud) as a Principal Engineer. His work is
with the Employee Central (EC) product wherein
his main focus is to make EC world’s most high-
performing, scalable, and blazing fast cloud
platform. Prior to this, he worked with Oracle
as a technology lead and Hewlett Packard (HP)
as a software analyst. He holds a patent and
disclosure in database and network technologies,
respectively.
NS Sekar
Sekar is Vice President of Engineering at Success
Factors. He has previously worked as Director
at Yahoo and Informatica. He is a seasoned tech-
nology and product development executive with
experience in building and scaling distributed en-
gineering and product teams from multiple ear-
ly-stage startups to the next level. His expertise
includes Data Integration, Data Quality, Web Ana-
lytics, Internet Platforms, and SaaS
Ankit Kumar