Ich habe einen großen Tisch entities
mit ~ 15 Millionen Datensätzen. Ich möchte die Top 5 Reihen finden, die zu 'Hockey' passen name
.
Ich habe einen Volltextindex name
, der verwendet wird:gin_ix_entity_full_text_search_name
Abfrage:
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
Dauer 25.623 ms
Plan erklären 1 Limit (Kosten = 12666.89..12666.89 Zeilen = 5 Breite = 3116) 2 -> Sortieren (Kosten = 12666.89..12670.18 Zeilen = 6571 Breite = 3116) 3 Sortierschlüssel: (ts_rank (to_tsvector ('english' :: regconfig, (name) :: text), '' 'hockey' '' :: tsquery)) 4 -> Bitmap-Heap-Scan für Entitäten (Kosten = 124.06..12645.06 Zeilen = 6571 Breite = 3116) 5 Überprüfen Sie erneut Cond: (to_tsvector ('english' :: regconfig, (name) :: text) @@ '' 'hockey' '' :: tsquery) 6 Filter: (NICHT platzieren) 7 -> Bitmap-Index-Scan für gin_ix_entity_full_text_search_name (Kosten = 0,00..123,74 Zeilen = 6625 Breite = 0) 8 Index Cond: (to_tsvector ('english' :: regconfig, (name) :: text) @@ '' 'hockey' '' :: tsquery)
Ich verstehe nicht, warum es die Indexbedingung zweimal überprüft. (Abfrageplan Schritt 4 und 7). Liegt es an meiner booleschen Bedingung ( not place
)? Wenn ja, sollte ich es meinem Index hinzufügen, um eine sehr schnelle Abfrage zu erhalten? Oder macht es die Sortierbedingung langsam?
EXPLAIN ANALYZE
Ausgabe:
Limit (Kosten = 4447,28..4447,29 Zeilen = 5 Breite = 3116) (tatsächliche Zeit = 18509,274..18509,282 Zeilen = 5 Schleifen = 1) -> Sortieren (Kosten = 4447,28..4448,41 Zeilen = 2248 Breite = 3116) (tatsächliche Zeit = 18509,271..18509,273 Zeilen = 5 Schleifen = 1) Sortierschlüssel: (ts_rank (to_tsvector ('english' :: regconfig, (name) :: text), '' 'test' '' :: tsquery)) Sortiermethode: Top-N-Heapsort Speicher: 19 KB -> Bitmap-Heap-Scan für Entitäten (Kosten = 43.31..4439.82 Zeilen = 2248 Breite = 3116) (tatsächliche Zeit = 119.003..18491.408 Zeilen = 2533 Schleifen = 1) Überprüfen Sie erneut Cond: (to_tsvector ('english' :: regconfig, (name) :: text) @@ '' 'test' '' :: tsquery) Filter: (NICHT platzieren) -> Bitmap-Index-Scan für gin_ix_entity_full_text_search_name (Kosten = 0,00..43,20 Zeilen = 2266 Breite = 0) (tatsächliche Zeit = 74,093..74,093 Zeilen = 2593 Schleifen = 1) Index Cond: (to_tsvector ('english' :: regconfig, (name) :: text) @@ '' 'test' '' :: tsquery) Gesamtlaufzeit: 18509.381 ms
Hier sind meine DB-Parameter. Es wird von Heroku auf Amazon-Diensten gehostet. Sie beschreiben es mit 1,7 GB RAM, 1 Prozessoreinheit und einer DB von maximal 1 TB.
Name | Aktuelle Einstellung ------------------------------ + ------------------- -------------------------------------------------- ------------------------------------ version | PostgreSQL 9.0.7 auf i486-pc-linux-gnu, kompiliert von GCC gcc-4.4.real (Ubuntu 4.4.3-4ubuntu5) 4.4.3, 32-Bit archive_command | 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 archive_mode | auf archive_timeout | 1 Minute checkpoint_completion_target | 0,7 checkpoint_segments | 40 client_min_messages | beachten cpu_index_tuple_cost | 0,001 cpu_operator_cost | 0,0005 cpu_tuple_cost | 0,003 effektive_cache_size | 1530000kB hot_standby | auf lc_collate | en_US.UTF-8 lc_ctype | en_US.UTF-8 listen_addresses | * * log_checkpoints | auf log_destination | Syslog log_line_prefix | % u [GELB] log_min_duration_statement | 50ms log_min_messages | beachten logging_collector | auf wartung_arbeit_mem | 64 MB max_connections | 500 max_prepared_transactions | 500 max_stack_depth | 2 MB max_standby_archive_delay | -1 max_standby_streaming_delay | -1 max_wal_senders | 10 port | random_page_cost | 2 server_encoding | UTF8 shared_buffers | 415 MB ssl | auf syslog_ident | resource29857_heroku_com Zeitzone | koordinierte Weltzeit wal_buffers | 8 MB wal_keep_segments | 127 wal_level | Hot-Standby work_mem | 100 MB (39 Zeilen)
BEARBEITEN
Sieht aus wie ORDER BY
ist der langsame Teil:
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. mit 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
Ich verstehe immer noch nicht, warum das langsamer ist. Sieht so aus, als würde es die gleiche Anzahl von Zeilen aus Bitmap Heap Scan abrufen, aber es dauert so viel länger?