Hi Group,
I've never really learned how to optimize queries that join several tables and have order by clauses that specify columns from each table. Is there documentation that could help me optimize and have the proper indexes in place? I've read through the PG Docs Chapter 11 on Indexes yet still lack the needed understanding.
Here's my latest culprit:
select Anl.Priority, Anl.Lab, Anl.Job, JOB.DateIn, JOB.CompanyCode, Anl.SampleName
from analysis anl join job on anl.job = job.job
order by job.companycode, anl.job, anl.lab
limit 10;
Here's the query plan using PG 8.4.4:
Limit (cost=21990.24..21990.27 rows=10 width=32)
-> Sort (cost=21990.24..22437.69 rows=178979 width=32)
Sort Key: job.companycode, anl.lab
-> Hash Join (cost=451.20..18122.57 rows=178979 width=32)
Hash Cond: (anl.job = job.job)
-> Seq Scan on analysis anl (cost=0.00..14091.79 rows=178979 width=23)
-> Hash (cost=287.20..287.20 rows=13120 width=17)
-> Seq Scan on job (cost=0.00..287.20 rows=13120 width=17)
If I change the above query to only order by one of the tables, I get better results:
select Anl.Priority, Anl.Lab, Anl.Job, JOB.DateIn, JOB.CompanyCode,
Anl.SampleName
from analysis anl join job on anl.job = job.job
order by job.companycode --, anl.job, anl.lab
limit 10;
Limit (cost=0.00..3.65 rows=10 width=32)
-> Nested Loop (cost=0.00..65269.13 rows=178979 width=32)
-> Index Scan using job_companycode on job (cost=0.00..972.67 rows=13120 width=17)
-> Index Scan using analysis_job_lab on analysis anl (cost=0.00..4.63 rows=22 width=23)
Index Cond: (anl.job = job.job)
Any idea on how I can improve this? In the past I would tend to create a cached copy of the query as a table that would be utilized, but I suspect that there is a better way to go about this. I'm using a system (Clarion) which heavily uses cursors via the ODBC driver (I use the psqlODBC latest version) to get a handful of records at a time, so no actual LIMITs would be used in the production queries; I've added the LIMITs here to try to simulate the performance differences that I find when browsing the data while ordering by the above columns.
Here are the relevant tables and indexes:
CREATE TABLE job
(
job bigint NOT NULL, -- Job #
companycode character(4), -- Company Code
recdbycode character(3), -- Initials of who checked in sample(s)
datein date, -- Date sample was received
project character varying, -- Project or Site name
remarks text, -- Remarks
--[CONSTRAINTs etc]
)
CREATE INDEX job_companycode
ON job
USING btree
(companycode);
CREATE INDEX job_companycode_job
ON samples.job
USING btree
(companycode, job);
CREATE TABLE analysis
(
lab bigint NOT NULL, -- Lab number
job bigint, -- Job number
sampletype character varying(5), -- General class of sample
priority character(1), -- Priority level
samplename character varying, -- Sample or Well name
CONSTRAINT rel_joblabk_to_jobk FOREIGN KEY (job)
REFERENCES job (job) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE RESTRICT,
--[CONSTRAINTs etc]
)
CREATE INDEX analysis_companycode_job_lab
ON analysis
USING btree
(companycode, job, lab);
CREATE INDEX analysis_job_lab
ON analysis
USING btree
(job, lab);
Thanks for any insights and tips you can provide!
Kind Regards,
-Joshua Berry