[MySQL] 증권 DB 최적화

한강섭·5일 전
0
post-thumbnail

주식 그래프를 그려주기 위해서 10만개의 데이터를 GET 요청을 보내야 한다.


이 데이터를 조회하기 위한 기존 쿼리로는 이렇게 활용하고 있었다.

<select id="findLast3BusinessDaysByStockId" resultType="StockPriceRaw">
    SELECT spr.price_id, spr.stock_id, spr.price, spr.recorded_at
    FROM STOCK_PRICE_RAWS spr
    JOIN (
        SELECT DATE(recorded_at) AS biz_date
        FROM STOCK_PRICE_RAWS
        WHERE stock_id = #{stockId}
        AND DAYOFWEEK(recorded_at) BETWEEN 2 AND 6
        GROUP BY DATE(recorded_at)
        ORDER BY biz_date DESC
        LIMIT 3
    ) recent ON DATE(spr.recorded_at) = recent.biz_date
    WHERE spr.stock_id = #{stockId}
    ORDER BY spr.recorded_at DESC
</select>

시행착오

처음에는 recorded_at과 stock_id에 복합인덱스를 달아서 해결하려고 하였다.


하지만 Date 함수를 사용한 쿼리는 인덱스 처리가 안되었고 아직까지도 API 응답 속도가 1초가 넘었다..

불필요한 조인 제거

Date를 Mysql이 아닌 백엔드 서비스 단에서 처리하고 복합인덱스를 100% 활용할 수 있도록 쿼리를 수정하였다.

EXPLAIN
SELECT price_id, stock_id, price, recorded_at
FROM STOCK_PRICE_RAWS
WHERE stock_id = 4
  AND (
    (recorded_at >= '2025-09-24 00:00:00' AND recorded_at < '2025-09-25 00:00:00')
        OR (recorded_at >= '2025-09-23 00:00:00' AND recorded_at < '2025-09-24 00:00:00')
        OR (recorded_at >= '2025-09-22 00:00:00' AND recorded_at < '2025-09-23 00:00:00')
    )
ORDER BY recorded_at DESC;

그렇게 복합 인덱스를 100프로 활용할 수 있게 되었고, 불필요한 join이 사라지게 되면서 API 응답속도를 200ms까지 줄일 수 있었다.

결론


10만 건의 주식 데이터를 조회하는 API의 응답 속도가 1초 이상 걸리는 성능 문제를 겪었다.

핵심 원인:

  • DATE() 함수 사용으로 인한 인덱스 미활용
  • 불필요한 서브쿼리 JOIN으로 인한 쿼리 복잡도 증가

해결 방법:

  • 날짜 계산 로직을 MySQL에서 애플리케이션 레이어로 이동
  • recorded_at >= '2025-09-24 00:00:00' AND recorded_at < '2025-09-25 00:00:00' 형태로 범위 검색
  • 불필요한 JOIN 제거하고 단순 WHERE 조건으로 변경

성능 개선 결과:

  • API 응답 속도: 1초 → 200ms (80% 개선)
  • 복합 인덱스 (stock_id, recorded_at) 100% 활용
  • 스캔 행 수 대폭 감소

이번 경험을 통해 인덱스 설계만큼이나 쿼리 작성 방식이 중요하다는 것을 배웠다. 함수를 사용하거나 복잡한 JOIN을 남발하면 인덱스가 있어도 성능을 제대로 활용할 수 없다. 데이터베이스에 모든 로직을 맡기기보다는, 애플리케이션 레이어에서 처리할 수 있는 부분은 분리하는 것이 성능 최적화의 핵심임을 알았습니다.

profile
기록하고 공유하는 개발자

0개의 댓글