COUNT 쿼리 기본 이해
Count 쿼리는 행 수를 세는 데 사용한다.
COUNT(*) 는 테이블의 모든 행을 센다.
NULL 값도 포함되는데
COUNT(fd) 의 경우
지정된 컬럼이 NULL이 아닌 경우에만 행을 센다.
NULL 값이 있는 행은 제외된다.
즉
fd1 컬럼이 NULL 을 허용하는 경우
SELECT COUNT(fd1)
의 경우SELECT COUNT(*)
보다 적은 수를 반환할 수 있음.
성능 최적화 팁
인덱스를 잘 활용 해야함
커버링 인덱스 사용하는 경우 쿼리가 인덱스만 읽으며
데이터 파일을 추가로 읽지 않아도 속도가 빨라진다.
MySQL 8.0 에서는
innodb_parallel_read_threads
설정을 통해일부 COUNT(*) 쿼리를 병렬 처리 가능
큰 테이블에서 유리하다..
모든 쿼리가 병렬 처리되는 것은 아니다.
설정과 쿼리 구조에 따라 다름
MySQL COUNT 쿼리 분석
쿼리 종류 차이
COUNT(*) ↔ COUNT(column)
COUNT(*)
테이블의 모든 행을 센다. null 값도 포함된다.
스토리지 엔진
ha_records
API 로 빠르게 행 수 반환 가능
COUNT(column)
지정된 컬럼이 null 이 아닌 경우 카운트
fd1
컬럼이 nullable 이고 일부 행이 NULL 인 경우SELECT COUNT(fd1)
은SELECT COUNT(*)
보다 적은 수 를 반환내부적으로
ha_index_next
API 사용함.행을 하나 씩 스캔해 NULL 여부를 확인해 성능이 느리다
create table counter ( fd1 int not null, fd2 int null ); mydb> select count(fd1) from counter [2025-03-20 21:20:12] 1 s 225 ms (execution: 958 ms, fetching: 267 ms)에서 1부터 1개 행을 불러왔습니다 mydb> select count(*) from counter [2025-03-20 21:20:18] 1 s 235 ms (execution: 938 ms, fetching: 297 ms)에서 1부터 1개 행을 불러왔습니다 mydb> select count(fd2) from counter [2025-03-20 21:20:27] 7 s 137 ms (execution: 6 s 799 ms, fetching: 338 ms)에서 1부터 1개 행을 불러왔습니다
보면 nullable 컬럼의 count 가 무려 7배나 느리다.
컬럼은 100만건이 insert 되어 있음 1로만 구성..
정리
쿼리 타입 실행 시간 (초) 설명 | ||
COUNT(*) | 1.235 | 병렬 처리 활성화, 커버링 인덱스 사용 |
COUNT(fd1, NOT NULL) | 1.225 | NOT NULL 컬럼, ha_records 사용 |
COUNT(fd2, nullable) | 7.137 | nullable 컬럼, ha_index_next 사용, 느림 |
난 COUNT(*) 이 성능이 더 안좋은 줄 알았다..
근데 실제로는 COUNT(*) 을 사용하는 경우가 성능 최적화에 더 도움이 된다;;
커버링인덱스로 짜여진 COUNT 와 COUNT(*) 대부분 성능이 비슷하고
병렬처리된 경우 COUNT(*) 이 거의 5배 이상으로 성능이 더 좋다
비교 대상 ) NULLABLE 컬럼, NOT NULL 컬럼 COUNT(fd) 경우