#postgresql #full-text-search
#postgresql #полнотекстовый поиск
Вопрос:
ИСПОЛЬЗОВАНИЕ ПРОСТОГО ПОЛНОТЕКСТОВОГО ЗАПРОСА:
Я использовал только столбец, который индексируется в SELECT, чтобы избежать дополнительных операций чтения с диска.
EXPLAIN (ANALYZE,BUFFERS)
SELECT products_vector
FROM products
WHERE
products_vector @@ to_tsquery('simple', 'sulfuric | acid | 0.1n');
Результат:
Bitmap Heap Scan on products (cost=2190.65..295693.90 rows=116987 width=148) (actual time=715.964..315781.144 rows=111681 loops=1)
Recheck Cond: (products_vector @@ '''sulfuric'' | ''acid'' | ''0.1'' amp; ''n'''::tsquery)
Heap Blocks: exact=84740
Buffers: shared hit=6 read=85492
-> Bitmap Index Scan on idx_fulltext_search (cost=0.00..2161.40 rows=116987 width=0) (actual time=643.421..643.428 rows=112306 loops=1)
Index Cond: (products_vector @@ '''sulfuric'' | ''acid'' | ''0.1'' amp; ''n'''::tsquery)
Buffers: shared hit=6 read=322
Planning Time: 808.165 ms
JIT:
Functions: 4
Options: Inlining false, Optimization false, Expressions true, Deforming true
Timing: Generation 2.253 ms, Inlining 0.000 ms, Optimization 2.188 ms, Emission 24.550 ms, Total 28.991 ms
Execution Time: 316028.302 ms
(13 rows)
ОГРАНИЧЕНИЕ КОЛИЧЕСТВА ИЗВЛЕКАЕМЫХ СТРОК (но добавляется ранжирование):
EXPLAIN (ANALYZE,BUFFERS)
SELECT * FROM (
SELECT
id,
ts_rank(products_vector, to_tsquery('simple', 'sulfuric | acid | 0.1n') ) as score
FROM products
WHERE
products_vector @@ to_tsquery('simple', 'sulfuric | acid | 0.1n')
) as t1
ORDER BY score DESC
LIMIT 20 OFFSET 0;
Результат:
Limit (cost=299099.35..299099.40 rows=20 width=8) (actual time=755802.185..755802.190 rows=20 loops=1)
Buffers: shared hit=364399 read=140370
-> Sort (cost=299099.35..299391.82 rows=116987 width=8) (actual time=755248.597..755248.600 rows=20 loops=1)
Sort Key: (ts_rank(products.products_vector, '''sulfuric'' | ''acid'' | ''0.1'' amp; ''n'''::tsquery)) DESC
Sort Method: top-N heapsort Memory: 26kB
Buffers: shared hit=364399 read=140370
-> Bitmap Heap Scan on products (cost=2190.65..295986.37 rows=116987 width=8) (actual time=1144.787..755097.254 rows=111681 loops=1)
Recheck Cond: (products_vector @@ '''sulfuric'' | ''acid'' | ''0.1'' amp; ''n'''::tsquery)
Heap Blocks: exact=84740
Buffers: shared hit=364396 read=140370
-> Bitmap Index Scan on idx_fulltext_search (cost=0.00..2161.40 rows=116987 width=0) (actual time=956.063..956.064 rows=112306 loops=1)
Index Cond: (products_vector @@ '''sulfuric'' | ''acid'' | ''0.1'' amp; ''n'''::tsquery)
Buffers: shared hit=6 read=322
Planning Time: 728.459 ms
JIT:
Functions: 6
Options: Inlining false, Optimization false, Expressions true, Deforming true
Timing: Generation 2.352 ms, Inlining 0.000 ms, Optimization 184.210 ms, Emission 358.190 ms, Total 544.751 ms
Execution Time: 757308.337 ms
Я могу заметить, что читается большое количество строк, но у меня нет другого выбора, кроме как читать их в этих случаях.
Выполнение даже запроса с использованием to_tsquery(‘simple’, ‘sulphuric amp; acid amp; 0.1n’) занимает более минуты.
Мои вопросы:
- Как мне ускорить эти запросы?
- Является ли «сканирование кучи растровых изображений» медленным из-за неправильных настроек? В таком случае, как мне их идентифицировать?
- Я пытался исключить «сканирование кучи растровых изображений», не выбирая в первом запросе никакой другой столбец, кроме product_vector? Почему он все еще медленный?
Заранее спасибо
Ответ №1:
Я использовал только столбец, который индексируется в SELECT, чтобы избежать дополнительных операций чтения с диска.
Это не работает с индексом GIN, так как значение каждого столбца разбивается на несколько строк индекса. Вы не можете повторно собрать исходное значение из записей индекса, вам нужно посетить таблицу, чтобы получить исходное значение.
Что произойдет, если вы даже не выберете индексированный столбец, например count(*)
? Если вы выполняете значение несколько раз подряд, каково время повторного выполнения? Какие планы вы получите, если включите track_io_timing
?
но у меня нет другого выбора, кроме как читать их в этих случаях.
Почему бы и нет?
Выполнение даже запроса с использованием to_tsquery(‘simple’, ‘sulphuric amp; acid amp; 0.1n’) занимает более минуты.
Что такое EXPLAIN (ANALYZE, BUFFERS)
(с track_io_timing
включенным) для этого?