MySQL GROUP BY 설명: 구문, 예제 및 성능 최적화

1. 소개: GROUP BY 개요

데이터베이스에서 대규모 데이터셋을 처리할 때, 데이터를 효율적으로 집계하고 정리하는 강력한 도구는 GROUP BY 절입니다. GROUP BY는 특정 열을 기반으로 데이터를 그룹화하며, 각 그룹에 대한 집계를 수행할 때 사용됩니다. 예를 들어, 각 제품 카테고리별 총 판매액을 계산하려면 이 절을 사용하면 원하는 데이터를 쉽게 검색할 수 있습니다.

GROUP BY 절을 사용하면 데이터를 읽기 쉬운 형식으로 정리할 수 있으며, 더 깊은 분석을 위해 집계 함수(SUM, COUNT, AVG 등)를 적용할 수 있습니다.

2. GROUP BY의 기본 사용법

GROUP BY 절은 지정된 열로 데이터를 그룹화하고 각 그룹에 대한 집계를 수행합니다. 이를 통해 카테고리나 조건에 기반한 요약 및 통계를 쉽게 생성할 수 있습니다.

기본 구문

SELECT column_name, aggregate_function(column_name)
FROM table_name
GROUP BY column_name;

예시

제품 카테고리별 총 판매액을 계산하려면 쿼리를 다음과 같이 작성할 수 있습니다:

SELECT product_category, SUM(sales_amount)
FROM sales
GROUP BY product_category;

이 쿼리는 각 제품 카테고리별 총 판매액을 계산합니다.

예시 결과

product_category

SUM(sales_amount)

전자제품

100,000

음식

50,000

의류

75,000

3. 집계 함수와 GROUP BY 결합

GROUP BY와 집계 함수를 결합하면 데이터를 그룹화하고 각 그룹에 대한 통계를 계산할 수 있습니다. MySQL에서 자주 사용되는 일반적인 집계 함수는 다음과 같습니다:

  • SUM() : 숫자 데이터의 합계를 계산합니다.
  • COUNT() : 행의 수를 계산합니다.
  • AVG() : 숫자 데이터의 평균을 계산합니다.
  • MAX() : 최대값을 검색합니다.
  • MIN() : 최소값을 검색합니다.

샘플 쿼리

제품 카테고리별 총 판매액과 판매 건수를 모두 가져오려면:

SELECT product_category, SUM(sales_amount), COUNT(*)
FROM sales
GROUP BY product_category;

이 쿼리는 각 product_category에 대한 총 판매액과 판매 건수를 모두 검색합니다.

4. HAVING 절을 사용한 필터링

HAVING 절은 GROUP BY로 생성된 그룹화된 데이터에 조건을 적용합니다. 행을 집계 전에 필터링하는 WHERE 절과 달리, HAVING은 집계 함수 결과에 기반하여 그룹을 필터링합니다.

샘플 쿼리

예를 들어, 총 판매액이 1000을 초과하는 카테고리만 추출하려면:

SELECT product_category, SUM(sales_amount)
FROM sales
GROUP BY product_category
HAVING SUM(sales_amount) > 1000;

이 쿼리는 판매 총액이 1000을 초과하는 제품 카테고리만 반환합니다.

5. ORDER BY와 GROUP BY 사용

GROUP BY로 데이터를 그룹화한 후, ORDER BY 절을 사용하여 결과를 정렬할 수 있습니다. ORDER BY는 지정된 열 값에 기반하여 결과를 오름차순(ASC) 또는 내림차순(DESC)으로 정렬합니다.

샘플 쿼리

총 판매액에 따라 제품 카테고리를 내림차순으로 정렬하려면:

SELECT product_category, SUM(sales_amount)
FROM sales
GROUP BY product_category
ORDER BY SUM(sales_amount) DESC;

이 쿼리는 판매액이 높은 순서부터 낮은 순서로 제품 카테고리를 표시합니다.

6. 고급 GROUP BY: WITH ROLLUP

WITH ROLLUP은 그룹 총계 외에 전체 총계를 보여주는 요약 행을 추가합니다. 이는 보고서와 요약에 특히 유용합니다.

샘플 쿼리

도시별 판매 총계와 전체 총계를 모두 표시하려면:

SELECT city, SUM(sales_amount)
FROM sales
GROUP BY city WITH ROLLUP;

이 쿼리는 각 도시의 총 판매액과 전체 총계를 표시합니다.

7. GROUP BY와 DISTINCT의 차이점

DISTINCTGROUP BY는 모두 데이터를 정리하는 데 도움이 되지만, 목적이 다릅니다. DISTINCT는 중복 행을 제거하는 반면, GROUP BY는 데이터를 그룹화하고 집계를 수행합니다.

샘플 쿼리 비교

DISTINCT를 사용하여 제품 카테고리의 고유 목록을 가져오는 경우:

SELECT DISTINCT product_category
FROM sales;

GROUP BY를 사용하여 제품 카테고리별 판매 건수를 가져오는 경우:

SELECT product_category, COUNT(*)
FROM sales
GROUP BY product_category;

DISTINCT는 중복을 제거할 뿐이며, GROUP BY는 집계를 수행합니다.

8. MySQL에서 GROUP BY 성능 최적화

대용량 데이터셋을 다룰 때, GROUP BY 성능을 최적화하는 것은 매우 중요합니다. 적절한 설정과 쿼리 튜닝을 통해 효율성을 크게 향상시킬 수 있습니다.

1. 인덱스 사용

GROUP BY에 사용되는 열에 인덱스를 추가하면 검색 및 그룹화 속도가 향상됩니다.

CREATE INDEX idx_category ON sales(product_category);

적절한 인덱싱은 성능을 크게 향상시킬 수 있습니다.

2. 메모리 설정 조정

sort_buffer_sizetmp_table_size와 같은 메모리 설정을 최적화하면 대용량 데이터셋을 처리할 때 성능이 개선됩니다.

SET GLOBAL sort_buffer_size = 2M;
SET GLOBAL tmp_table_size = 64M;

메모리를 늘리면 디스크 쓰기가 감소하고 쿼리 실행 시간이 단축됩니다.

3. 쿼리 단순화

복잡한 쿼리는 성능을 저하시킵니다. 과도한 JOIN 및 서브쿼리를 피하고, 불필요한 열과 조건을 제거하여 속도를 높이세요.

4. 버전별 기능

MySQL 8.0 이상에서는 정렬 기반 그룹화 외에 해시 기반 그룹화가 제공됩니다. 해시 기반 그룹화는 대용량 데이터셋에서 더 빠릅니다.

SET optimizer_switch = 'hash_join=on';

5. 쿼리 캐시 사용

MySQL 5.7 및 이전 버전에서는 쿼리 캐시를 활성화하면 반복 쿼리의 성능이 향상됩니다.

SET GLOBAL query_cache_size = 16M;
SET GLOBAL query_cache_type = 1;

6. 파티셔닝 고려

MySQL의 파티셔닝 기능은 대규모 데이터베이스를 작은 세그먼트로 나누어 쿼리 실행 속도를 높입니다.

ALTER TABLE sales PARTITION BY RANGE (YEAR(sale_date)) (
    PARTITION p0 VALUES LESS THAN (2021),
    PARTITION p1 VALUES LESS THAN (2022),
    PARTITION p2 VALUES LESS THAN (2023)
);

9. 요약: GROUP BY의 효과적인 사용

GROUP BY 절은 데이터를 그룹화하고 집계하는 데 필수적인 SQL 도구입니다. 이 글에서는 GROUP BY의 기본 개념, HAVING 및 ORDER BY와 함께 사용하는 방법, 그리고 WITH ROLLUP과 같은 고급 기능을 배웠습니다. 또한 인덱스, 메모리 설정, MySQL 8.0의 해시 기반 그룹화와 같은 버전별 기능을 활용한 성능 최적화 방법도 살펴보았습니다.

추가로, 쿼리 캐시와 파티셔닝과 같은 고급 MySQL 기능을 다루어 대용량 데이터셋을 보다 효율적으로 처리하는 방법을 소개했습니다. 이러한 기술을 적절히 적용하면 프로젝트에서 데이터 분석 및 보고 성능을 크게 향상시킬 수 있습니다.