ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [MariaDB] 인덱스로 성능 향상 체감하기
    스터디 & 프로젝트/Init Cloud 팀 프로젝트 2023. 3. 3. 22:40

    이유

    프로젝트로 백엔드 API를 만들고 있었다.

    이미 기능은 모두 완성되었고 리팩토링이나 버그 수정 등등 만이 남았다.

    예전부터 DB 성능 개선을 한번 해보고싶어서 해볼까 했다.

     

    그래서 가장 많이 들어왔던 적절한 Index 적용을 통한 조회 성능 개선을 하고싶었다.

    근데 문제는 DB 자체의 레코드가 많지 않다는 것이었다.

     

    진행하는 프로젝트 특성 상 일반적인 웹 서비스처럼 Insert, Update 쿼리가 많이 발생하지는 않고 DB에 저장된 기본 데이터를 조회하는 로직이 많았다.

     

    그래도 뭐 일단 진행해보기로 했다.

    인덱스는 PK가 아닌 UNIQUE VARCHAR 필드에 지정했다.

     


    최초 시도

    정말 규모가 작은 DB이다보니 솔직히 성능 향상을 체감하기는 어려울 것이라 생각했다.

    그도 그럴 것이 히스토리를 관리하는 테이블을 제외하고 기존의 DB화 되어있는 데이터셋을 조회하는 기능이 있고 여기서 접근하는 테이블의 레코드가 400개 정도 됐다.

     

    400개의 레코드, 15개 남짓의 필드

    솔직히 이걸로 어떻게 테스트를 할까 싶었는데 그래도 테이블 크기에 따라 성능 체감이 어느 정도 규모로 달라지는지는 알아보고 싶었다.

    # 단위 ms
    
    # 리스트 조회
    ## 인덱스 적용 전
    avg list before 41.43103448275862
    mid list before 24
    
    max list before 207
    min list before 13
    
    
    ## 인덱스 적용 후
    avg list after 48.857142857142854
    mid list after 33
    
    max list after 183
    min list after 23
    
    
    # ------------------------- #
    
    # 상세 조회
    ## 인덱스 적용 전
    avg details before 20.675675675675677
    mid details before 14
    
    max details before 109
    min details before 7
    
    
    ## 인덱스 적용 후
    avg details after 16.70967741935484
    mid details after 11
    
    max details after 81
    min details after 6

     

    조회 쿼리를 날리는 API에 무작위로 "손수" 요청을 날려보았다. 요청 횟수는 40~50 정도.

    DB 자체에서 동일 쿼리에 대해서는 캐싱을 적용해서인지 최초 요청 이후는 평이한 응답속도를 보였다.

     

    리스트 조회

    리스트 조회 API의 경우 큰 차이를 보이지 않았고 오히려 응답 속도가 늘어났다.

     

    현재 레코드 자체가 많지 않아서 전체 레코드를 한번에 반환하는데 기존에 bigint로 지정된 PK를 기본 인덱스로 사용하다가 varchar로 인덱스가 변경되어서 그런가 싶다.

     

    평균, 중간 값 모두 증가했다.

    상세 조회

    상세 조회의 경우 평균, 중간 값 모두 개선된 것을 확인했다.

    물론 너무 미미해서 그 체감이 될까 싶었다.

     


    이게 맞나?

    근데 이렇게 테스트를 하고 보니 든 생각은 동일한 환경, 횟수도 아니었고 이 결과가 믿을 만한 결과인가? 였다.

    내가 테스트하다가 실수 했을 수도 있고...

    select count(*) from table;
    +----------+
    | count(*) |
    +----------+
    |   100105 |
    +----------+

     

    그래서 데이터셋을 늘리고 요청 횟수를 통일하고 요청하는 값만 무작위로 변경했다.

     

    기존의 400 여개의 레코드를 가진 테이블을 100000(십만) 개의 레코드로 늘리고 진행했다.

    추가한 레코드는 인덱스를 적용할 문자열 유니크 필드에 대해 Prefix + 번호 형태로 이어붙였다.

     


    재시도

    CREATE INDEX `index_table_index_target_field` ON table(target_field);
    
    EXPLAIN SELECT * FROM table WHERE target_field="PREFIX_1234";
    ...

    우선 인덱스를 제대로 끌고가는지를 확인했다.

     

    인덱스를 생성하고 SELECT 쿼리가 발생했을때의 결과를 보자 제대로 원하는 키의 인덱스를 사용하는 것을 볼 수 있었다.

     

    이제 10만개의 레코드 중 무작위 번호의 레코드를 조회해보기로 했다.

    일단 테스트 환경은 무작위 API 가내수공업에서 파이썬에서 각각 100회 무작위 요청하기로 바꿨다.

     

    와우...

    # 단위 ms
    # 상세 조회
    
    ## 인덱스 적용 전
    sum 44996.650339
    
    avg 449.96650339
    mid 450.5180000000002
    
    max 495.70987499999995
    min 441.889917000001
    
    ## 인덱스 적용 후 (1)
    sum 211.93329900000023
    
    avg 2.1193329900000024
    mid 1.7908749999999696
    
    max 25.101833000000003
    min 1.4242090000000096
    
    ## 인덱스 적용 후 (2)
    sum 204.00537100000022
    
    avg 2.0400537100000022
    mid 1.8525000000000347
    
    max 18.977166000000018
    min 1.480750000000003

     

    뭔가 잘못했나 싶어서 코드도 살펴봤는데 진짜 큰 차이가 있었다.

     

    상세 조회의 경우 450ms 정도의 평균, 중간 값이 1~2ms 정도로 급격하게 줄어든 것을 확인했다.

    인덱스 하나만 걸었을 뿐인데...

     

    그러면 리스트 조회는?

    # 단위 ms
    # 리스트 전체 조회
    
    ## 인덱스 적용 전
    sum 26853.388043999996
    
    avg 2685.3388043999994
    mid 2631.7681670000006
    
    max 3091.1683749999997
    min 2606.6020839999987
    
    
    ## 인덱스 적용 후
    sum 26276.581457999997
    
    avg 2627.6581457999996
    mid 2629.819749999999
    
    max 2716.6168749999997
    min 2570.738000000002

     

    리스트 조회의 경우 큰 변동이 없었다.

     

    나는 오히려 인덱스 적용 후가 더 많은 응답 시간을 보일 것이라 생각했는데 그건 아니었다.

    어차피 전체 레코드를 다 끌고오는 것이라 큰 상관이 없었을 수도 있다.

     


    결론

    결국 테이블 중 일부 레코드를 조회함에 있어서 인덱스를 적용하는 것이 성능 개선을 가져온다는 것을 확인할 수 있었다.

    물론 무지성으로 그냥 막 적용하는 것은 오히려 마이너스다.

     

    데이터가 많을 때 조회 쿼리에서 이렇게 큰 차이를 보일 줄은 몰랐다.

     

    내일 시험인데 하루 전에 이게 그렇게 하고싶었다.

     

    다음엔 삽입, 수정, 삭제에 대해서 테스트해보겠다.

    댓글

Designed by Tistory.