인프런 커뮤니티 질문&답변

hoony19980님의 프로필 이미지
hoony19980

작성한 질문수

초보자를 위한 BigQuery(SQL) 입문

5-6. JOIN 연습 문제 3~5번

5-6 JOIN 연습 문제 4번 질문입니다.

해결된 질문

작성

·

41

0

안녕하세요 카일님, JOIN 연습문제 4번에서 작성 순서 및 효율성 관련해서 질문드리고 싶습니다.

카일님의 풀이에서는 Active, Training 의 Status 를 필터링 후 pokemon, trainer 테이블을 LEFT JOIN 하시고 마지막에 'Master' 를 필터링하셨는데,

저 같은 경우에는 각각의 테이블마다 필요한 부분을 먼저 필터링 후에 마지막에는 COUNT 만 할 수 있게 진행하였습니다.

  • Trainer 테이블에서는 'Master' 필터

  • Trainer_pokemon 테이블에서는 'Active', 'Training' 필터

결과적으로 결과값은 올바르게 나오는데 카일님께서 앞선 강의에서 필터링을 먼저 하는 것이 효율적이라 하셨던 것 같아서 질문드리게 되었습니다. 감사합니다.

SELECT
  p.type1,
  COUNT(tp.id) AS pokemon_cnt
  -- t.*,
  -- tp.pokemon_id,
  -- tp.status,
  -- p.type1
FROM(
  SELECT
    id,
    achievement_level
  FROM `basic.trainer`
  WHERE
    achievement_level = 'Master'
) AS t
LEFT JOIN(
  SELECT
    *
  FROM `basic.trainer_pokemon`
  WHERE
    status IN ('Active', 'Training')
) AS tp
ON t.id = tp.trainer_id
LEFT JOIN `basic.pokemon` AS p
ON tp.pokemon_id = p.id
WHERE
  tp.pokemon_id IS NOT NULL
GROUP BY
  p.type1
ORDER BY
  2 DESC
LIMIT 1;

답변 2

0

카일스쿨님의 프로필 이미지
카일스쿨
지식공유자

안녕하세요! 말씀하신 방법대로 해도 가능합니다. 다만 저는 JOIN시 LEFT에 더 많은 Row가 있는 데이터를 추가합니다. 아래 링크의 쿼리 최적화 가이드에도 나오는 방식이에요.

 

 

https://cloud.google.com/bigquery/docs/best-practices-performance-compute?hl=ko#optimize_your_join_patterns

제가 achievement_level = 'Master' 을 쿼리 마지막에 했던 것은 이 데이터를 많이 활용할 수 있다고 생각해서 그렇게 했어요. hoony19980님이 하신 방법도 결과론적으론 푸는 방법이 맞고, 저는 조금 더 유연하게 해서 데이터를 탐색하기 위해 했다고 보시면 될 것 같아요. 저는 약간의 속도보단 유연하게 데이터를 보기 위해 쿼리를 작성해주셔요

 

저희 데이터셋에선 쿼리 속도 차이가 미미한데, 데이터가 많다면 차이가 존재할거에요.

아래 글도 보시면 도움이 될거에요

https://www.inflearn.com/community/questions/1363007/join-4%EB%B2%88-%EB%AC%B8%EC%A0%9C

 

 

hoony19980님의 프로필 이미지
hoony19980
질문자

아하 그렇군요 ! 그렇다면 단순히 문제에 나온 결과를 출력하기 위해서 쿼리를 작성한다면 속도 면에서 작성하고, 실제로 현업에서 무언가 인사이트를 도출하기 위해 데이터를 살펴보기 위해 사용한다고 생각한다면 큰 테이블부터 세우고 LEFT JOIN 하는 카일님의 유연성을 고려한 방법을 사용하는 것이 좋다고 이해하면 될까요 ?

카일스쿨님의 프로필 이미지
카일스쿨
지식공유자

쿼리 작성할 때 무조건 좋다라는 관점은 없는 것 같고, 상황에 따라 그 때 필요한 목적에 맞게 하면 되는 것 같아요. 속도가 중요한지, 유연성이 중요한지 등

 

큰 테이블부터 LEFT에 둔 것은 퍼포먼스 개선 관점에서 추가한거에요.
공유드린 링크에 이렇게 나와있어요.
When you have a large table as the left side of the JOIN and a small one on the right side of the JOIN, a broadcast join is created. A broadcast join sends all the data in the smaller table to each slot that processes the larger table. It is advisable to perform the broadcast join first.

유연하게 하려고 했던 것은 achievement_level = 'Master' 이걸 제일 바깥쪽에 빼둔건데, 어떤 분은 이렇게 하는 것이 유연하지 않다고 볼 수 있을 거에요. 그래서 상황에 따라 다르다 정도로 인지하시면 될 것 같네요. 목적에 따라 적절히 짜는게 중요하고 이 부분에 대해 절대 법칙은 없다 정도로 정리드릴게요

hoony19980님의 프로필 이미지
hoony19980
질문자

아하 이해됐습니다 감사합니다 🙂 !

0

안녕하세요, 인프런 AI 인턴입니다.

hoony19980님께서 질문하신 JOIN 연습문제 4번에 대한 내용, 그리고 SQL 쿼리 최적화에 관한 부분에 대해 답변 드리겠습니다.

쿼리 최적화 관점에서 필터링

SQL 쿼리에서 데이터를 필터링하는 것은 효율적으로 쿼리를 수행하기 위해 매우 중요합니다. 특히, 데이터를 조인하기 전에 필터링을 수행하면, 서버는 더 적은 데이터만을 처리하게 되므로 전체적인 성능이 향상될 수 있습니다. 이러한 이유로 카일님이 강의에서 필터링을 강조하셨던 것입니다.

질문하신 쿼리 해법

hoony19980님의 쿼리는 기본적으로 각 테이블에서 필요한 데이터를 사전에 필터링하고 조인하는 방식입니다. 이는 데이터의 크기를 줄임으로써 조인 연산의 부담을 줄이는 방법론입니다.

  • Trainer 테이블에서 ‘Master’ 조건을 먼저 필터링하는 것은 매 쿼리 수행 시 마스터 레벨의 트레이너만 남기게 되어 효율적입니다.
  • Trainer_pokemon 테이블에서 ‘Active’, ‘Training’ 조건을 먼저 필터링하는 방법도 유사한 논리로 작용합니다.

최적화된 방식

카일님의 쿼리 접근과 hoony19980님의 접근은 데이터의 크기와 구조에 따라 효율이 달라질 수 있습니다. 하지만 가급적이면 데이터를 조인하기 전에 가능한 필터링을 하여 데이터의 양을 줄이는 방법이 일반적인 SQL 쿼리 최적화 전략입니다. 이를 통해 조인 연산의 부하를 줄일 수 있습니다.

마무리

결론적으로, hoony19980님이 사용하신 방식도 SQL 최적화 원칙에 잘 맞는 접근법입니다. 쿼리가 올바르게 동작하며 효율적으로 작동하면 괜찮은 방법이라고 볼 수 있습니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 관련된 내용에 대해 보다 깊이 이해하시려면, join 3번, 4번 문제 내용을 참조하시길 권장합니다.

현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

hoony19980님의 프로필 이미지
hoony19980

작성한 질문수

질문하기