Контекст: В PlaceService.List GetTagsBatch и GetFeaturesBatch вызывались на полном списке мест, включая лишний элемент limit+1 (нужен только для определения hasMore).
Репозиторий возвращает limit+1 записей для cursor-based пагинации. Лишняя запись нужна только для флага hasMore и сразу отбрасывается.
Проблема: batch-запросы тегов и фич выполнялись ДО обрезки лишней записи — лишний SQL-запрос к таблицам place_tags и place_features.
// было:
places = fetch(limit+1)
tagsMap = GetTagsBatch(places) // ← лишний запрос для limit+1 элемента
featuresMap = GetFeaturesBatch(places) // ← лишний запрос для limit+1 элемента
places = places[:limit]
hasMore = true
// стало:
places = fetch(limit+1)
hasMore = len(places) > limit
places = places[:limit] // ← обрезка ДО batch-запросов
tagsMap = GetTagsBatch(places) // ← только limit элементов
featuresMap = GetFeaturesBatch(places)
Файл: backend/internal/services/places.go:142-190
Code review 2026-07-01, исправление P1.
#backend #performance #pagination #n-plus-one #sql