@setupx
Go & TS developer

10к строк по базе размером 500кк?

Есть вот такая база
CREATE TABLE base
(
    id       BIGSERIAL PRIMARY KEY,
    url      text NOT NULL,
    login    text NOT NULL,
    name text NOT NULL
);


Какими способами можно ускорить поиск по совпадениям url/login/name?
Некоторые индексы вообще отказываются применяться: размер строки индекса (3432) больше предельного для btree версии 4 размера (2704) (индекс "idx_base_url") (SQLSTATE 54000)

Условно в БД есть записи в url со словом login: "cloudflare.com/login", "login.test.com", и мне нужно реализовать поиск по таким столбцам и на выходе получить не более 10к строк не более чем за 10 секунд.

P.S: если нужно: на бэке используется Golang
P.S2: кэшировать данные не вариант, т.к после поиска строк человеком, эти строки удаляются
  • Вопрос задан
  • 300 просмотров
Пригласить эксперта
Ответы на вопрос 6
@Akina
Сетевой и системный админ, SQL-программист.
Запрос
SELECT * FROM base WHERE domain LIKE '%habr%' LIMIT 10000;


Какой это нахрен поиск "по совпадениям"??? Это, блин, поиск по подстроке!!! причём в любом месте строки.

С таким шаблоном поиска можете с обычными индексами вообще не трахаться, по причине абсолютной бессмысленности действа. Читайте про GIN, GiST, RUM и прочие виды индексов и поиск с их использованием.
Ответ написан
Комментировать
@galaxy
SELECT * FROM base WHERE domain LIKE '%habr%' LIMIT 10000;


проще всего так, наверно:

CREATE EXTENSION pg_trgm;

CREATE INDEX trgm_domain_base_idx ON base USING GIST (domain gist_trgm_ops);

EXPLAIN ANALYZE SELECT * FROM base WHERE domain LIKE '%habr%' LIMIT 10000;


https://www.postgresql.org/docs/current/pgtrgm.html
Ответ написан
Комментировать
ky0
@ky0
Миллиардер, филантроп, патологический лгун
Первое, что приходит в голову - разделить домен и URI. Тогда можно будет сначала поискать по индексу доменов, а потом уже эту выборку по урлу.
Ответ написан
Fragster
@Fragster
помогло? отметь решением!
индекс по like %login% не будет применяться. нужно добавить колонку типа булево и partial index на неё. При вставке/обновлении и один раз при создании колонки - заполнить её значением true для нужных строк.
Ответ написан
@rPman
Избавляйся от like '%...%', это худший способ искать, он индексы не использует
даже поиск с регулярными выражениями работает лучше (правда там лимит на размер строки)

Если like используется чтобы искать части url, то храни в базе не целиком а разделенную по полям, в идеале чтобы поиск был на равенство (даже если база увеличится и станет сложнее, например тебе нужно искать по параметрам GET url, т.е. потребуется создать еще одну таблицу на них, скорость все равно будет хорошей)
Ответ написан
Комментировать
@Makcimmm
А мне первое что приходит на ум, реализовать собственный словарик + табличку в которой будут указаны сопоставления ID слов из словарика и ID из таблицы с текстом в которых встречается данное слово.
Я так делал, когда на проекте поиск был по большим кускам текста, который был в BLOB-ах. Я разделял текст на слова по пробелам.
Использовали этот поиск редко, но когда запускали, он висел минут 10-20, люди уходили пить чай наверно :) и всех это устраивало. Но однажды этот поиск повесил БД, и эта проблема оказалась в поле моего зрения. После формирования словарика и добавления функций чтобы по новым записям так же добавлялась инфа в словарик, поиск стал занимать доли секунды :)
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы