Я пытаюсь реализовать функцию поиска, и после некоторого исследования (см. это интересное чтение Йориком Петерсе в GitLab ) я решил, что выберу триграмный подход с использованием расширения pg_trgm
.
Я хотел бы вернуть 10 наиболее релевантных строк.
Вот пара запросов, которые я протестировал (следуя документу ) к таблице с 110868 строками:
SELECT name, similarity(name, 'search query') AS sml
FROM table
ORDER BY sml DESC, name;
Time: 701.814 ms
SELECT name, similarity(name, 'search query') AS sml
FROM table
WHERE name % 'search query'
ORDER BY sml DESC, name;
Time: 376.692 ms
SELECT name, similarity(name, 'search query') AS sml
FROM table
WHERE name % 'search query'
ORDER BY sml DESC, name LIMIT 10;
Time: 378.921 ms
С индексом GiST:
CREATE INDEX trigram_index ON table USING GIST (name gist_trgm_ops);
SELECT name, similarity(name, 'search query') AS sml
FROM table
WHERE name % 'search query'
ORDER BY sml DESC, name LIMIT 10;
Time: 36.877 ms
С индексом GIN:
CREATE INDEX trigram_index ON table USING GIN (name gin_trgm_ops);
SELECT name, similarity(name, 'search query') AS sml
FROM table WHERE name % 'search query'
ORDER BY sml DESC, name LIMIT 10;
Time: 18.992 ms
С АНАЛИЗОМ EXPLAIN:
Limit (cost=632.37..632.39 rows=10 width=25) (actual time=22.202..22.204 rows=10 loops=1)
-> Sort (cost=632.37..632.64 rows=111 width=25) (actual time=22.201..22.201 rows=10 loops=1)
Sort Key: (similarity((name)::text, 'search query'::text)) DESC, name
Sort Method: top-N heapsort Memory: 26kB
-> Bitmap Heap Scan on table (cost=208.86..629.97 rows=111 width=25) (actual time=6.900..22.157 rows=134 loops=1)
Recheck Cond: ((name)::text % 'search query'::text)
Rows Removed by Index Recheck: 2274
Heap Blocks: exact=2257
-> Bitmap Index Scan on trigram_index (cost=0.00..208.83 rows=111 width=0) (actual time=6.532..6.532 rows=2408 loops=1)
Index Cond: ((name)::text % 'World of Warcraft'::text)
Planning time: 0.073 ms
Execution time: 18.521 ms
ИспользованиеИндекс GIN значительно улучшает производительность.Ограничение результата до 10 строк, похоже, не оказывает никакого влияния.
Есть ли еще возможности для улучшения, которое я не рассматривал?Меня особенно интересуют предложения, которые могли бы использовать тот факт, что мне нужно только небольшое подмножество всей таблицы.