You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// 경매 이미지
JPAExpressions
.select(auctionImage.id.min())
.from(auctionImage)
.where(auctionImage.auction.id.eq(auction.id))
.groupBy(auctionImage.auction.id)
// 마지막 메세지
JPAExpressions
.select(message.id.max())
.from(message)
.where(message.chatRoom.id.eq(chatRoom.id))
.groupBy(message.chatRoom.id)
MIN()이나 MAX()나 똑같으니 메세지만 예시로 들어보겠습니다
SELECT MAX(id)
FROM message
WHERE chat_room_id = 5
GROUP BY chat_room_id;
-- 실행 결과
+---------+
| MAX(id) |
+---------+
| 17 |
+---------+
사실 여기서는 GROUP BY가 필요하지 않습니다
왜나면 id만을 기준으로 쿼리를 실행하기 때문입니다
GROUP BY는 특정 컬럼을 기준으로 결과 집합을 그룹화하는 용도로 사용합니다
그리고 그 그룹화한 결과를 토대로 다양한 처리(주로 집계함수)를 하는 용도입니다
그룹화한 결과를 토대로 다양한 처리를 하기 위해서는, 특정 컬럼만을 가공해야 할 필요성이 있는 경우란 의미라고 볼 수 있습니다
하지만 위의 쿼리는 오로지 id만을 조회하고 있습니다
WHERE절의 조건은 다른 컬럼이지만, 결과로 조회되는 것은 오로지 id입니다
그러므로 GROUP BY를 할 필요가 없습니다
id를 기준으로 처리를 할 때, 다른 컬럼이 존재해 방해받을 여지가 없기 때문입니다
하지만 지금 쿼리는 GROUP BY가 추가되었고, 이로 인해 불필요한 쿼리 계획이 추가되었다고 볼 수 있습니다
그럼 이제 실행 계획 관점에서 확인해보겠습니다
+----+-------------+---------+------------+-------+----------------------+----------------------+---------+------+------+----------+---------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------+------------+-------+----------------------+----------------------+---------+------+------+----------+---------------------------------------+
| 1 | SIMPLE | message | NULL | range | fk_message_chat_room | fk_message_chat_room | 8 | NULL | 1 | 100.00 | Using where; Using index for group-by |
+----+-------------+---------+------------+-------+----------------------+----------------------+---------+------+------+----------+---------------------------------------+
WHERE절로 FK를 조건으로 둬서 필터링
필터링 결과를 토대로 GROUP BY
MAX() 집계 함수를 통해 최대 값 조회
요런 식이고 FK 기반으로 스캔하니 range가 되었습니다
extra도 저 기반으로 되었으니 쿼리 실행 결과가 자연스럽다고 볼 수 있겠습니다
다만 이제 위에서 언급한 내용을 보자면 여러 아쉬운 점이 있습니다
어처피 PK만 조회하는데 굳이 GROUP BY를 해서 불필요한 쿼리 실행 과정이 추가됨
인덱스 특성 상 MIN(), MAX()는 특정 조건을 필터링한 이후 디스크까지 읽지 않고 바로 처음 혹은 마지막 인덱스 값만 조회하면 되는데 그러지 않아 비효율적임
이제 GROUP BY를 제외한 쿼리를 실행하고 그 결과와 실행 계획을 살펴보겠습니다
SELECT MAX(id)
FROM message
WHERE chat_room_id = 5;
-- 실행 결과
+---------+
| MAX(id) |
+---------+
| 17 |
+---------+
Select tables optimized away라는 extra를 제외하고는 그냥 싹 다 null입니다
이에 대한 정보는 mysql 공식 문서를 보시면 확인할 수 있습니다
요약하면 쿼리를 실행하기 위해 최적화 도중 쿼리의 결과를 구하기 위해 테이블을 조회할 필요가 없었다라는 의미입니다
그래서 비용도 표기 안해줍니다
최적화의 끝판왕 급이라고 생각해주시면 될 것 같습니다
GROUP BY만 제거하면 극단적으로 쿼리의 효율을 올릴 수 있습니다
물론 제거 안해도 비용이 비싼 쿼리는 아니지만
그래도 제거를 안할 이유도 없으니까 제거해서 최적화를 해주면 좋을 것 같습니다
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
MIN()이나 MAX()나 똑같으니 메세지만 예시로 들어보겠습니다
사실 여기서는 GROUP BY가 필요하지 않습니다
왜나면 id만을 기준으로 쿼리를 실행하기 때문입니다
GROUP BY는 특정 컬럼을 기준으로 결과 집합을 그룹화하는 용도로 사용합니다
그리고 그 그룹화한 결과를 토대로 다양한 처리(주로 집계함수)를 하는 용도입니다
그룹화한 결과를 토대로 다양한 처리를 하기 위해서는, 특정 컬럼만을 가공해야 할 필요성이 있는 경우란 의미라고 볼 수 있습니다
하지만 위의 쿼리는 오로지 id만을 조회하고 있습니다
WHERE절의 조건은 다른 컬럼이지만, 결과로 조회되는 것은 오로지 id입니다
그러므로 GROUP BY를 할 필요가 없습니다
id를 기준으로 처리를 할 때, 다른 컬럼이 존재해 방해받을 여지가 없기 때문입니다
하지만 지금 쿼리는 GROUP BY가 추가되었고, 이로 인해 불필요한 쿼리 계획이 추가되었다고 볼 수 있습니다
그럼 이제 실행 계획 관점에서 확인해보겠습니다
요런 식이고 FK 기반으로 스캔하니 range가 되었습니다
extra도 저 기반으로 되었으니 쿼리 실행 결과가 자연스럽다고 볼 수 있겠습니다
다만 이제 위에서 언급한 내용을 보자면 여러 아쉬운 점이 있습니다
이제 GROUP BY를 제외한 쿼리를 실행하고 그 결과와 실행 계획을 살펴보겠습니다
실행 결과는 똑같습니다
실행 계획을 보겠습니다
Select tables optimized away라는 extra를 제외하고는 그냥 싹 다 null입니다
이에 대한 정보는 mysql 공식 문서를 보시면 확인할 수 있습니다
요약하면 쿼리를 실행하기 위해 최적화 도중 쿼리의 결과를 구하기 위해 테이블을 조회할 필요가 없었다라는 의미입니다
그래서 비용도 표기 안해줍니다
최적화의 끝판왕 급이라고 생각해주시면 될 것 같습니다
GROUP BY만 제거하면 극단적으로 쿼리의 효율을 올릴 수 있습니다
물론 제거 안해도 비용이 비싼 쿼리는 아니지만
그래도 제거를 안할 이유도 없으니까 제거해서 최적화를 해주면 좋을 것 같습니다
Beta Was this translation helpful? Give feedback.
All reactions