Tengo esta consulta:
SELECT *
FROM location
WHERE to_tsvector('simple',unaccent2("city"))
@@ to_tsquery('simple',unaccent2('wroclaw'))
order by displaycount
Estoy feliz con eso:
"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"
Pero cuando agrego LIMIT, la ejecución tarda más de 2 segundos:
SELECT *
FROM location
WHERE to_tsvector('simple',unaccent2("city"))
@@ to_tsquery('simple',unaccent2('wroclaw'))
order by displaycount
limit 20
Explique:
"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"
Creo que es un problema con ORDER BY y LIMIT. ¿Cómo puedo forzar a PostgreSQL a usar el índice y hacer el pedido al final?
Subconsulta no ayuda:
SELECT *
FROM (
SELECT *
FROM location
WHERE to_tsvector('simple',unaccent2("city"))
@@ to_tsquery('simple',unaccent2('wroclaw'))
order by displaycount
) t
LIMIT 20;
o:
SELECT *
FROM (
SELECT *
FROM location
WHERE to_tsvector('simple',unaccent2("city"))
@@ to_tsquery('simple',unaccent2('wroclaw'))
) t
order by displaycount
LIMIT 20;
Cuando se utiliza un ajuste LIMIT postgresql, su plan es óptimo para recuperar solo el subconjunto de fila. Desafortunadamente, de alguna manera toma una decisión equivocada en su caso. Esto podría deberse a que las estadísticas de la tabla son demasiado antiguas. Intente actualizar la estadística emitiendo VACUUM ANALYZE location;
Forzar el uso de índices normalmente se realiza deshabilitando el uso de exploraciones secuenciales (establezca enable_seqscan = false). Sin embargo, en su caso, no está haciendo una exploración secuencial, simplemente cambia a un índice diferente para la consulta con el LÍMITE.
En caso de que el análisis no ayude, ¿podría decir qué versión de postgresql está utilizando? Además, ¿cuántas filas hay en la tabla?
fuente