У меня есть небольшая база данных PostgreSQL (~ ~ 3000 строк).PostgreSQL Поиск по всему тексту: почему поиск медленнее?
Я пытаюсь настроить полнотекстовый поиск в одном из его текстовых полей («тело»).
Проблема в том, что любой запрос выполняется очень медленно (35+ секунд !!!).
Я полагаю, что проблема возникает из-за того, что DB выбирает режим последовательного сканирования ...
Это мой запрос:
SELECT
ts_rank_cd(to_tsvector('italian', body), query),
ts_headline('italian', body, to_tsquery('torino')),
title,
location,
id_author
FROM
fulltextsearch.documents, to_tsquery('torino') as query
WHERE
(body_tsvector @@ query)
OFFSET
0
Это EXPLAIN ANALYZE:
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------
Limit (cost=0.00..1129.81 rows=19 width=468) (actual time=74.059..13630.114 rows=863 loops=1)
-> Nested Loop (cost=0.00..1129.81 rows=19 width=468) (actual time=74.056..13629.342 rows=863 loops=1)
Join Filter: (documents.body_tsvector @@ query.query)
-> Function Scan on to_tsquery query (cost=0.00..0.01 rows=1 width=32) (actual time=4.606..4.608 rows=1 loops=1)
-> Seq Scan on documents (cost=0.00..1082.09 rows=3809 width=591) (actual time=0.045..48.072 rows=3809 loops=1)
Total runtime: 13630.720 ms
Это моя таблица:
mydb=# \d+ fulltextsearch.documents;
Table "fulltextsearch.documents"
Column | Type | Modifiers | Storage | Description
---------------+-------------------+-----------------------------------------------------------------------+----------+-------------
id | integer | not null default nextval('fulltextsearch.documents_id_seq'::regclass) | plain |
id_author | integer | | plain |
body | character varying | | extended |
title | character varying | | extended |
location | character varying | | extended |
date_creation | date | | plain |
body_tsvector | tsvector | | extended |
Indexes:
"fulltextsearch_documents_tsvector_idx" gin (to_tsvector('italian'::regconfig, COALESCE(body, ''::character varying)::text))
"id_idx" btree (id)
Triggers:
body_tsvectorupdate BEFORE INSERT OR UPDATE ON fulltextsearch.documents FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger('body_tsvector', 'pg_catalog.italian', 'body')
Has OIDs: no
Я уверен, что мне не хватает чего-то очевидного ....
Любые подсказки?
.
.
.
=== ОБНОВЛЕНИЕ =========================================================== ==========================================
Благодаря вашим предложениям я придумал этот (лучший) запрос:
SELECT
ts_rank(body_tsvector, query),
ts_headline('italian', body, query),
title,
location
FROM
fulltextsearch.documents, to_tsquery('italian', 'torino') as query
WHERE
to_tsvector('italian', coalesce(body,'')) @@ query
, который является довольно хорошим, но всегда очень медленным (13+ секунд ...).
Я замечаю, что комментируя строку «ts_headline()», запрос является молниеносным.
Это EXPLAIN ANALYZE, который, наконец, использует индекс, но не поможет мне много ...:
EXPLAIN ANALYZE SELECT
clock_timestamp() - statement_timestamp() as elapsed_time,
ts_rank(body_tsvector, query),
ts_headline('italian', body, query),
title,
location
FROM
fulltextsearch.documents, to_tsquery('italian', 'torino') as query
WHERE
to_tsvector('italian', coalesce(body,'')) @@ query
Nested Loop (cost=16.15..85.04 rows=19 width=605) (actual time=102.290..13392.161 rows=863 loops=1)
-> Function Scan on query (cost=0.00..0.01 rows=1 width=32) (actual time=0.008..0.009 rows=1 loops=1)
-> Bitmap Heap Scan on documents (cost=16.15..84.65 rows=19 width=573) (actual time=0.381..4.236 rows=863 loops=1)
Recheck Cond: (to_tsvector('italian'::regconfig, (COALESCE(body, ''::character varying))::text) @@ query.query)
-> Bitmap Index Scan on fulltextsearch_documents_tsvector_idx (cost=0.00..16.15 rows=19 width=0) (actual time=0.312..0.312 rows=863 loops=1)
Index Cond: (to_tsvector('italian'::regconfig, (COALESCE(body, ''::character varying))::text) @@ query.query)
Total runtime: 13392.717 ms
Планировщик прост и консервативен в выборе индекса. Он не будет искать язык tsearch2 по умолчанию, чтобы узнать, является ли это 'italian', а затем обрабатывает версию, не определенную языком, так же, как и язык-указана-как-итальянская версия, для того чтобы оба вызова функций были * одинаковыми *. Фактически, в этом отношении планировщик может быть немного тусклым - в прошлый раз, когда я проверил, было довольно много простых вариаций в отношении того, как вы могли бы написать выражение - например, резервные скобки - это привело бы к тому, что планировщик не узнал, что он соответствует индексу , –
@Richard Huxton Спасибо за ваш ответ. Под «поиском против» вы имеете в виду предложение FROM? Если да, не могли бы вы разместить образец правильного предложения FROM для моей ситуации? Извините, я все еще довольно смущен ... – MarcoS
http://www.postgresql.org/docs/current/static/textsearch-controls.html#TEXTSEARCH-HEADLINE «ts_headline использует исходный документ, а не сводку tsvector, поэтому он может быть медленным и должен использоваться с осторожностью ... » –