본문으로 건너뛰기

[hermes-agent] SQL GROUP BY를 활용한 세션 통계 쿼리 최적화: 575ms에서 1ms 미만으로

PR 링크: NousResearch/hermes-agent#73362 상태: Merged | 변경: +117 / -3

들어가며

최근 hermes-agent 프로젝트에서 /api/sessions/stats 엔드포인트의 성능 병목 현상이 발견되었습니다. 기존 구현은 통계 데이터를 계산하기 위해 최대 10,000개의 세션 행을 메모리로 가져온 뒤, Python 루프를 통해 직접 집계(Aggregation)를 수행하고 있었습니다. 이는 데이터베이스 크기가 커질수록 메모리 사용량과 응답 시간이 기하급수적으로 증가하는 구조적 문제를 안고 있었습니다. 본 글에서는 이 문제를 SQL의 GROUP BY를 활용해 어떻게 해결했는지 살펴봅니다.

코드 분석

1. hermes_cli/web_server.py: 불필요한 데이터 로딩 제거

기존 코드는 list_sessions_rich를 호출하여 모든 행을 객체화한 뒤 순회했습니다. 이를 데이터베이스 엔진에서 직접 계산하도록 변경했습니다.

Before:

for s in db.list_sessions_rich(limit=10000, include_archived=True, compact_rows=True):
    src = str(s.get("source") or "cli")
    by_source[src] = by_source.get(src, 0) + 1

After:

by_source = db.session_count_by_source(
    include_archived=True,
    exclude_children=True,
)

2. hermes_state.py: SQL 수준의 집계 구현

데이터베이스 계층에 session_count_by_source 메서드를 추가하여, 데이터베이스가 최적화된 인덱스를 활용해 집계 결과를 반환하도록 했습니다.

핵심 변경 코드:

rows = self._conn.execute(
    "SELECT COALESCE(NULLIF(s.source, ''), 'cli') AS source, COUNT(*) AS count "
    f"FROM sessions s{where_sql} "
    "GROUP BY COALESCE(NULLIF(s.source, ''), 'cli') "
    "ORDER BY count DESC",
    params,
).fetchall()

여기서 COALESCE(NULLIF(s.source, ''), 'cli')를 사용한 점이 중요합니다. 이는 빈 문자열이나 NULL 값을 'cli'라는 기본값으로 통일하여, 데이터 무결성을 유지하면서 정확한 그룹화가 가능하게 합니다.

왜 이게 좋은가

  1. 성능 향상: 10,000개의 행을 애플리케이션 메모리로 전송하고 파싱하는 비용이 사라졌습니다. 결과적으로 응답 시간이 575ms에서 1ms 미만으로 단축되었습니다.
  2. 메모리 효율성: 대규모 데이터셋에서도 서버의 메모리 사용량이 일정하게 유지됩니다.
  3. 데이터 일관성: 리뷰 과정에서 지적된 exclude_children 옵션을 추가하여, 실제 UI에 표시되는 세션 목록과 통계 수치가 일치하도록 정합성을 맞췄습니다.

교훈: 데이터베이스가 처리할 수 있는 작업(집계, 정렬, 필터링)을 애플리케이션 레이어로 가져오지 마세요. 데이터베이스 엔진은 이러한 작업을 위해 고도로 최적화되어 있습니다.

리뷰 피드백 반영

  • 예외 처리: try/except 블록을 제거하여 DB 에러 발생 시 500 에러를 내는 대신, 빈 딕셔너리를 반환하도록 하여 안정성을 높였습니다.
  • 데이터 무결성: GROUP BY 절에서 COALESCE를 사용하여 데이터 누락을 방지했습니다.
  • 비즈니스 로직 동기화: exclude_children 옵션을 추가하여 기존 list_sessions_rich와 동일한 필터링 로직을 적용했습니다.

참고 자료

⚠️ 알림: 이 분석은 AI가 실제 코드 diff를 기반으로 작성했습니다.

댓글

관련 포스트

PR Analysis 의 다른글