-
typeorm에서 페이징 처리시 distinct 실행 문제NodeJS 2022. 11. 16. 15:10728x90
typeorm에서 페이징 처리시, distinct 가 실행되는 문제 처리 방법
다음과 같이 typeorm을 사용하여 페이징 처리를 하였습니다.
export class CmtCommentDService { async getCommentList(searchCommentDto: SearchCommentDto) { const dataList = await this.cmtReplyDRoRepository.find({ order: { id: 'DESC' }, skip: searchCommentDto.page * searchCommentDto.limit, take: searchCommentDto.limit, }); return dataList; } }
실형 결과를 보면, 아래와 같이 2회 SQL을 질의합니다.
-- distinct 로 id 조회 처리 select distinct `distinctAlias`.`CmtReplyD_id` as ids_CmtReplyD_id from ( select `CmtReplyD`.`mod_dtm` as `CmtReplyD_mod_dtm`, `CmtReplyD`.`mod_sytm_nm` as `CmtReplyD_mod_sytm_nm`, `CmtReplyD`.`reg_dtm` as `CmtReplyD_reg_dtm`, `CmtReplyD`.`reg_sytm_nm` as `CmtReplyD_reg_sytm_nm`, `CmtReplyD`.`use_yn` as `CmtReplyD_use_yn`, `CmtReplyD`.`id` as `CmtReplyD_id`, `CmtReplyD`.`cmt_comment_d_id` as `CmtReplyD_cmt_comment_d_id`, `CmtReplyD`.`cmt_txt` as `CmtReplyD_cmt_txt`, `CmtReplyD`.`like_cnt` as `CmtReplyD_like_cnt`, `CmtReplyD`.`pet_user_d_id` as `CmtReplyD_pet_user_d_id`, `CmtReplyD`.`pet_ccd` as `CmtReplyD_pet_ccd` from `cmt_reply_d` `CmtReplyD` where `CmtReplyD`.`id` = 10) `distinctAlias` order by `CmtReplyD_id` asc limit 1 -- 실제 데이터조회 처리 select `CmtReplyD`.`mod_dtm` as `CmtReplyD_mod_dtm`, `CmtReplyD`.`mod_sytm_nm` as `CmtReplyD_mod_sytm_nm`, `CmtReplyD`.`reg_dtm` as `CmtReplyD_reg_dtm`, `CmtReplyD`.`reg_sytm_nm` as `CmtReplyD_reg_sytm_nm`, `CmtReplyD`.`use_yn` as `CmtReplyD_use_yn`, `CmtReplyD`.`id` as `CmtReplyD_id`, `CmtReplyD`.`cmt_comment_d_id` as `CmtReplyD_cmt_comment_d_id`, `CmtReplyD`.`cmt_txt` as `CmtReplyD_cmt_txt`, `CmtReplyD`.`like_cnt` as `CmtReplyD_like_cnt`, `CmtReplyD`.`pet_user_d_id` as `CmtReplyD_pet_user_d_id`, `CmtReplyD`.`pet_ccd` as `CmtReplyD_pet_ccd` from `cmt_reply_d` `CmtReplyD` where ( `CmtReplyD`.`id` = 10 ) and ( `CmtReplyD`.`id` in (1,2,3,4,5,6,7,8,9,10) )
관련 이슈를 찾아 보니, Typeorm add select distinct in my query. I dont want select distinct. Help!를 확인 할 수 있었습니다.
TypeORM prefers joins, which makes for better performance when pagination is not used.
번역하면, TypeORM은 조인을 선호하므로 페이지 매김을 사용하지 않을 때 성능이 향상됩니다. 으로, 페이징 처리시에 releation(조인) 처리를 위해서 사용되는 것으로 판된 됩니다.
먼저 id 목록을 distinct를 이용하여 중복 없는 id를 조회 하고, 다시 in id값을 조회 처리 하여 실제 페이징 이상의 row를 가져와서 객체를 생성합니다.
하지만, 함께 일하시는 DBA 분의 의견은 distinct 처리로 인해서 되려 성능이 좋지 않다라는 의견을 주셨습니다. Typeorm add select distinct in my query. I dont want select distinct. Help!이 이슈에서도 비슷한 내용이 많이 있습니다.
typeorm에서 페이징 처리시 distinct을 회피를 아래와 같이 하였습니다.
export class CmtCommentDService { async getCommentList(searchCommentDto: SearchCommentDto) { const ids = await this.cmtReplyDRoRepository.createQueryBuilder('cmt') .distinct(true).distinctOn(['cmt.id']) .select(['cmt.id']) .orderBy('cmt.id', 'desc') .limit(options.limit).offset(options.page * options.limit) .getMany(); const dataList = await this.cmtReplyDRoRepository.find({ order: { id: 'DESC' }, where: (qb) => { qb.where(``, { ids: ids.map(i => i.id)}) }, }); return dataList; } }
typeorm에서 제공하는 take, skip를 사용하지 않고 MYSQL(DBMS)에서 제공하는 limit, offset을 사용하여 페이지이 처리를 하면, distinct 호출을 회피가 가능합니다.
또한 relation이 있을 경우 createQueryBuilder을 이용해서 id를 먼저 조회하는 SQL을 최적화하여 실행하는 방식을 추천 드립니다.
참고자료
728x90'NodeJS' 카테고리의 다른 글
nestjs에서 config모듈을 이용한 설정 관리 (0) 2022.12.09 nestjs swagger에서 enum validate 처리 하기 (0) 2022.11.17 bcrypt를 bcryptjs로 전환 (0) 2022.11.15 nestjs에서 jest TIP 정리 (0) 2022.11.07 공통 테이블을 상수로 전환 처리 (0) 2022.10.31