티스토리 뷰
사용자의 구독 이력UserSubscribeHistory 을 확인하는 find 함수
기존 JPA Query
다음 코드는 사용자가 해당 채널을 구독하는지 조회하는 JPA Query이다.
- 사용자의 구독 이력 UserSubscribeHistory 에서
- 구독하는 채널명 channelName 인지 확인하고
- UserSubscribeStatus 구독 상태 여부에 따라 UserSubscribeHistory를 반환한다.
fun find(channelName: String, status: UserSubscribeStatus? = null): UserSubscribeHistory? {
return queryFactory.select(userSubscribeHistory)
.from(userSubscribeHistory)
.where(
userSubscribeHistory.channelName.eq(channelName),
status?.let { userSubscribeHistory.status.eq(status) }
)
.limit(1)
.fetchOne()
}
ChatGPT가 변경해준 JPA Query
fun findModifiedByGPT(channelName: String, status: UserSubscribeStatus? = null): UserSubscribeHistory? =
queryFactory.selectFrom(userSubscribeHistory)
.where(
userSubscribeHistory.channelName.eq(channelName),
status?.let { userSubscribeHistory.status.eq(it) }
)
.orderBy(userSubscribeHistory.id.desc())
.fetchFirst()
변경된 사항
selectFrom
select + from 절 -> selectFrom
단일 표현식 함수 (Single-expression functions)
fun 함수명():반환타입 {
return
}
fun 함수명():반환타입 = 결과
Kotlin은 함수가 하나의 표현식(Expression)만으로 구성되어 있다면,
return 결과를 중괄호 {} 대신 = 을 사용하여 함수 결과를 직접 반환할 수 있다.
이 경우, 함수의 마지막 표현식이 자동으로 반환된다.
limit -> orderBy 와 fetchFirst 로 대체
.orderBy(userSubscribeHistory.id.desc())
.fetchFirst()
- orderBy(userSubscribeHistory.id.desc()) : id 열을 기준으로 내림차순으로 결과를 정렬
- fetchFirst() : 첫 번째 결과를 반환
userSubscribeHistory.id가 고유한 식별자이고, 가장 최근 항목(즉, 가장 높은 ID를 가진 항목)이 반환되어야 한다고 가정한 결과이다.
다른 기준을 사용한다면 orderBy 로 정렬 기준을 수정한다.
limit(1) 보다 orderBy + fetchFirst 를 사용하는게 효율적인 이유
1. limit(1)은 대량의 데이터가 있는 경우 쿼리 실행 속도를 늦출 수 있다.
MySQL의 limit 은 항상 쿼리의 마지막에 실행된다.
데이터 전체를 조회해서 메모리에 저장한 후에, limit 으로 실제 사용할 데이터만 추출하고
나머지 데이터는 버리는 방식으로 동작하기 때문에 대용량 데이터를 처리할 경우 실행 속도가 느릴 수 있다.
limit 절은 쿼리 결과에서 지정된 순서에 위치한 레코드만 가져오고자 할 때 사용한다.
select * from employees
where emp_no between 10001 and 10010
order by first_name
limit 0, 5;
위의 쿼리는 다음과 같은 순서로 실행된다.
- employees 에서 where 절의 검색 조건에 일치하는 레코드를 전부 읽어 온다.
- 1번에서 읽어온 레코드를 first_name 칼럼값에 따라 정렬한다.
- 상위 5건이 정렬이 완료되면 즉시 쿼리를 멈춘다.
- 정렬된 결과의 상위 5건만 사용자에게 반환한다.
2. orderBy, fetchFirst는 인덱스를 사용하여 정렬한다.
3. orderBy, fetchFirst는 다양한 데이터베이스에서 지원되기 때문에 데이터베이스 간 이식성을 향상시킬 수 있다.
결과 테스트
간결하고 함수형으로 변환되기는 했는데, 뭐가 더 실무에서 많이 쓰고 좋은(?) 코드인지는 아직 아리송하다..
그런데 일단 쿼리문이 더 효율성 있는 걸로 바뀌었으니까, 두개 성능 차이가 있을 거 같아 테스트 코드를 돌려보았다.
이렇게나 성능이 차이난다고..?
나가는 하이버네이트 쿼리문은 이렇게 바뀌었다.
Hibernate:
select
userloanhi0_.id as id1_2_,
userloanhi0_.book_name as book_nam2_2_,
userloanhi0_.status as status3_2_,
userloanhi0_.user_id as user_id4_2_
from
user_loan_history userloanhi0_
where
userloanhi0_.book_name=?
and userloanhi0_.status=? limit ?
Hibernate:
select
userloanhi0_.id as id1_2_,
userloanhi0_.book_name as book_nam2_2_,
userloanhi0_.status as status3_2_,
userloanhi0_.user_id as user_id4_2_
from
user_loan_history userloanhi0_
where
userloanhi0_.book_name=?
and userloanhi0_.status=?
order by
userloanhi0_.id desc limit ?
아니 뭐야 둘다 limit 는 있잖아..?
뭐지 분명 성능이 좋아지긴 했는데 둘다 limit 가 있어서 더 헷갈려.. 인덱스를 타게 되는건가?
이 부분은 좀 더 찾아봐야겠다.
'etc > etc' 카테고리의 다른 글
구글클라우드잼 쿠버네티스 입문반 후기 (5) | 2023.05.31 |
---|---|
ChatGPT 랑 놀기 : 에러 고쳐줘. 삼행시 지어줘. (0) | 2023.02.13 |
- Total
- Today
- Yesterday
- FetchJoin
- addFilterBefore
- 티스토리챌린지
- redisson 분산락
- checkout
- 추상클래스
- spring boot 3
- MultipleBagFetchException
- Linux
- Java
- n+1
- Git
- Kotlin
- QueryDSL
- 배열
- JPA
- dto 클래스 생성자
- array
- junit5
- Cannot construct instance of
- 스프링오류
- Spring Security
- bucket4j
- ChatGPT
- 오블완
- jvm warm-up 전략
- 자바 어플리케이션 실행 과정
- 스프링 스케줄링
- MongoDB
- port
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |