Мгновенный автодополнитель на 240 миллионах доменов
Позволь рассказать об одном подходе, который буквально сломал мне мозг, когда я впервые о нём услышал.
Представь: у тебя 240 миллионов доменов. Пользователь печатает «wik», и результаты появляются до того, как он отпустит клавишу «k». То есть для него задержка равна нулю. Буквально.
Как это работает?
Проблема: мгновенный отклик на 240 миллионах записей
Автор статьи работает над Wirewiki.com — инструментом для исследования интернет-инфраструктуры. Там можно посмотреть DNS-записи, историю делегирования доменов, настройки почты и многое другое.
Конкурентов — десятки. Поэтому ставка сделана на UX: автодополнение должно быть моментальным. Не «быстрым». Не «отзывчивым». Моментальным — как будто результаты уже лежат рядом.
240 миллионов доменов — это серьёзный объём данных. Обычный поиск по базе с запросом вроде SELECT * FROM domains WHERE name LIKE 'wik%' здесь не катит: даже с индексом это десятки миллисекунд. А пользователь видит «тормозит».
Почему обычный подход не работает
Классическая схема автодополнения выглядит так:
ОБЫЧНЫЙ ПОДХОД
──────────────
Нажатие Отжатие Результат
▼ ▼ ▼
├───────────┼───────────┤
└──────────▶│
Поиск
в БД
(~50-200мс)
Воспринимаемая задержка: 50-200мс
50–200 миллисекунд — это уже заметно. Мозг человека воспринимает задержку больше 100 мс как «тормозит». А автор хотел ноль.
Механика: предвыборка на каждое нажатие
Секрет в том, чтобы запрашивать данные раньше, чем они понадобятся.
Весь фокус — в разнице между keyDown и keyUp. Между ними проходит примерно 50–100 миллисекунд. Это и есть наш временной бюджет.
Схема работы:
- keyDown: пользователь нажал «w» → сразу запрашиваем варианты для «w» и «w + любая следующая буква»
- keyUp: пользователь отпустил «w» → рендерим полученные варианты
- Повторяем для следующей буквы
ОПТИМИЗИРОВАННЫЙ ПОДХОД
───────────────────────
Пользователь: w i k
▼ ▼ ▼
keyDown: Запрос "wi" Запрос "wik"
(предвыборка) (предвыборка)
│ │
keyUp: Рендер "w*" Рендер "wi*" Рендер "wik*"
(данные уже (данные уже
получены) получены)
Воспринимаемая задержка: ~0мс
Если сервер ответит быстрее, чем пользователь нажмёт следующую клавишу, — результаты появятся мгновенно. Для пользователя это выглядит как магия.
Как устроен поиск под капотом
240 миллионов доменов — это много. Но структура URL-адресов предсказуема: они состоят из букв, цифр, точек и дефисов.
Автор не хранит домены в традиционной базе. Вместо этого:
- Компактное хранение: все варианты для каждого префикса предвычислены и лежат в памяти
- Плоская структура: ответ содержит не только текущие результаты, но и «следующие» — для каждой возможной следующей буквы
- CDN и кэширование: статические ответы раздаются с границы сети
Формат ответа API:
{
"results": ["wikipedia.org", "wikimedia.org", ...],
"next": {
"a": ["wikipedia.org", ...],
"k": ["wikihow.com", ...],
"z": ["wizzair.com", ...]
}
}
Пользователь видит текущие результаты. Параллельно в фоне уже загружаются варианты для w + a, w + k, w + z и так далее.
Что такое p99 и почему там ноль
P99 — это 99-й процентиль. То есть 99% запросов выполняются быстрее этого значения. Если P99 = 0 мс, это значит, что в 99% случаев результат готов до того, как мы его попросили.
Звёздочка в заголовке статьи важна: это не «ноль» как отсутствие задержки. Это задержка ниже порога измерения — потому что данные уже были предвыбраны.
На экране с частотой 60 Гц кадр обновляется каждые 16,7 миллисекунды. Если ответ пришёл раньше следующего кадра — пользователь не фиксирует задержку вообще.
Ограничения: память, цена и хрупкость
Решение не бесплатное. Вот цена:
- Предвычисление всех вариантов означает огромный объём данных в памяти
- Предвыборка на каждый
keyDownгенерирует трафик: не все запросы нужны - Хрупкость при нестабильной сети: если пользователь на Wi‑Fi с высокой задержкой, схема ломается
- Узкая специализация: подход заточен под автодополнение префиксов
Практический вывод
Это не просто хак. Это пример переосмысления архитектуры под конкретную задачу.
Вместо того чтобы оптимизировать скорость поиска, автор убрал поиск как узкое место. Данные уже готовы — нужно только показать.
- Временной бюджет как метрика: оптимизируйте под реальные 50–100 мс между нажатиями
- Предвыборка вместо оптимизации: иногда проще загрузить лишнее, чем ускорить основной путь
- Данные для следующего шага: если пользователь делает X, заранее готовьте Y
Моя оценка
Меня зацепила честность автора со звёздочкой. Он не утверждает, что победил физику. Он показывает, как воспринимаемый ноль достигается через предвычисление и предвыборку.
Для меня это хороший пример: иногда лучше пересмотреть архитектуру взаимодействия, чем оптимизировать существующую. 240 миллионов доменов — это не «большая таблица». Это набор префиксов, которые можно разложить и раздать как статику.
Единственное, что смущает: цена хранения. Если у вас нет пары сотен гигабайт оперативки и CDN с хорошим кэшированием — схема не взлетит. Это решение для больших проектов с соответствующим бюджетом.
Но как концепция — чистое инженерное мышление.
Ссылки
- Оригинальная статья: P99 0 ms autocomplete for 240 million domain names — материал Ruurtjan Pul о предвыборке и мгновенном автодополнении
- Wirewiki.com — инструмент для исследования интернет-инфраструктуры
Дмитрий Полухин — продуктовый дизайнер. Пишу про разработку, AI и дизайн интерфейсов. Обо мне, контакты и профили.