У меня есть простая таблица в Postgres с более чем 8 миллионами строк.Интересующий столбец содержит короткие текстовые строки, обычно одно или несколько слов общей длиной менее 100 символов.Это установлено как 'изменение символа (100)'.Столбец индексируется.Простой поиск, как показано ниже, занимает> 3000 мс.
SELECT a, b, c FROM t WHERE a LIKE '?%'
Да, сейчас нужно просто найти строки, где "a" начинается с введенного текста.Я хочу довести скорость просмотра до 100 мс (появление мгновенно).Предложения?Мне кажется, что полнотекстовый поиск здесь не поможет, так как моя колонка текста слишком коротка, но я был бы рад попробовать, если это того стоит.
О, кстати, я также загрузил те же самые данные в mongodbи индексированный столбец «а».Загрузка данных в mongodb была удивительно быстрой (mongodb ++).И mongodb, и Postgres в значительной степени мгновенны при выполнении точных поисков.Но Postgres на самом деле светит, когда выполняет поиск по подстановочным знакам, как указано выше, последовательно занимая примерно 1/3 длины mongodb.Я был бы счастлив продолжить mongodb, если бы мог ускорить это, поскольку это только операция только для чтения.
Обновление: Сначала пара EXPLAIN ANALYZE
выходов
EXPLAIN ANALYZE SELECT a, b, c FROM t WHERE a LIKE 'abcd%'
"Seq Scan on t (cost=0.00..282075.55 rows=802 width=40)
(actual time=1220.132..1220.132 rows=0 loops=1)"
" Filter: ((a)::text ~~ 'abcd%'::text)"
"Total runtime: 1220.153 ms"
Я на самом деле хочу сравнить Lower(a)
с поисковым термином, длина которого не менее 4 символов, поэтому
EXPLAIN ANALYZE SELECT a, b, c FROM t WHERE Lower(a) LIKE 'abcd%'
"Seq Scan on t (cost=0.00..302680.04 rows=40612 width=40)
(actual time=4.681..3321.387 rows=788 loops=1)"
" Filter: (lower((a)::text) ~~ 'abcd%'::text)"
"Total runtime: 3321.504 ms"
Итак, я создал индекс
CREATE INDEX idx_t ON t USING btree (Lower(Substring(a, 1, 4) ));
"Seq Scan on t (cost=0.00..302680.04 rows=40612 width=40)
(actual time=3243.841..3243.841 rows=0 loops=1)"
" Filter: (lower((a)::text) = 'abcd%'::text)"
"Total runtime: 3243.860 ms"
Кажется,индекс используется только тогда, когда я ищу точное совпадение
EXPLAIN ANALYZE SELECT a, b, c FROM t WHERE a = 'abcd'
"Index Scan using idx_t on geonames (cost=0.00..57.89 rows=13 width=40)
(actual time=40.831..40.923 rows=17 loops=1)"
" Index Cond: ((ascii_name)::text = 'Abcd'::text)"
"Total runtime: 40.940 ms"
Нашел решение, внедрив индекс с varchar_pattern_ops
, а теперь ищет еще более быстрые поиски .