У меня есть этот запрос:
SELECT *
FROM location
WHERE to_tsvector('simple',unaccent2("city"))
@@ to_tsquery('simple',unaccent2('wroclaw'))
order by displaycount
Я рада этому:
"Sort (cost=3842.56..3847.12 rows=1826 width=123) (actual time=1.915..2.084 rows=1307 loops=1)"
" Sort Key: displaycount"
" Sort Method: quicksort Memory: 206kB"
" -> Bitmap Heap Scan on location (cost=34.40..3743.64 rows=1826 width=123) (actual time=0.788..1.208 rows=1307 loops=1)"
" Recheck Cond: (to_tsvector('simple'::regconfig, unaccent2((city)::text)) @@ '''wroclaw'''::tsquery)"
" -> Bitmap Index Scan on location_lower_idx (cost=0.00..33.95 rows=1826 width=0) (actual time=0.760..0.760 rows=1307 loops=1)"
" Index Cond: (to_tsvector('simple'::regconfig, unaccent2((city)::text)) @@ '''wroclaw'''::tsquery)"
"Total runtime: 2.412 ms"
Но когда я добавляю LIMIT, выполнение занимает больше 2 секунд:
SELECT *
FROM location
WHERE to_tsvector('simple',unaccent2("city"))
@@ to_tsquery('simple',unaccent2('wroclaw'))
order by displaycount
limit 20
Объясните:
"Limit (cost=0.00..1167.59 rows=20 width=123) (actual time=2775.452..2775.643 rows=20 loops=1)"
" -> Index Scan using location_displaycount_index on location (cost=0.00..106601.25 rows=1826 width=123) (actual time=2775.448..2775.637 rows=20 loops=1)"
" Filter: (to_tsvector('simple'::regconfig, unaccent2((city)::text)) @@ '''wroclaw'''::tsquery)"
"Total runtime: 2775.693 ms"
Я думаю, что это проблема с ORDER BY и LIMIT. Как я могу заставить PostgreSQL использовать индекс и выполнить упорядочение в конце?
Подзапрос не помогает:
SELECT *
FROM (
SELECT *
FROM location
WHERE to_tsvector('simple',unaccent2("city"))
@@ to_tsquery('simple',unaccent2('wroclaw'))
order by displaycount
) t
LIMIT 20;
или:
SELECT *
FROM (
SELECT *
FROM location
WHERE to_tsvector('simple',unaccent2("city"))
@@ to_tsquery('simple',unaccent2('wroclaw'))
) t
order by displaycount
LIMIT 20;
При использовании LIMIT postgresql настроить его план будет оптимальным только для извлечения подмножества строки. К сожалению, это как-то делает неправильный выбор в вашем случае. Это может быть потому, что статистика для таблицы слишком старая. Попробуйте обновить статистику, указав местоположение VACUUM ANALYZE;
Принудительное использование индексов обычно выполняется путем запрета использования последовательного сканирования (set enable_seqscan = false). Однако в вашем случае он не выполняет последовательное сканирование, он просто переключается на другой индекс для запроса с LIMIT.
Если анализ не помогает, можете ли вы сказать, какую версию postgresql вы используете? Кроме того, сколько строк в таблице?
источник