> Как реализовать эффективную пагинацию с курсорами и индексами (Go)

Уровень: senior · Роль: backend · Категория: Технические вопросы

Компании: sferaplatform.ru

Стек: Go

> Пример ответа

Для эффективной пагинации с курсорами в Go используйте комбинацию индекса B-tree и курсора на основе уникального сортируемого поля (например, id или created_at). Вместо OFFSET, который сканирует пропущенные строки, применяйте условие WHERE cursor > last_seen_value ORDER BY cursor LIMIT n. Это позволяет базе данных использовать индекс для прямого доступа к следующей порции данных.

Пример реализации:

GO
type CursorPaginator struct {
db *sql.DB
}
type PageParams struct {
Cursor string // последнее значение курсора (например, ID)
Limit int
}
type PageResult struct {
Items []Item
NextCursor string
HasMore bool
}
func (p *CursorPaginator) GetItems(params PageParams) (*PageResult, error) {
query := `
SELECT id, name, created_at
FROM items
WHERE id > $1
ORDER BY id ASC
LIMIT $2
`
rows, err := p.db.Query(query, params.Cursor, params.Limit+1)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Item
for rows.Next() {
var item Item
if err := rows.Scan(&item.ID, &item.Name, &item.CreatedAt); err != nil {
return nil, err
}
items = append(items, item)
}
hasMore := len(items) > params.Limit
if hasMore {
items = items[:params.Limit]
}
nextCursor := ""
if len(items) > 0 {
nextCursor = items[len(items)-1].ID
}
return &PageResult{
Items: items,
NextCursor: nextCursor,
HasMore: hasMore,
}, nil
}

Ключевые моменты:

  • Индекс: обязательно создайте составной индекс на поле сортировки (id или created_at), чтобы запрос выполнялся за O(log n).
  • Курсор: используйте уникальное поле (например, UUID или автоинкрементный ID). Для временных меток добавляйте вторичный ключ для разрешения коллизий.
  • Limit+1: запрашивайте на одну запись больше, чтобы определить наличие следующей страницы без дополнительного запроса.
  • Безопасность: курсор должен быть закодирован (например, base64) для передачи в URL, но в БД храните сырое значение.

Такой подход обеспечивает O(1) сложность для каждой страницы при наличии индекса, в отличие от O(n) у OFFSET.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью