Skip to content

쿼리 성능 개선 ‐ 템플릿 단건 조회

김경미 edited this page Sep 26, 2024 · 4 revisions

데이터 스펙

멤버: 10 건
카테고리: 100 건 (멤버 당 10 건)
태그: 2000 건 (멤버 당 200 건)
템플릿: 10만 건 (멤버 당 1만 건)
소스 코드: 10만 ~ 50만 건 (템플릿 당 1~5 개 랜덤 생성)

컴퓨터 스펙

윈도우 11
프로세서 AMD Ryzen 9 4900HS with Radeon Graphics 3.00 GH
설치된 RAM 16.0GB
시스템 종류 64비트 운영 체제, x64 기반 프로세서

테스트 조건

10개의 스레드로 100번씩 실행
총 1000번의 요청 실행
최대 테스트 대기 시간은 60초



개선 전

속도 측정

Total request count: 1000
Total elapsed time: 51851ms
Average elapsed time: 51ms

쿼리 분석

총 [5 + 태그 개수] 개 쿼리 실행

1. Template 조회 (ID별)

  • Repository: TemplateJpaRepository
  • Method: fetchById
    select
        t1_0.id,
        t1_0.category_id,
        t1_0.created_at,
        t1_0.description,
        (select
            count(*) 
        from
            likes 
        where
            likes.template_id = t1_0.id),
        t1_0.member_id,
        t1_0.modified_at,
        t1_0.title 
    from
        template t1_0 
    where
        t1_0.id=?
  • 호출 횟수: 1회

2. Template의 Tag 목록 조회 (Template ID별)

  • Repository: TemplateTagJpaRepository
  • Method: findAllByTemplate
    select
        tt1_0.tag_id,
        tt1_0.template_id,
        tt1_0.created_at,
        tt1_0.modified_at 
    from
        template_tag tt1_0 
    where
        tt1_0.template_id=?
  • 호출 횟수: 1회

3. Tag 조회 (ID별)

  • (TemplateTagJpaRepository.findAllByTemplate에서 파생된 sql 명령)
    select
        t1_0.id,
        t1_0.created_at,
        t1_0.modified_at,
        t1_0.name 
    from
        tag t1_0 
    where
        t1_0.id=?
  • 호출 횟수: 3회 (태그 개수 만큼)

4. Template에 속한 SourceCode 목록 조회 (Template ID별)

  • Repository: SourceCodeJpaRepository
  • Method: findAllByTemplate
    select
        sc1_0.id,
        sc1_0.content,
        sc1_0.created_at,
        sc1_0.filename,
        sc1_0.modified_at,
        sc1_0.ordinal,
        sc1_0.template_id 
    from
        source_code sc1_0 
    where
        sc1_0.template_id=?
  • 호출 횟수: 1회

5. 멤버 조회 (Template ID별)

  • Repository: MemberJpaRepository
  • Method: fetchByTemplateId
    select
        m1_0.id,
        m1_0.created_at,
        m1_0.modified_at,
        m1_0.name,
        m1_0.password,
        m1_0.salt 
    from
        member m1_0 
    where
        m1_0.id=?
  • 호출 횟수: 1회

6. FindTemplateResponse 생성

    select
        c1_0.id,
        c1_0.created_at,
        c1_0.is_default,
        c1_0.member_id,
        m1_0.id,
        m1_0.created_at,
        m1_0.modified_at,
        m1_0.name,
        m1_0.password,
        m1_0.salt,
        c1_0.modified_at,
        c1_0.name 
    from
        category c1_0 
    join
        member m1_0 
            on m1_0.id=c1_0.member_id 
    where
        c1_0.id=?
  • 호출 횟수: 1회

개선을 위해 필요한 작업

인덱스 개선 사항

  • 현재 조회하는 5가지 명령문 모두 primary key, Foreign key 자동으로 인덱스가 생성된다.

Category 테이블

  • 인덱스 제안:
    • member_id
      • 이유: join에서 category_id로 조인하기 때문에 인덱스가 필요. Template 기본 정보 조회 시 category.member_id와 member.id를 비교.
      • 추가 여부: O, CREATE INDEX idx_member_id ON category(member_id);

### 쿼리 최적화

TemplateTag 조회 로직 변경

Template의 Tag 목록 조회 / Tag 정보 조회 (ID별) 을 하나의 query로 변경

@Query("""
	SELECT t  
	FROM Tag t  
	JOIN TemplateTag tt ON t.id = tt.id.templateId  
	WHERE tt.template = :template
""")  
List<Tag> findAllByTemplate(Template template);
Template의 Tag 목록 조회
  • Repository: TemplateTagJpaRepository
  • Method: findAllByTemplate
select
    t1_0.id,
    t1_0.created_at,
    t1_0.modified_at,
    t1_0.name 
from
    tag t1_0 
join
    template_tag tt1_0 
        on t1_0.id=tt1_0.template_id 
where
    tt1_0.template_id=?
  • 호출 횟수: 1회

개선 후

속도 측정

Total request count: 1000
Total elapsed time: 40136ms
Average elapsed time: 40ms

쿼리 분석

총 5 번 쿼리 실행

1. Template 조회 (ID별)

  • Repository: TemplateJpaRepository
  • Method: fetchById
    select
        t1_0.id,
        t1_0.category_id,
        t1_0.created_at,
        t1_0.description,
        (select
            count(*) 
        from
            likes 
        where
            likes.template_id = t1_0.id),
        t1_0.member_id,
        t1_0.modified_at,
        t1_0.title 
    from
        template t1_0 
    where
        t1_0.id=?
  • 호출 횟수: 1회

2. Template의 Tag 목록 조회 (Template ID별)

  • Repository: TemplateTagJpaRepository
  • Method: findAllTagsByTemplate
태그 템플릿 목록 조회
    select
        t1_0.id,
        t1_0.created_at,
        t1_0.modified_at,
        t1_0.name 
    from
        tag t1_0 
    join
        template_tag tt1_0 
            on t1_0.id=tt1_0.tag_id 
    where
        tt1_0.template_id=?
  • 호출 횟수: 1회

3. Template에 속한 SourceCode 목록 조회 (Template ID별)

  • Repository: SourceCodeJpaRepository
  • Method: findAllByTemplate
    select
        sc1_0.id,
        sc1_0.content,
        sc1_0.created_at,
        sc1_0.filename,
        sc1_0.modified_at,
        sc1_0.ordinal,
        sc1_0.template_id 
    from
        source_code sc1_0 
    where
        sc1_0.template_id=?
  • 호출 횟수: 1회

4. FindTemplateResponse 제작

MemberResponse 제작
    select
        m1_0.id,
        m1_0.created_at,
        m1_0.modified_at,
        m1_0.name,
        m1_0.password,
        m1_0.salt 
    from
        member m1_0 
    where
        m1_0.id=?
  • 호출 횟수: 1회
FindTemplateResponse 제작
    select
        c1_0.id,
        c1_0.created_at,
        c1_0.is_default,
        c1_0.member_id,
        m1_0.id,
        m1_0.created_at,
        m1_0.modified_at,
        m1_0.name,
        m1_0.password,
        m1_0.salt,
        c1_0.modified_at,
        c1_0.name 
    from
        category c1_0 
    join
        member m1_0 
            on m1_0.id=c1_0.member_id 
    where
        c1_0.id=?
  • 호출 횟수: 1회


성능 개선 결과

개선 전

Total request count: 1000
Total elapsed time: 51851ms
Average elapsed time: 51ms

개선 후

Total request count: 1000
Total elapsed time: 40136ms
Average elapsed time: 40ms

⚡️ 코드zap

프로젝트

규칙 및 정책

공통

백엔드

프론트엔드

매뉴얼

백엔드

기술 문서

백엔드

프론트엔드

회의록


Clone this wiki locally