Медленный поиск
Задержка поиска выше ожидаемой — диагностика холодных стартов, завышенного `perPage`, сложного `filterBy`, отсутствующих фасетов и давления вышестоящего поискового движка.
Здоровая медианная задержка поиска в AACsearch составляет < 50 мс внутри региона кластера, < 150 мс через публичный интернет. Если вы видите > 500 мс или спорадические тайм-ауты, пройдите по этим проверкам.
Симптомы
| Что вы видите | Первая проверка |
|---|---|
| Первый запрос медленный, последующие быстрые | Холодный старт — прогрейте холостым запросом |
| Все запросы медленные, даже второй | Форма запроса (perPage, filterBy) |
| Медленно только в пиковые часы | Поключевая конкурентность или давление вышестоящего кластера |
| Случайные всплески | Сетевой путь; проверьте из второго местоположения клиента |
| Тайм-ауты, 502, 503 | См. ошибки и лимиты запросов для стратегии повторов |
Дерево решений
Первый запрос после деплоя / перезапуска медленный?
└─ да → холодный старт, прогрейте холостым запросом:
client.search({ q: "*", perPage: 1 })
Все запросы медленные?
├─ perPage > 100 → уменьшить
├─ filterBy сложный → упростить или предвычислить
├─ фасетов > 10 полей → уменьшить или перенести на отдельные запросы
└─ всё минимально → проверить страницу статуса; открыть тикетПроверка 1: холодный старт
Первый запрос к только что развёрнутому воркеру может занимать на 200–500 мс дольше, чем в установившемся режиме, потому что ему нужно установить соединения и скомпилировать план запроса. Это нормально.
Если ваш паттерн трафика включает длительные периоды простоя (например, внутренний дашборд, используемый дважды в день), вы будете видеть это при каждом посещении.
Смягчение: прогрейте воркер до запроса пользователя:
// При запуске приложения или через cron/edge prewarm
await client.search({ q: "*", perPage: 1 });Для Vercel / Cloudflare Workers / аналогичных сред используйте запланированный вызов прогрева.
Проверка 2: завышенный perPage
perPage напрямую влияет на стоимость сериализации. Сервер масштабируется линейно после ~100; после ~250 доминирует кодирование JSON.
// ❌ Медленно даже на здоровом кластере
client.search({ q: "shoes", perPage: 1000 });
// ✅ Используйте пагинацию вместо этого
client.search({ q: "shoes", perPage: 50, page: 1 });Если вам действительно нужны все совпадения, используйте documents/export с административным ключом — он потоковый и пагинируется на серверной стороне.
Проверка 3: сложный filterBy
Фильтры с многими условиями || (ИЛИ) или глубокими скобками медленны, потому что каждая ветка вычисляется.
// ❌ Одно большое ИЛИ по множеству id
filterBy: "id:=[id1,id2,...,id500]";
// ✅ Используйте anyOf, который работает напрямую с инвертированным индексом
filterBy: "id:[id1,id2,...,id500]";
// ❌ Вложенные группы
filterBy: "(brand:=Nike && price:<100) || (brand:=Adidas && price:<150) || ...";
// ✅ Предвычислите поле тега на этапе индексации
filterBy: "discount_tier:=tier_a";Когда сомневаетесь, упростите фильтр и замерьте с помощью /search?stats=true (ответ включает searchTimeMs).
Проверка 4: слишком много фасетов
Каждое фасетное поле требует сортировки и агрегации по корзинам. После ~10 фасетов на запрос задержка заметно возрастает.
// ❌
facetBy: "brand,category,subcategory,size,color,material,season,fit,collection,store,warehouse";
// ✅ Показывайте только основные фасеты на первой странице; подгружайте вторичные лениво
facetBy: "brand,category,price";Остальные можно отрисовать отдельными вызовами multi-search только когда пользователь открывает эту группу фильтров.
Проверка 5: логирование запросов
Ответ включает поле searchTimeMs, если вы включите его. Сравните его с вашей сквозной задержкой, чтобы понять, где теряется время.
const result = await client.search({ q: "shoes", debug: true });
console.log("сервер:", result.searchTimeMs, "мс");
console.log("сквозная:", endTime - startTime, "мс");
// Разница > 100 мс предполагает сетевые или прокси-накладные расходы, а не движокПроверка 6: давление вышестоящего кластера
Если само значение searchTimeMs > 500 мс, проблема на вышестоящем уровне. Проверьте:
- https://status.aacsearch.com на наличие текущих инцидентов
- Поиск → Аналитика → график «p95 latency» (последние 24ч)
- Если вы self-hosted: память и CPU инстанса AACSearch
Если статус зелёный, а ваши метрики аномальны, откройте тикет — см. диагностический пакет ниже.
Проверка 7: исчерпание пула соединений (только сервер)
Для серверных высококонкурентных вызывающих (10k+ qps с одного Node-процесса) стандартный пул соединений fetch может троттлиться под нагрузкой. Настройте:
import { Agent } from "undici";
const agent = new Agent({
connections: 256, // по умолчанию 50
pipelining: 10,
});
const client = new SearchClient({
baseUrl: "...",
apiKey: "...",
indexSlug: "products",
dispatcher: agent,
});Для браузеров и Workers это не применимо.
Матрица решений
| Диагноз | Исправление |
|---|---|
| Холодный старт | Прогреть холостым запросом q: "*" |
perPage слишком высок | Уменьшить до ≤ 50, пагинировать |
| Сложный фильтр | Упростить; предвычислить поля тегов на этапе индексации |
| Слишком много фасетов | Ограничить основными при первой отрисовке, остальные лениво |
| Сервер действительно медленный | Проверить страницу статуса; сообщить searchTimeMs в поддержку |
| Сетевые накладные расходы | Использовать регион ближе к кластеру; переиспользовать keep-alive соединения |
| Пул соединений | Настроить undici Agent для серверных вызывающих |
Диагностический пакет
| Поле | Примечания |
|---|---|
| ID организации | обязательно |
| Slug индекса | обязательно |
| Временное окно (UTC) | начало и конец медленного периода |
searchTimeMs из примера ответа | обязательно |
| Медианная сквозная задержка | из вашего собственного мониторинга |
| Пример тела запроса | минимальный падающий случай |
| Регион вызывающего | датацентр / город / облачный регион |
| Конкурентность | запросов в секунду от этого вызывающего |
Если вы можете воспроизвести медленность одним curl, вставьте его. Воспроизводимые случаи решаются примерно в 4× быстрее, чем «иногда кажется медленным».
Связанные страницы
- Ошибки и лимиты запросов — для тайм-аутов, 5xx
- Мульти-поиск и запросы — эффективные формы запросов
- Переиндексация и нулевой простой — изменение схемы может вызвать прогрев
- Тарифы и лимиты — потолки конкурентности по тарифам
Пустые результаты
Поиск возвращает `found: 0` для запросов, которые должны находить совпадения — диагностика отсутствующих документов, слишком узких фильтров, фильтров токенов с ограниченной областью и несоответствий `queryBy`.
Виджет не загружается
Тег скрипта виджета на странице, но поисковый UI не появляется — диагностика сбоя загрузки скрипта, отсутствующего контейнера, блокировок CSP, проблем с ключом и монтирования в Shadow DOM.