~ / посты / every-keystroke-waited-for-the-one-before-it

Подсказки поиска тормозили из-за очереди server actions и ILIKE по городам — города переехали в память_

отказ

Хотел мгновенные подсказки в поиске: человек набирает три буквы и сразу видит города и школы, без кнопки «найти».

Получилось наоборот. Поле молчало секунду-полторы, а потом выбрасывало пачку подсказок разом — ответы на все нажатые буквы сразу. Короткие запросы вроде «ma» или «se» отвечали 2,1 с и приходили вообще без городов.

Споткнулся о две вещи, и обе оказались не там, где я искал.

Первая — не моя: клиентские server actions фреймворк выполняет строго по очереди, одну за другой. Тайпахед делает запрос на каждое нажатие, и каждый следующий честно стоял в хвосте за предыдущим. Троттлинг на клиенте такую очередь не лечит: она не на моей стороне.

Вторая — моя: города искались в базе через ILIKE без индекса, и для каждого найденного города запрос досчитывал число школ. На узком запросе это 1,2 с, на коротком — упор в таймаут 2 с и ответ 500, так что группа городов в подсказках приходила пустой. Заодно выяснилось, что ILIKE по названию с диакритикой не находит того, что люди набирают: «malaga», «cordoba» и «gijon» не давали ничего, а «valencia» отдавала две деревни вместо города с 379 школами.

Решил убрать из подсказок и то и другое. Дерево локаций API и так держит в памяти, и города теперь ищутся по нему. Название складывается в сравнимый вид — нижний регистр, без ударений, всё кроме букв и цифр становится пробелом, — а дальше поиск идёт по уровням: название целиком, начало названия, начало слова внутри названия, подстрока и начало с одной-двумя опечатками. Худший случай на восьми тысячах городов — 6 мс в бенчмарке. Server action для тайпахеда выброшен: браузер ходит в эндпоинт подсказок сам и отменяет устаревший запрос, как только нажата следующая буква.

Замер на проде до и после: некэшированная подсказка 0,9–1,5 с → 0,10–0,25 с, короткий запрос 2,1 с с пустыми городами → 0,25 с.

Чем плачу. Нечёткий поиск теперь мой код, а не возможность базы: складывание названий, расстояние с перестановкой соседних букв, порядок уровней совпадения — всё это я написал сам и сам покрыл тестами, и каждый новый случай вроде «la coruna» → «A Coruña» буду добавлять руками. Подсказки видят данные не новее кэша: город, добавленный минуту назад, появится после перезагрузки дерева, а не сразу. И восемь тысяч городов с заранее сложенными формами названия лежат в памяти процесса — пока это мелочь, но мелочь постоянная, и она растёт вместе со справочником.

#отказ

$ echo "читать серию"

← Все посты