Blog >> Tag: oracle

When tuning SQL statements, reviewing SQL plans are an important part of the process.  During a recent consulting session with one of our customers, we used a key piece of the plan called a filter predicate to determine why the customer's shipping application was performing poorly and costing the company a lot of money.

  

Note: The data gathered in this case study was done using Confio's Ignite for Oracle product.

 

Problem

Using Ignite we determined the following query was causing 80% of all wait time for the application.   It is fairly straightforward and looked similar to the following query:

SELECT company, attribute
FROM data_out
WHERE segment = :1;


A unique index exists on the SEGMENT column (standard NUMBER data type) so the selectivity is very good.  However, when this query executes from the Java application, it always takes 2-3 seconds and waits exclusively on the "db file scattered read" event.  Since the SEGMENT column has a unique index, 2-3 seconds seems really slow, and why does it wait on this event that typically indicates a full table scan?

Analysis

The developer retrieved the SQL plan using the EXPLAIN PLAN command and found the following:

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=ALL_ROWS (Cost=3 Card=1 Bytes=13)
   1    0   TABLE ACCESS (BY INDEX ROWID) OF 'DATA_OUT' (TABLE) (Cost=3 Card=1 Bytes=13)
   2    1     INDEX (UNIQUE SCAN) OF 'IX1_DATA_OUT' (INDEX (UNIQUE)) (Cost=2 Card=1)

Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
       2645  consistent gets
          1  rows processed


Based on this, Oracle appears to be using the unique index, but at least a couple questions arise from the data above:

  1. Why is a UNIQUE SCAN being used on the IX1_DATA_OUT unique index?
  2. Why are 2,645 consistent gets being performed when a unique index is being used?

Solution

Further analysis and the use of something called filter predicates led us to the answer.  In this case, we used data collected by Ignite for Oracle from the V$SQL_PLAN table to get more information.  You can also utilize the DBMS_XPLAN package to get similar results:

SQL_ID  46nx5qrtk8mtd, child number 0
-------------------------------------
SELECT company, attribute FROM data_out WHERE segment = :s1

Plan hash value: 3666395456

------------------------------------------------------------------------------
| Id  | Operation         | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |          |       |       |   668 (100)|          |
|*  1 |  TABLE ACCESS FULL| DATA_OUT |     1 |    13 |   668  (14)| 00:00:09 |
------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter(TO_BINARY_DOUBLE("SEGMENT")=:S1)


Wait a minute, this plan says a full table scan is occurring.  Why the difference in the two plans?  The difference can be explained by the fact that EXPLAIN PLAN does not have all the information necessary to give an accurate plan.  It has no knowledge of what the bind variable data will look like.  Using V$SQL_PLAN to get the actual execution plan, you can see the filter predicates and immediately recognize that a data conversion is being performed.  The TO_BINARY_DOUBLE function used around the SEGMENT column is negating the use of the unique index and hence a full table scan occurs. 

 

Results

Now that we know what is really happening, we can fix this problem several different ways:

  1. Tell the Java developers to pass a number data type so Oracle does not have to perform any data conversion.
  2. Since we know a data conversion is done, we could utilize a function-based index on TO_BINARY_DOUBLE(SEGMENT).
  3. Change the definition of the SEGMENT column to BINARY_DOUBLE vs. NUMBER.

Because this was a vendor application and we did not have immediate control of the code nor column definitions, we decided to go with option 2.  Using Ignite or the DBMS_XPLAN package again we see the new plan.  Instead of the query executing in 2-3 seconds, it now executes in 0.01 seconds.

 

SQL_ID  46nx5qrtk8mtd, child number 0
-------------------------------------
SELECT company, attribute FROM data_out WHERE segment = :s1

Plan hash value: 4253606649

--------------------------------------------------------------------------------------------
| Id  | Operation                   | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |              |       |       |     3 (100)|          |
|   1 |  TABLE ACCESS BY INDEX ROWID| DATA_OUT     |     1 |    14 |     3   (0)| 00:00:01 |
|*  2 |   INDEX UNIQUE SCAN         | IX3_DATA_OUT |     1 |       |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("DATA_OUT"."SYS_NC00004$"=:S1)

 

 

Conclusion

 

Without using the predicate information to see exactly how Oracle was executing this query, we were blind to the real problem.  Using Ignite for Oracle's Historical Execution Plan feature to collect the real execution plan from the V$SQL_PLAN table, we knew immediately what the options were and fixed the problem in less than a day.

 

Dean Richards, Senior DBA, Confio Software


Using Histograms to Help Oracle Cost-Based Optimizer Make Better Decisions

by Dean R.
Aug 07 2008
3:54 AM
Introduction Histograms are a feature of the cost-based optimizer (CBO) that allows the Oracle engine to determine how data is distributed within a column.  They are most useful for a column...
read more...

Looking at Linux Utilization with sar and Oracle’s V$OSSTAT

by Guest .
Feb 26 2009
8:36 AM
(This guest blog entry contributed by James Koopmann of Pinehorse, Inc., a well known database performance consultant, trainer and speaker, and a friend of Confio.) With the advent of the new...
read more...

Extended Optimizer Statistics in 11g

by Guest .
Apr 14 2009
8:48 AM
(This guest blog entry contributed by James Koopmann of Pinehorse, Inc., a well known database performance consultant, trainer and speaker, and a friend of Confio.) Better execution plans for faster...
read more...

Finding Usable Oracle Database Indexes

by Guest .
Apr 29 2009
1:23 AM
(This guest blog entry contributed by James Koopmann of Pinehorse, Inc., a well known database performance consultant, trainer and speaker, and a friend of Confio.) The rules of slap-happy data...
read more...

Invisible Indexes in Oracle 11g

by Don B.
May 15 2009
9:24 AM
(This guest blog entry contributed by James Koopmann of Pinehorse, Inc., a well known database performance consultant, trainer and speaker, and a friend of Confio.)   Have you ever wished you...
read more...

Error install Oracle 11g on CentOS - libmawt.so: Can't load IA 32-bit .so on IA 32bit platform

by Dean R.
Dec 04 2009
11:24 AM
I am setting up an Oracle 11g database environment on CentOS linux and ran into the following error from the runInstaller script: java.lang.UnsatisfiedLinkError:...
read more...

1000% Performance Improvement Using Oracle 11g Result Cache

by Dean R.
Feb 09 2010
9:05 AM
Server Result Cache Result Cache is a new feature in Oracle 11g and it does exactly what its name implies, it caches the results of queries and puts it into a slice of the shared pool.  If...
read more...