Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
Tags
- RedirectService
- 오블완
- 노드간 통신
- 핀포인트
- reids
- pinpoint
- 개발 어렵당.ㅠ
- 7879
- 플루터
- 애자일 싫타
- Loki 로그
- nGinder
- formik
- jar 배포
- R2DBC Paging
- fake jwt
- jsonMarshaller
- hbase 저장공간 설정
- Ingress Controller Fake
- Armeria
- OIDC
- save/update
- pinpoint 2.5.3
- intellij
- ㅉ때
- UnsupportedOperationException
- 월급루팡 일지
- LPOS
- 티스토리챌린지
- 논블록킹 성능
Archives
- Today
- Total
대머리개발자
성능 - 조건절 OR 본문
728x90
조건절에 OR을 사용하면 성능에 부정적인 영향을 미칠수 있다.
그래서 어지간 하면 다른 방향으로 설계를 해야 한다.
성능 저하의 이뉴는
인덱스 활용 어렵고 쿼리 최적화가 어렵고 전체 테이블 스캔을 한다.
결국 다 같은 말이다. ㅋ 당근 인덱스 활용을 안 하니 최적화 어렵고 전체 테이블 스캔을 하겠쥬.
가능한 경우는 IN 연산자를 활용하고 또는 UNION ALL 연산자를 사용하라고 한다.
내가 원하는 조건절은 아래의 내용을 만족해야 한다.
1. 기준일 상관없이 멤버쉽이면 볼 수 있는 공개 게시글 있고
2. 멤버십으로 가입한 기준일로 볼 수 있는 조건이 있다.
// 1. 전체 공개 게시글 (날짜 조건 없음)
val publicPredicate = QBoard.board.visibility.eq(Visibility.PUBLIC)
// 2. 멤버쉽 전용 게시글 (날짜 조건 적용)
val memberPredicate = QBoard.board.visibility.eq(Visibility.MEMBER).and(QBoard.board.regDt.after(searchInfo.regDt))
// 두 조건을 OR로 연결
predicate = predicate.and(publicPredicate.or(memberPredicate))
일단 두개의 조건을 IN으로 할 수가 없다. 또한
UNION ALL 할 경우에는 페이징 처리가 지랄 맞게 된다. 물론 jpa 네이티브 쿼리 아니면 지원도 안 한다.
결국 "or 조건절"은 그대로 이용하는데 "조회하는 범위를 최대한 줄이는 방향으로 최적화"
즉, 조인을 다 하고 서브 쿼리 진행하고 정렬해서 20개를 뽑아내는 것이 아니고
먼저 20개를 뽑아내서 20개만 딱 조인하고 20개만 딱 서브 쿼리진행하는 방향으로 간다.
또한
필요한 모든것을 같이(동시) 진행한다.(논-블록킹)
return withContext(Dispatchers.Default) {
val list = async { runCatching{ searchSimple(searchInfo) }.onFailure { mutableListOf<BoardListDto>() } }
val count = async { try{ searchSimpleCount(searchInfo) } catch (e:Exception){0L} }
APIResultList(list.await(), count.await())
}
가즈아!!! 생각 길게 코드는 짧게!!
그래도 어지간하면 OR은 하지 않는 방향으로 짱구를 굴려보자. ㅠ
fun search(searchInfo: SearchInfo): MutableList<BoardListDto> {
val filter = searchInfo.filter ?: Filter(pageIndex = 0, pageSize = 20, sort = 1)
// innerJoin 절에 조건을 추가해 join 자체를 경량화 한다.
val query:JPAQuery<BoardListDto> = jpaQueryFactory.select(searchColumns(searchInfo)).from(qBoard)
.innerJoin(qMenu).on(qMenu.id.eq(qBoard.menuId))
// 본문이 내용이 경우
if(searchInfo.includeContent == true){
query.innerJoin(QBoardContent.boardContent).on(QBoardContent.boardContent.boardId.eq(qBoard.id))
}
// 예약 발행인 경우
if(searchInfo.status == EntityStatus.B){
query.innerJoin(qBoardBooking).on(qBoardBooking.boardId.eq(qBoard.id))
}
// 조회수, 좋아요수
query.leftJoin(qHistory).on(qHistory.targetId.eq(qBoard.id))
// 필요한 게시판Id를 가져온다. 20개! In절이 너무 커지면 그 때 고민s ㅠ
query.where(qBoard.id.`in`(coveringIndex(searchInfo)))
.groupBy(qBoard.id)
if(searchInfo.isNoticeList == true){
query.orderBy(qBoard.noticeType.desc())
}
return query.orderBy(sortBy(filter.sort)).fetch()
}
728x90
'개발이야기 > DataBase' 카테고리의 다른 글
어색한 쿼리. (0) | 2025.03.31 |
---|---|
모든 쿼리는 index를 타야 제맛이쥐 (0) | 2024.09.04 |
CROSS JOIN 언제 쓸까 했는데.. (1) | 2024.07.09 |
마이그레이션(MyBatis -> R2DBC) 언제나 즐겁네! (0) | 2024.07.08 |
group_concat 속 문자 정렬하기 (0) | 2024.05.31 |