안녕하세요. 주니어 개발자입니다.
다름이 아니라 계층형 게시판 개인 프로젝트를 하다가 잘 안되는 부분이 있어 질문 드립니다.
먼저 제가 설계한 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을 하고 성능은 나아지지 않습니다.
제가 어떤 부분을 놓치고 있는건지, 또한 해결방법은 무엇일까요? 선배님들께 도움 요청드립니다. 감사합니다
페이징 쿼리에서 뒤로 갈수록 느려지는 것은 어느정도 감수해야 하는 부분입니다.
위 쿼리에서 개선할 수 있는 방법으로는 인덱스만을 이용한 페이징 방법이 있습니다.
다른 항목을 제외하고 오로지 인덱스만 이용하여 페이징 합니다.
페이징 결과만 가지고 한번더 테이블과 조인하는 방안
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 ;