mariadb INDEX 질문드립니다 0 3 1,365

by 고고야 [MySQL] Maraidb index [2022.07.20 23:17:56]


안녕하세요. 주니어 개발자입니다.

다름이 아니라 계층형 게시판 개인 프로젝트를 하다가 잘 안되는 부분이 있어 질문 드립니다.

먼저 제가 설계한 board 테이블은 아래와 같습니다.

(JPA를 이용한것이라 Entity에 의해 자동으로 만들어진 테이블입니다.)

create table board
(
    board_id    bigint auto_increment
        primary key,
    create_time datetime(6)  not null,
    update_time datetime(6)  not null,
    content     longtext     not null,
    group_no    bigint       not null,
    group_order int          not null,
    hit         int          not null,
    indent      int          not null,
    status      varchar(255) not null,
    title       varchar(255) not null,
    member_id   bigint       not null,
    constraint FKsds8ox89wwf6aihinar49rmfy
        foreign key (member_id) references member (member_id)
);

 간단한 테이블이라 따로 설명드릴건 없지만, pk는 board_id이지만 계층형으로 보여주기 위해 group_no와 group_seq라는 두개의 컬럼을 이용합니다.

결론적으로 페이징 쿼리는 단순하게 아래와 같이 만들어집니다.

    select
        board_id,
        create_time,
        update_time,
        content,
        group_no,
        group_order,
        hit,
        indent,
        member_id,
        status
    from
        board
    order by
        group_no,
        group_order
    limit 0, 20;

첫번째 페이지는 limit 0,20 그 다음은 20,40 그 다음은 40,60과 같이 offset과 limit 값으로 페이징을 처리합니다. 단, 정렬기준이 pk가 아닌 보시는것처럼 group_no과 group_order입니다.

데이터가 얼마 없을 땐 전혀 문제가 없었는데 강제로 더미데이터를 몇백만건 넣고나니 위 쿼리문의 속도가 현저하게 낮아졌습니다.(뒤쪽 페이지는 1~2초 이상 걸려서 순간 렉걸린듯한 느낌ㅠㅠ)

그래서 저는 단순히 group_no를 인덱스로 설정해주면 이 문제를 해결할 수 있을 거라고 생각했습니다. 또는 group_no와 group_seq를 복합인덱스로요. 하지만 어떤 INDEX를 생성해도 위 쿼리문은 계속 Full-scan을 하고 성능은 나아지지 않습니다.

 

제가 어떤 부분을 놓치고 있는건지, 또한 해결방법은 무엇일까요? 선배님들께 도움 요청드립니다. 감사합니다

by 고고야 [2022.07.20 23:21:46]

추가로 group_no는 글을 쓸 때 board_id와 같은값을 갖고, 답글을 쓸때는 부모글의 group_no를 그대로 가집니다.

그리고 같은 group_no를 갖는 묶음끼리 순서를 결정하기 위한 컬럼이 group_seq입니다.

그래서 group_no가 상대적으로 카디널리티가 훨씬 높고 group_seq는 낮을것같습니다.

 

그래서 group_no만 인덱스를 걸어줘도 충분히 쿼리성능이 해결되지 않을까? 라고 추측했습니다


by 고고야 [2022.07.21 00:40:42]

현재  group과 seq 두 컬럼으로 복합인덱스로 설정한 결과

limi 0,20처럼 약 offset 10000정도까지는 index를 잘 타는것 같습니다!!

그런데 그 뒤쪽으로 갈수록(offset 값이 커지면 다시 풀스캔을 하고 있습니다!)


by 마농 [2022.07.21 09:17:15]

페이징 쿼리에서 뒤로 갈수록 느려지는 것은 어느정도 감수해야 하는 부분입니다.
위 쿼리에서 개선할 수 있는 방법으로는 인덱스만을 이용한 페이징 방법이 있습니다.
다른 항목을 제외하고 오로지 인덱스만 이용하여 페이징 합니다.
페이징 결과만 가지고 한번더 테이블과 조인하는 방안
MySQL 의 인덱스는 PK 를 포함하는 것으로 압니다.
따라서 pk 를 포함하여 정렬하시면 됩니다.
 

SELECT a.board_id
     , b.create_time
     , b.update_time
     , b.content
     , a.group_no
     , a.group_order
     , b.hit
     , b.indent
     , b.member_id
     , b.status
  FROM (-- 인덱스만을 이용한 페이징
        SELECT group_no
             , group_order
             , board_id
          FROM board
         ORDER BY group_no, group_order
         LIMIT 0, 20
        ) a
 INNER JOIN board b
    ON a.board_id = b.board_id
 ORDER BY group_no, group_order
;

 

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입