[MySQL] GROUP BY Optimization

2023. 12. 24. 17:05·Database/MySQL
반응형

[MySQL] GROUP BY Optimization 

MySQL은 GROUP BY 사용 시 대개는 전체 대상 테이블을 스캔한 후 새로운 임시 테이블을 만든 후 사용을 하도록 되어 있다. 하지만 인덱스 접근이 가능하다면 임시 테이블 생성을 피할 수 있다.

GROUP BY에 가장 중요한 인덱스 사용 조건은 컬럼들이 호출한 쿼리 순서대로 저장하고 있는지 이다. 인덱스 사용에 성공한다면, 두가지의 방법이 있다.

  • Loose Index Scan: 모든 범위 조건과 함께 그룹화하는 방법.
  • Tight Index Scan: 범위 스캔 후 결과를 그룹화하는 방법.

Loose Index Scan

테이블 t1(컬럼 a, b, c, d, e)이 인덱스로 (a, b, c) 를 가지고 있다고 가정해 보겠다.

인덱스 사용 가능

  • GROUP BY a, b
  • MIN(), MAX() 같은 SELECT 집계 함수 대상 컬럼이 인덱스 있는 경우 
    •  AVG와 SUM은 Single argument 경우, COUNT는 하나 이상 지원한다.
SELECT a, b FROM t1 GROUP BY a, b;
SELECT DISTINCT a, b FROM t1;

SELECT a, MIN(b) FROM t1 GROUP BY a;
SELECT MAX(c), MIN(c), a, b FROM t1 WHERE b > const GROUP BY a, b;

SELECT b FROM t1 WHERE a < const GROUP BY a, b;
SELECT a, b FROM t1 WHERE a < const GROUP BY a, b;
SELECT a, b FROM t1 WHERE c = const GROUP BY a, b;

인덱스 사용 불가능

  • GROUP BY b, c
  • GROUP BY a, b, d
# MIN(), MAX() 집계 함수가 아니라 
SELECT a, SUM(b) FROM t1 GROUP BY a;

# 가장 처음 시작하는 컬럼으로 GROUP BY를 하지 않음 (애초에 오류 발생 가능한 쿼리임)
SELECT a, b FROM t1 GROUP BY b, c;

# SELECT 컬럼과 GROUP BY 컬럼이 일치하지 않음 (애초에 오류 발생 가능한 쿼리임)
SELECT c1, c3 FROM t1 GROUP BY c1, c2;

Tight Index Scan

Tight Index Scan은 쿼리 조건에 따라서 full index scan 혹은 range index scan으로 처리될 수 있다.

쿼리가 Loose Index Scan으로 아직 처리 되지 않았을 때 아직 임시 테이블을 피할 수 있는 경우가 있다. 
만약, Where 절에 range 조건이 있다면 조건에 만족하는 키들만 읽어올 것이고 그렇지 않다면 index scan을 수행할 수 있다.
인덱스를 사용하지 않는 경우의 이유는 이 방법은 Where 절에 범위를 확인하기 위해 모든 키를 읽어야 하기 때문이다.

인덱스 사용 가능

# GROUP BY에 컬럼이 누락 되었지만, CONDITION으로 b가 있어서 충족이 된다.
SELECT a, b, c FROM t1 WHERE b = 'xxx' GROUP BY a, c;

인덱스 사용 

# 이 경우는 인덱스 첫 컬럼으로 시작하지 않기에 조건에 충족하지 못한다.
SELECT a, b, c FROM t1 WHERE a = 'xxx' GROUP BY b, c;

Ref

https://dev.mysql.com/doc/refman/8.0/en/group-by-optimization.html

 

MySQL :: MySQL 8.0 Reference Manual :: 8.2.1.17 GROUP BY Optimization

8.2.1.17 GROUP BY Optimization The most general way to satisfy a GROUP BY clause is to scan the whole table and create a new temporary table where all rows from each group are consecutive, and then use this temporary table to discover groups and apply agg

dev.mysql.com

 

728x90
반응형
저작자표시 비영리 (새창열림)
'Database/MySQL' 카테고리의 다른 글
  • [MySQL] Table lock 조회 쿼리
  • [MySQL] ORDER BY Optimization
  • [MySQL] Show Index
  • [MySQL] binlog to SQL(텍스트) 변환
상쾌한기분
상쾌한기분
  • 상쾌한기분
    상쾌한기분
    상쾌한기분
  • 전체
    오늘
    어제
    • 분류 전체보기 (251)
      • Python (44)
        • Python (26)
        • Django (6)
        • Flask (4)
        • Open Source (6)
      • Kotlin & Java (5)
        • Spring (2)
        • 프로젝트 (1)
      • Go (11)
      • Database (24)
        • MySQL (21)
        • Redis (3)
      • Infrastructure (2)
        • CDC (4)
        • Kafka (5)
        • Prometheus (2)
        • Fluentd (11)
        • Docker (1)
        • Airflow (2)
        • VPN (2)
      • IT (26)
        • AI (9)
        • Langchain (8)
        • Web (18)
        • Git (8)
        • 리팩토링 (9)
        • Micro Service Architecture (8)
        • Clean Code (16)
        • Design Pattern (0)
        • 수학 (1)
        • 알고리즘 (14)
      • OS (14)
        • Centos (10)
        • Ubuntu (3)
        • Mac (1)
      • Search Engine (2)
        • ElasticSearch (1)
        • Lucene Solr (1)
      • PHP (2)
        • Laravel (1)
        • Codeigniter (1)
  • 블로그 메뉴

    • Github 방문
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    Langchain
    performance
    파이썬
    git
    prompt
    CDC
    Golang
    백준
    python
    go
    Redis
    MYSQL
    LLM
    Kafka
    ollama
    docker
    티스토리챌린지
    http
    fluentd
    오블완
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
상쾌한기분
[MySQL] GROUP BY Optimization
상단으로

티스토리툴바