Ho un grande tavolo entities
con ~ 15 milioni di record. Voglio trovare le prime 5 righe corrispondenti a "hockey" nelle loro name
.
Ho un indice di testo completo su name
, che viene utilizzato:gin_ix_entity_full_text_search_name
Query:
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
Durata 25.623 ms
Spiega il piano 1 limite (costo = 12666,89..12666,89 righe = 5 larghezza = 3116) 2 -> Ordina (costo = 12666,89..12670,18 righe = 6571 larghezza = 3116) 3 Chiave di ordinamento: (ts_rank (to_tsvector ('english' :: regconfig, (name) :: text), '' 'hockey' '' :: tsquery)) 4 -> Scansione heap bitmap su entità (costo = 124.06..12645.06 righe = 6571 larghezza = 3116) 5 Ricontrolla Cond: (to_tsvector ('inglese' :: regconfig, (nome) :: testo) @@ '' 'hockey' '' :: tsquery) 6 Filtro: (NON posizionare) 7 -> Scansione indice bitmap su gin_ix_entity_full_text_search_name (costo = 0,00..123,74 righe = 6625 larghezza = 0) 8 Index Cond: (to_tsvector ('english' :: regconfig, (name) :: text) @@ '' 'hockey' '' :: tsquery)
Non capisco perché verifica due volte la condizione dell'indice. (Piano di query passaggi 4 e 7). È a causa della mia condizione booleana ( not place
)? In tal caso, dovrei aggiungerlo al mio indice per ottenere una query molto veloce? O la condizione di smistamento lo rallenta?
EXPLAIN ANALYZE
produzione:
Limite (costo = 4447.28..4447.29 righe = 5 larghezza = 3116) (tempo effettivo = 18509.274..18509.282 righe = 5 anelli = 1) -> Ordina (costo = 4447.28..4448.41 righe = 2248 larghezza = 3116) (tempo effettivo = 18509.271..18509.273 righe = 5 loop = 1) Chiave di ordinamento: (ts_rank (to_tsvector ('english' :: regconfig, (name) :: text), '' 'test' '' :: tsquery)) Metodo di ordinamento: memoria heapsort top-N: 19kB -> Scansione heap bitmap su entità (costo = 43.31..4439.82 righe = 2248 larghezza = 3116) (tempo effettivo = 119.003..18491.408 righe = 2533 loop = 1) Ricontrolla Cond: (to_tsvector ('english' :: regconfig, (name) :: text) @@ '' 'test' '' :: tsquery) Filtro: (NON posizionare) -> Scansione indice bitmap su gin_ix_entity_full_text_search_name (costo = 0,00..43,20 righe = 2266 larghezza = 0) (tempo effettivo = 74.093..74.093 righe = 2593 loop = 1) Index Cond: (to_tsvector ('english' :: regconfig, (name) :: text) @@ '' 'test' '' :: tsquery) Durata totale: 18509.381 ms
Ecco i miei parametri DB. È ospitato da Heroku, sui servizi di Amazon. Lo descrivono con 1,7 GB di RAM, 1 unità di elaborazione e un DB di massimo 1 TB.
nome | impostazioni correnti ------------------------------ + ------------------- -------------------------------------------------- ------------------------------------ versione | PostgreSQL 9.0.7 su i486-pc-linux-gnu, compilato da GCC gcc-4.4.real (Ubuntu 4.4.3-4ubuntu5) 4.4.3, 32-bit comando_archivio | test -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 modalità_archivio | su archive_timeout | 1 minuto checkpoint_completion_target | 0.7 checkpoint_segments | 40 client_min_messages | Avviso cpu_index_tuple_cost | 0.001 cpu_operator_cost | 0,0005 cpu_tuple_cost | 0.003 efficient_cache_size | 1530000kB hot_standby | su lc_collate | en_US.UTF-8 lc_ctype | en_US.UTF-8 ascolta_indirizzo | * log_checkpoints | su log_destination | syslog log_line_prefix | % u [GIALLO] log_min_duration_statement | 50ms log_min_messages | Avviso logging_collector | su 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 codifica_server | UTF8 shared_buffers | 415MB ssl | su syslog_ident | resource29857_heroku_com TimeZone | UTC wal_buffers | 8MB wal_keep_segments | 127 wal_level | hot_standby work_mem | 100MB (39 file)
MODIFICARE
Sembra che ORDER BY
sia 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
Un po 'non capisco ancora perché sia più lento. Sembra che stia recuperando la stessa quantità di righe da Bitmap Heap Scan, ma impiega molto più tempo?