Reputation: 7382
My use case, is I need to to a text search on a field, and then order by another column, unrelated to the text search, but I can't seem to create an index that handles both.
Create table:
create table file (
id bigint,
path character varying(2048),
peers bigint,
text_search tsvector
);
Some indices to test:
create index idx_file_text_search_1 on file using gin (text_search);
create index idx_file_text_search_2 on file using gin (peers, text_search);
create index idx_file_peers on file using btree (peers desc);
Here is my main query:
explain analyze
select *
from file_fast
where text_search @@ to_tsquery('whatever')
order by peers desc
limit 10;
Yet its only using the peers index:
Limit (cost=0.43..20870.27 rows=10 width=316) (actual time=2507.304..9016.220 rows=10 loops=1)
-> Index Scan using idx_file_peers on file (cost=0.43..18286146.09 rows=8762 width=316) (actual time=2507.301..9016.205 rows=10 loops=1)
Filter: (text_search @@ to_tsquery('ole'::text))
Rows Removed by Filter: 497504
Planning time: 0.399 ms
Execution time: 9016.265 ms
(6 rows)
And when I try it without the order by, it appears to use text searching index:
-------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=104.15..143.54 rows=10 width=316) (actual time=76.949..76.977 rows=10 loops=1)
-> Bitmap Heap Scan on file (cost=104.15..34612.36 rows=8762 width=316) (actual time=76.946..76.970 rows=10 loops=1)
Recheck Cond: (text_search @@ to_tsquery('ole'::text))
Heap Blocks: exact=10
-> Bitmap Index Scan on idx_file_text_search_1 (cost=0.00..101.96 rows=8762 width=0) (actual time=76.802..76.802 rows=515 loops=1)
Index Cond: (text_search @@ to_tsquery('ole'::text))
Planning time: 0.376 ms
Execution time: 175.775 ms
(8 rows)
Does postgres really lack an index to be able to text search, and sort on another field?
Upvotes: 1
Views: 2342
Reputation: 48197
dont know if you can improve the index but if second query is the faster one maybe you can split the query
with cte as (
select *
from file_fast
where text_search @@ to_tsquery('whatever')
)
SELECT *
FROM cte
order by peers desc
limit 10;
Upvotes: 2