Tengo una gran mesa entities
con ~ 15 millones de registros. Quiero encontrar las 5 filas superiores que coinciden con 'hockey' en su name
.
Tengo un índice de texto completo name
, que se utiliza:gin_ix_entity_full_text_search_name
Consulta:
SELECT "entities".*,
ts_rank(to_tsvector('english', "entities"."name"::text),
to_tsquery('english', 'hockey'::text)) AS "rank0.48661998202865475"
FROM "entities"
WHERE "entities"."place" = 'f'
AND (to_tsvector('english', "entities"."name"::text) @@ to_tsquery('english', 'hockey'::text))
ORDER BY "rank0.48661998202865475" DESC LIMIT 5
Duración 25,623 ms
Explicar el plan 1 Límite (costo = 12666.89..12666.89 filas = 5 ancho = 3116) 2 -> Ordenar (costo = 12666.89..12670.18 filas = 6571 ancho = 3116) 3 Clave de clasificación: (ts_rank (to_tsvector ('english' :: regconfig, (name) :: text), '' 'hockey' '' :: tsquery)) 4 -> Escaneo de montón de mapa de bits en entidades (costo = 124.06..12645.06 filas = 6571 ancho = 3116) 5 Vuelva a verificar Cond: (to_tsvector ('english' :: regconfig, (name) :: text) @@ '' 'hockey' '' :: tsquery) 6 Filtro: (NO lugar) 7 -> Escaneo de índice de mapa de bits en gin_ix_entity_full_text_search_name (costo = 0.00..123.74 filas = 6625 ancho = 0) 8 Índice Cond: (to_tsvector ('english' :: regconfig, (name) :: text) @@ '' 'hockey' '' :: tsquery)
No entiendo por qué verifica la condición del índice dos veces. (Plan de consulta paso 4 y 7). ¿Es por mi condición booleana ( not place
)? Si es así, ¿debo agregarlo a mi índice para obtener una consulta muy rápida? ¿O la condición de clasificación lo hace lento?
EXPLAIN ANALYZE
salida:
Límite (costo = 4447.28..4447.29 filas = 5 ancho = 3116) (tiempo real = 18509.274..18509.282 filas = 5 bucles = 1) -> Ordenar (costo = 4447.28..4448.41 filas = 2248 ancho = 3116) (tiempo real = 18509.271..18509.273 filas = 5 bucles = 1) Clave de clasificación: (ts_rank (to_tsvector ('english' :: regconfig, (name) :: text), '' 'test' '' :: tsquery)) Método de clasificación: top-N heapsort Memoria: 19kB -> Escaneo de montón de mapa de bits en entidades (costo = 43.31..4439.82 filas = 2248 ancho = 3116) (tiempo real = 119.003..18491.408 filas = 2533 bucles = 1) Vuelva a verificar Cond: (to_tsvector ('english' :: regconfig, (name) :: text) @@ '' 'test' '' :: tsquery) Filtro: (NO lugar) -> Escaneo de índice de mapa de bits en gin_ix_entity_full_text_search_name (costo = 0.00..43.20 filas = 2266 ancho = 0) (tiempo real = 74.093..74.093 filas = 2593 bucles = 1) Índice Cond: (to_tsvector ('english' :: regconfig, (name) :: text) @@ '' 'test' '' :: tsquery) Tiempo de ejecución total: 18509.381 ms
Aquí están mis parámetros de base de datos. Está alojado por Heroku, en los servicios de Amazon. Lo describen como tener 1,7 GB de RAM, 1 unidad de procesamiento y una base de datos de máximo 1 TB.
nombre | configuración actual ------------------------------ + ------------------- -------------------------------------------------- ------------------------------------ version | PostgreSQL 9.0.7 en i486-pc-linux-gnu, compilado por GCC gcc-4.4.real (Ubuntu 4.4.3-4ubuntu5) 4.4.3, 32 bits comando_archivo | prueba -f /etc/postgresql/9.0/main/wal-ed/ARCHIVING_OFF || envdir /etc/postgresql/9.0/resource29857_heroku_com/wal-ed/env wal-e wal-push% p archive_mode | en archive_timeout | 1 minuto checkpoint_completion_target | 0.7 checkpoint_segments | 40 client_min_messages | aviso cpu_index_tuple_cost | 0.001 cpu_operator_cost | 0,0005 cpu_tuple_cost | 0.003 eficaz_caché_tamaño | 1530000kB hot_standby | en lc_collate | en_US.UTF-8 lc_ctype | en_US.UTF-8 listen_addresses | * * log_checkpoints | en log_destination | syslog log_line_prefix | % u [AMARILLO] log_min_duration_statement | 50ms log_min_messages | aviso logging_collector | en mantenimiento_trabajo_mem | 64MB max_ connections | 500 max_prepared_transactions | 500 max_stack_depth | 2MB max_standby_archive_delay | -1 max_standby_streaming_delay | -1 max_wal_senders | 10 puerto | random_page_cost | 2 codificación_servidor | UTF8 shared_buffers | 415MB ssl | en syslog_ident | resource29857_heroku_com TimeZone | UTC wal_buffers | 8MB wal_keep_segments | 127 wal_level | hot_standby work_mem | 100MB (39 filas)
EDITAR
Parece que ORDER BY
es la parte lenta:
d6ifslbf0ugpu=> EXPLAIN ANALYZE SELECT "entities"."name",
ts_rank(to_tsvector('english', "entities"."name"::text),
to_tsquery('english', 'banana'::text)) AS "rank0.48661998202865475"
FROM "entities"
WHERE (to_tsvector('english', "entities"."name"::text) @@ to_tsquery('english', 'banana'::text))
LIMIT 5;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=43.31..53.07 rows=5 width=24) (actual time=76.583..103.623 rows=5 loops=1)
-> Bitmap Heap Scan on entities (cost=43.31..4467.60 rows=2266 width=24) (actual time=76.581..103.613 rows=5 loops=1)
Recheck Cond: (to_tsvector('english'::regconfig, (name)::text) @@ '''banana'''::tsquery)
-> Bitmap Index Scan on gin_ix_entity_full_text_search_name (cost=0.00..43.20 rows=2266 width=0) (actual time=53.592..53.592 rows=1495 loops=1)
Index Cond: (to_tsvector('english'::regconfig, (name)::text) @@ '''banana'''::tsquery)
Total runtime: 103.680 ms
Vs. con ORDER BY
:
d6ifslbf0ugpu=> EXPLAIN ANALYZE SELECT "entities"."name",
ts_rank(to_tsvector('english', "entities"."name"::text),
to_tsquery('english', 'banana'::text)) AS "rank0.48661998202865475"
FROM "entities"
WHERE (to_tsvector('english', "entities"."name"::text) @@ to_tsquery('english', 'banana'::text))
ORDER BY "rank0.48661998202865475" DESC
LIMIT 5;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=4475.12..4475.13 rows=5 width=24) (actual time=15013.735..15013.741 rows=5 loops=1)
-> Sort (cost=4475.12..4476.26 rows=2266 width=24) (actual time=15013.732..15013.735 rows=5 loops=1)
Sort Key: (ts_rank(to_tsvector('english'::regconfig, (name)::text), '''banana'''::tsquery))
Sort Method: top-N heapsort Memory: 17kB
-> Bitmap Heap Scan on entities (cost=43.31..4467.60 rows=2266 width=24) (actual time=0.872..15006.763 rows=1495 loops=1)
Recheck Cond: (to_tsvector('english'::regconfig, (name)::text) @@ '''banana'''::tsquery)
-> Bitmap Index Scan on gin_ix_entity_full_text_search_name (cost=0.00..43.20 rows=2266 width=0) (actual time=0.549..0.549 rows=1495 loops=1)
Index Cond: (to_tsvector('english'::regconfig, (name)::text) @@ '''banana'''::tsquery)
Total runtime: 15013.805 ms
Bit Todavía no entiendo por qué esto es más lento. Parece que está obteniendo la misma cantidad de filas de Bitmap Heap Scan, pero ¿lleva mucho más tiempo?