How to use Explain Plan to optimize queries?

52,421

Solution 1

You get more than that actually depending on what you are doing. Check out this explain plan page. I'm assuming a little bit here that you are using Oracle and know how to run the script to display the plan output. What may be more important to start with is looking at the left hand side for the use of a particular index or not and how that index is being utilized. You should see things like "(Full)", "(By Index Rowid)", etc if you are doing joins. The cost would be the next thing to look at with lower costs being better and you will notice that if you are doing a join that is not using an index you may get a very large cost. You may also want to read details about the explain plan columns.

Solution 2

I also assume you are using Oracle. And I also recommend that you check out the explain plan web page, for starters. There is a lot to optimization, but it can be learned.

A few tips follow:

First, when somebody tasks you to optimize, they are almost always looking for acceptable performance rather than ultimate performance. If you can reduce a query's running time from 3 minutes down to 3 seconds, don't sweat reducing it down to 2 seconds, until you are asked to.

Second, do a quick check to make sure the queries you are optimizing are logically correct. It sounds absurd, but I can't tell you the number of times I've been asked for advice on a slow running query, only to find out that it was occasionally giving wrong answers! And as it turns out, debugging the query often turned out to speed it up as well.

In particular, look for the phrase "Cartesian Join" in the explain plan. If you see it there, the chances are awfully good that you've found an unintentional cartesian join. The usual pattern for an unintentional cartesian join is that the FROM clause lists tables separated by comma, and the join conditions are in the WHERE clause. Except that one of the join conditions is missing, so that Oracle has no choice but to perform a cartesian join. With large tables, this is a performance disaster.

It is possible to see a Cartesian Join in the explain plan where the query is logically correct, but I associate this with older versions of Oracle.

Also look for the unused compound index. If the first column of a compound index is not used in the query, Oracle may use the index inefficiently, or not at all. Let me give an example:

The query was:

select * from customers    
where
     State = @State
     and ZipCode = @ZipCode

(The DBMS was not Oracle, so the syntax was different, and I've forgotten the original syntax).

A quick peek at the indexes revealed an index on Customers with the columns (Country, State, ZipCode) in that order. I changed the query to read

  select * from customers
   where Country = @Country
      and State = @State
      and ZipCode = @ZipCode

and now it ran in about 6 seconds instead of about 6 minutes, because the optimizer was able to use the index to good advantage. I asked the application programmers why they had omitted the country from the criteria, and this was their answer: they knew that all the addresses had country equal to 'USA' so they figured they could speed up the query by leaving that criterion out!

Unfortunately, optimizing database retrieval is not really the same as shaving microseconds off of computing time. It involves understanding the database design, especially indexes, and at least an overview of how the optimizer does its job.

You generally get better results from the optimizer when you learn to collaborate with it instead of trying to outsmart it.

Good luck coming up to speed at optimization!

Solution 3

This is a massive area of expertise (aka a black art).

The approach I generally take is:

  1. Run the SQL statement in question,
  2. Get the actual plan (look up dbms_xplan),
  3. Compare the estimated number of rows (cardinality) vs actual number of rows. A big difference indicates a problem to be fixed (e.g. index, histogram)
  4. Consider if you can create an index to speed part of the process (generally where you conceptually think the plan should go first). Try some indexes.

You need to understand the O() impacts of different indexes in the context of what you are asking the database. It helps you understand data structures like b-trees, hash tables etc. Then, create an index that might work and repeat the process.

If Oracle decides not to use your index, apply an INDEX() hint and look at the new plan. The cost will be greater than the plan it did choose - this is why it didn't pick your index. The hinted plan might lead to some insight about why your index is not good.

Share:
52,421
Jacob Schoen
Author by

Jacob Schoen

Born and raised in Southeast Louisiana, graduated with CS degree from the University of New Orleans and currently working towards Masters degree in Computer Science also. I have always been interested in computers, and becoming a programmer seemed a natural progression for me. It fits my personality and gives me a new puzzle to solve everyday.

Updated on December 01, 2020

Comments

  • Jacob Schoen
    Jacob Schoen over 3 years

    I have been tasked to optimize some sql queries at work. Everything I have found points to using Explain Plan to identify problem areas. The problem I can not find out exactly what explain plan is telling me. You get Cost, Cardinality, and bytes.

    What do this indicate, and how should I be using this as a guide. Are low numbers better? High better? Any input would be greatly appreciated.

    Or if you have a better way to go about optimizing a query, I would be interested.

  • Jacob Schoen
    Jacob Schoen over 15 years
    I appreciate you help, and especially the links. It is starting to make since to me now. Thanks again for the help.
  • Admin
    Admin over 15 years
    Joins not using indexes may be bad, they may be the absolutely best. It all depends. do not, do not, do not try to eliminate every full table scan with indexes.
  • Jacob Schoen
    Jacob Schoen over 15 years
    Oracle not choosing to use an index seemed strange to me at first, until your explanation above, and now I realize I am in deeper than I ever realized. If only they would get us an experienced DBA to work with us, we would be better off.