Subject RE: [firebird-support] Help with query optimization
Author Svein Erling Tysvær
Hi Kevin!

>I've got a query that I threw together to serve as a search in a web app.
>My first cut of it used "containing" operators for the user's search terms and was
>taking 15-20 seconds to run, which didn't surprise me. I figured I would have to do
>something smarter than "containing". As I began to play around with optimization, I
>came to find that the "containing" operators weren't my problem. My problem was my
>"distinct" and my joins.
>
>I prowled through the mailing list last Friday looking for leads, tried a lot of
>things, but never could get just the joins, without search criteria, running in much
>under about 14 seconds.
>
>select distinct s.StudentSeq, s.LastName, s.FirstName,
> s.BirthDate, s.MiddleName, p.StudentID
>from student s
>join PrfStuID p on s.StudentSeq=p.StudentSeq
>join AliasStu a on s.StudentSeq=a.StudentSeq
>join SchlHist h on s.StudentSeq=h.StudentSeq
>join Facility f on h.FacilityID=f.FacilityID
>join District d on f.DistrictCode=d.DistrictCode
>
>This database is old and hoary. I'll include the DDL, at least for the important
>fields and indexes. There are no primary keys on any tables, although every table has
>a single unique index. The plan looks like this:
>
>PLAN SORT (JOIN (F NATURAL, D INDEX (DISTRICT_), H INDEX (SCHLHIST_FACILITYID),
>S INDEX (STUDENT_), P INDEX (PRFSTUID_), A INDEX (ALIASSTU_STUDENTSEQINDEX)))

The first impression is that this is a fair query with a decent plan, or at least as decent as it gets without any WHERE clause. However, many web apps desire to show only a fraction of the records on screen, and that can be done without distinct (so that you do not have to select all records):

select s.StudentSeq, s.LastName, s.FirstName, s.BirthDate, s.MiddleName, p.StudentID
from student s
join PrfStuID p on s.StudentSeq=p.StudentSeq
where exists(select * from AliasStu a
join SchlHist h on a.StudentSeq=h.StudentSeq
join Facility f on h.FacilityID=f.FacilityID
join District d on f.DistrictCode=d.DistrictCode
where s.StudentSeq=a.StudentSeq)
ROWS 1 TO 20

(you may want to add ORDER BY and possibly use FIRST rather than ROWS if you use an old Firebird version, of course 1 TO 20 was randomly chosen, use whatever fits your need).

However, if you want all rows returned, then I don't think my suggestion will help you anything.

HTH,
Set