Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Query Optimization

26 views
Skip to first unread message

Roy

unread,
Feb 26, 2007, 3:53:35 PM2/26/07
to
I am learning SQL (trial by fire) and have a question regarding a
query optimization. Lets say I have three tables 'project', 'notes' &
'reminder'. Key on 'project' is 'proj_id'. The other two tables
reference this key as 'notes' contains note entries on a given project
and 'reminder' tracks todo type and due dates.

select count(a.proj_id)
from project a
where a.stat_cd = 'CLOSED'
and exists
(
select b.proj_id
from reminder b
where b.rem_type = 'LAST'
and a.proj_id = b.proj_id
)
and exists
(
select c.proj_id
from notes c
where c.note_type = 'QA'
and a.proj_id = c.proj_id
)

I am trying to determine the number of projects that have a 'CLOSED'
status, contain a reminder type of 'LAST' and has a note type of 'QA'

I get the result I am looking for but these are very large tables and
it takes over 30 minutes for this to run. Is there a better way to
write this query? I'm betting there is. Thank you in advance for your
advice.

Regards...

Roy

unread,
Feb 26, 2007, 4:23:51 PM2/26/07
to
Also - for whatever the reasons, indexing is not an option (per my
developers)

DA Morgan

unread,
Feb 26, 2007, 5:54:03 PM2/26/07
to
Roy wrote:
> Also - for whatever the reasons, indexing is not an option (per my
> developers)

Please explain this. If "my developers" ever said this to me my first
reaction would be to ask them to work on their resumes.
--
Daniel A. Morgan
University of Washington
damo...@x.washington.edu
(replace x with u to respond)
Puget Sound Oracle Users Group
www.psoug.org

Roy

unread,
Feb 26, 2007, 6:03:48 PM2/26/07
to
We do not do non-billable, in-house improvements (matter of policy -
yes, even for something as easy as adding an index). I'm a BA on a
customer site who has lost his Oracle guru to the military. I don't
have the immediate budget to grab a contractor so... I'm temporarily
up the proverbial creek, sans paddle.

The goal here is to mine potential data for a new interface I'm
designing. Now - what would a script look like that adds the indexes
(or temp tables?), performs the query, and then drops the temporary
elements?

-rgb

On Feb 26, 4:54 pm, DA Morgan <damor...@psoug.org> wrote:
> Roy wrote:
> > Also - for whatever the reasons, indexing is not an option (per my
> > developers)
>
> Please explain this. If "my developers" ever said this to me my first
> reaction would be to ask them to work on their resumes.
> --
> Daniel A. Morgan
> University of Washington

> damor...@x.washington.edu

Charles Hooper

unread,
Feb 26, 2007, 7:31:52 PM2/26/07
to

Give this re-write a try to see if it improves performance - I have
essentially moved the exists statements into two inline views (some
versions of Oracle may automatically perform such transformations):
SELECT
COUNT(A.PROJ_ID)
FROM
PROJECT A,
(SELECT DISTINCT
B.PROJ_ID
FROM
REMINDER B
WHERE
B.REM_TYPE = 'LAST') B,
(SELECT DISTINCT
C.PROJ_ID
FROM
NOTES C
WHERE
C.NOTE_TYPE = 'QA') C
WHERE
A.STAT_CD = 'CLOSED'
AND A.PROJ_ID = B.PROJ_ID
AND A.PROJ_ID = C.PROJ_ID;

Very likely, you will need an index on the PROJ_ID column for each
table, especially if the REMINDER and NOTES tables contain columns
that are wide. An index on REMINDER.REM_TYPE might help. An index on
NOTES.NOTE_TYPE also might help. Take a look at the explain plan
(preferrably DBMS_XPLAN) for your query, and compare it to the explain
plan for the one above. Also, make certain that the tables and
indexes are analyzed (use DBMS_STATS for Oracle 8i and above).

Charles Hooper
PC Support Specialist
K&M Machine-Fabricating, Inc.

AlterEgo

unread,
Feb 26, 2007, 8:00:00 PM2/26/07
to
Roy,

Unless I'm missing something or have misunderstood ... have you tried just
straight inner join syntax? It should be the most optimized (but not
always).

select count(a.projectid)
from project a
inner join reminder b on a.proj_id = b.proj_id
inner join notes c on a.proj_id = c.proj_id
where
a.stat_cd = 'CLOSED'
and b.rem_type = 'LAST'
and c.note_type = 'QA'

-- Bill

"Roy" <roy....@gmail.com> wrote in message
news:1172523215.4...@v33g2000cwv.googlegroups.com...

DA Morgan

unread,
Feb 26, 2007, 8:21:51 PM2/26/07
to

Good recommendations from Charles and AlterEgo ... but without the
ability to build an index ... it sounds like the "policy" is rather
expensive ... unless you are donating your time.

A policy that costs more than the alternative is a bad policy.


--
Daniel A. Morgan
University of Washington

damo...@x.washington.edu

Roy

unread,
Feb 27, 2007, 12:07:58 AM2/27/07
to
Suggestions are much appreciated. The last two of which both worked
quite well - especially after convincing the client DBA to move on the
indexes.

Having no understanding of my market, offering NO solution and feeling
compelled to dictate what is and is not good policy - a complete waste
of time.

Charles Hooper

unread,
Feb 27, 2007, 6:18:52 AM2/27/07
to
On Feb 27, 12:07 am, "Roy" <roy.b...@gmail.com> wrote:
> Suggestions are much appreciated. The last two of which both worked
> quite well - especially after convincing the client DBA to move on the
> indexes.
>
> Having no understanding of my market, offering NO solution and feeling
> compelled to dictate what is and is not good policy - a complete waste
> of time.

It is important to keep in mind that the two solutions provided may or
may not yield the same results. This will be evident in those cases
where there is more than one row in REMINDER for a PROJ_ID WHERE
REM_TYPE = 'LAST', and in cases where there is more than one row in
NOTES for a PROJ_ID WHERE NOTE_TYPE = 'QA'.

To work around the above issue, if it may occur, modify AlterEgo's
solution:

select count(a.projectid)

Can be modified as (assuming that PROJECTID is the primary key of the
PROJECT table):
SELECT
COUNT(DISTINCT A.PROJECTID)

With the above change, you may find that AlterEgo's SQL statement
executes slightly faster than the solution that I provided (this may
be Oracle version dependent).

One final note. When building SQL statements with aliases, it is
easier to troubleshoot problems with the SQL statements if the alias
name is somehow related to the object name that it represents:
Rather than using:
PROJECT A,
REMINDER B,
NOTES C
I would use:
PROJECT P,
REMINDER R,
NOTES N

rgb

unread,
Feb 27, 2007, 9:42:30 AM2/27/07
to
Excellent! I was indeed looking for distinct values. The tip for
alias' helps as well. I think I've learned more here in this amount of
time than in triple time spent with any of my books.

AlterEgo

unread,
Feb 27, 2007, 1:02:59 PM2/27/07
to
Good catch Charles.

"Charles Hooper" <hoope...@yahoo.com> wrote in message
news:1172575132.0...@p10g2000cwp.googlegroups.com...

0 new messages