Eu tenho uma mesa grande entities
com ~ 15 milhões de registros. Eu quero encontrar as 5 principais linhas correspondentes a 'hockey' na sua name
.
Eu tenho um índice de texto completo name
, usado:gin_ix_entity_full_text_search_name
Inquerir:
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
Duração 25.623 ms
Explique o plano 1 Limite (custo = 12666,89..12666,89 linhas = 5 largura = 3116) 2 -> Classificação (custo = 12666,89..12670,18 linhas = 6571 largura = 3116) 3 Chave de Classificação: (ts_rank (to_tsvector ('english' :: regconfig, (name) :: text), '' hockey '' '' :: tsquery))) 4 -> Verificação de heap de bitmap em entidades (custo = 124.06..12645.06 linhas = 6571 width = 3116) 5 Verifique novamente Cond: (to_tsvector ('english' :: regconfig, (name) :: text) @@ '' 'hockey' '' :: tsquery) 6 Filtro: (NÃO coloque) 7 -> Varredura de índice de bitmap no gin_ix_entity_full_text_search_name (custo = 0.00..123.74 linhas = 6625 width = 0) 8 Índice Cond: (to_tsvector ('english' :: regconfig, (name) :: text) @@ '' 'hockey' '' :: tsquery)
Não entendo por que ele verifica a condição do índice duas vezes. (Etapa 4 e 7 do plano de consulta). É por causa da minha condição booleana ( not place
)? Em caso afirmativo, devo adicioná-lo ao meu índice para obter uma consulta muito rápida? Ou a condição de classificação torna lenta?
EXPLAIN ANALYZE
resultado:
Limite (custo = 4447,28..4447,29 linhas = 5 largura = 3116) (tempo real = 18509,274..18509,282 linhas = 5 loops = 1) -> Classificação (custo = 4447,28..4448,41 linhas = 2248 largura = 3116) (tempo real = 18509,271..18509,273 linhas = 5 loops = 1) Chave de classificação: (ts_rank (to_tsvector ('english' :: regconfig, (name) :: text), '' test '' ':: :: tsquery))) Método de classificação: top-N heapsort Memória: 19kB -> Varredura de Heap de Bitmap em entidades (custo = 43.31..4439.82 linhas = 2248 largura = 3116) (tempo real = 119.003..18491.408 linhas = 2533 loops = 1) Verifique novamente Cond: (to_tsvector ('english' :: regconfig, (name) :: text) @@ '' 'test' '' :: tsquery) Filtro: (NÃO colocar) -> Varredura de índice de bitmap no gin_ix_entity_full_text_search_name (custo = 0.00..43.20 linhas = 2266 width = 0) (tempo real = 74.093..74.093 linhas = 2593 loops = 1) Índice Cond: (to_tsvector ('english' :: regconfig, (name) :: text) @@ '' 'test' '' :: tsquery) Tempo de execução total: 18509,381 ms
Aqui estão meus parâmetros de banco de dados. Está hospedado em Heroku, nos serviços da Amazon. Eles o descrevem como tendo 1,7 GB de RAM, 1 unidade de processamento e um banco de dados de no máximo 1 TB.
nome | Configuração atual ------------------------------ + ------------------- -------------------------------------------------- ------------------------------------ versão | PostgreSQL 9.0.7 no i486-pc-linux-gnu, compilado pelo GCC gcc-4.4.real (Ubuntu 4.4.3-4ubuntu5) 4.4.3, 32 bits arquivo_command | teste -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 | em archive_timeout | 1 minuto checkpoint_completion_target | 0,7 checkpoint_segments | 40. client_min_messages | aviso prévio cpu_index_tuple_cost | 0,001 cpu_operator_cost | 0,0005 cpu_tuple_cost | 0,003 effective_cache_size | 1530000kB hot_standby | em lc_collate | en_US.UTF-8 lc_ctype | en_US.UTF-8 listen_addresses | * log_checkpoints | em log_destination | syslog log_line_prefix | % u [AMARELO] log_min_duration_statement | 50ms log_min_messages | aviso prévio logging_collector | em maintenance_work_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 porto | random_page_cost | 2 server_encoding | UTF8 shared_buffers | 415MB ssl em syslog_ident | resource29857_heroku_com Fuso horário | UTC wal_buffers | 8MB wal_keep_segments | 127 wal_level | Hot Standby work_mem | 100MB (39 linhas)
EDITAR
Parece que ORDER BY
é a parte mais 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. com 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
Ainda não entendi por que isso é mais lento. Parece que está buscando a mesma quantidade de linhas do Bitmap Heap Scan, mas leva muito mais tempo?