Reputation: 5919
I have a table (of snmp traps, but that's neither here nor there).
I have a query which pulls some records, which goes something like this:
SELECT *
FROM traps_trap
WHERE summary_id = 1600
ORDER BY traps_trap."trapTime";
This responds instantaneously, with 6 records.
When I add LIMIT 50
(since not all results will have only 6 records), it is very, VERY slow (to the point of not returning at all).
There is an index on the summary_id
column, I can only assume that it isn't being used for the second query.
I understand that the tool to solve this is explain
, but I'm not familiar enough with it to understand the results.
The explain analyse verbose for the first (quick) query is as follows:
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------
Sort (cost=14491.51..14502.48 rows=4387 width=263) (actual time=0.128..0.130 rows=6 loops=1)
Output: id, summary_id, "trapTime", packet
Sort Key: traps_trap."trapTime"
Sort Method: quicksort Memory: 28kB
-> Index Scan using traps_trap_summary_id on public.traps_trap (cost=0.00..13683.62 rows=4387 width=263) (actual time=0.060..0.108 rows=6 loops=1)
Output: id, summary_id, "trapTime", packet
Index Cond: (traps_trap.summary_id = 1600)
Total runtime: 0.205 ms
(8 rows)
explain for the second is:
QUERY PLAN
---------------------------------------------------------------------------------------------------------
Limit (cost=0.00..2538.69 rows=10 width=263)
-> Index Scan using "traps_trap_trapTime" on traps_trap (cost=0.00..1113975.68 rows=4388 width=263)
Filter: (summary_id = 1600)
(3 rows)
I run VACUUM
and ANALYZE
daily, I understand that is supposed to improve the plan. Any other pointers?
Upvotes: 3
Views: 151
Reputation: 121604
Index scan using trapTime is much slower than one using summary_id. I would try to nest the query (to use plan #1):
select * from (
SELECT *
FROM traps_trap
WHERE summary_id = 1600
ORDER BY traps_trap."trapTime"
) t
limit 50;
Edit:
After doing some tests I learned that simple query nesting (as above) has no effect on the planner.
To force the planner to use traps_trap_summary_id
index you can use CTE (my tests confirm this method):
with t as (
SELECT *
FROM traps_trap
WHERE summary_id = 1600
ORDER BY traps_trap."trapTime"
)
select * from t
limit 50;
Upvotes: 1