일반 SQL 질의의 SELECT 절에의 *는 모든 컬럼을 가지고 오기 때문에
필요한 컬럼만 가지고 오는 SELECT 절에 비해 속도가 느리고 불필요한 자원을
낭비한다는 사실은 모두가 알고 있을 것입니다.
그렇기 때문에 이러한 것을 똑같이 생각함으로 인해 집계함수의 COUNT에 대한 COUNT(*) 와
COUNT(컬럼)에 대한 잘못된 인식과 SQL 질의를 실행하여 DB의속도를 느리게 할 수 있는 원인이 될 수 있습니다.
일반 SQL질의와 다르게 COUNT 집계함수에서의 *의 역할은 다른 역할을 수행하고 있습니다.
* MySQL COUNT 함수의 역할을 보면
COUNT(*) : 단순 행을 세는 역할을 합니다. (MySQL 내부적으로 데이터를 읽지않고 행의 갯수만 흝고 지나간다는 뜻을 말합니다.)
COUNT(컬럼) : 행의 값을 세는 역할을 합니다.(데이터를 읽는다는 뜻이 되겠지요)
자 그럼, 컬럼이 VARCHAR(50) 형태의 데이터가 100만건이 있다는 가정하에 실행계획 및 질의를 실행에 보도록 하겠습니다.
* 실행계획
1) COUNT(*) : 우선 단순 행을 세는 COUNT(*)의 실행계획을 보도록 하겠습니다.
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE Select tables optimized away
Select tables optimized away : 인덱스, 또는 MyISAM용 COUNT(*)을 사용하되 GROUP BY 구문은 사용하지 않은 채로 처리된 집단 함수(MIN(), MAX())만을 가지고 있음.
2) COUNT(컬럼) : 데이터를 읽고 지나가는 COUNT(컬럼)의 실행계획을 보도록 하겠습니다.
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE performance1 ALL 1000000
실행계획을 보면 알듯이 type을 보면 알 수 있듯이 ALL로 전체를 스캔하는 것을 알 수 있수 있을 것입니다.
3) COUNT(DISTINCT(컬럼)): DISTINCT에 데이터를 읽고 지나가는 COUNT(DISTINCT(컬럼))의 실행계획을 보도록 하겠습니다.
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE performance1 ALL 1000000
COUNT(DISTINCT(컬럼))도 type을 보면 알 수 있듯이 ALL로 전체를 스캔하는 것을 알 수 있을 것입니다.
실행계획을 봤으니 SQL질의를 실행하여 실행시간을 비교해 보도록 하겠습니다.
* 실행결과를 종합해 보면
1) COUNT(*) : 0:00:00.029
2) COUNT(컬럼) : 0:00:00.201
3) COUNT(DISTINCT(컬럼)) : 0:00:02.413
COUNT(DISTINCT(컬럼)) < COUNT(컬럼) < COUNT(*) 순입니다.
그렇습니다. 불필요한 데이터를 셀 필요없이 행의 갯수만 얻고 싶다면 당연히 * 쓰는게 훨씬 속도
가 빠르다는 사실을 알 수 있을 것을 것입니다.
그러면 '혹시 컬럼에 인덱스를 걸어주면 데이터를 세더라도 count(*)보다 빠르지 않을까?' 라는 생각이 문득 들어서
컬럼 하나에 인덱스를 걸고 인덱스를 타게 해서 질의를 실행하여 비교해 보도록 하였습니다.
* 실행계획
1) COUNT(*)
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE Select tables optimized away
2) COUNT(컬럼)
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE performance2 index index 153 1000000 Using index
3) COUNT(DISTINCT(컬럼))
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE performance2 index index 153 1000000 Using index
* 실행결과를 다시 종합해보면
1) COUNT(*) : 0:00:00.054
2) COUNT(컬럼) : 0:00:00.592
3) COUNT(DISTINCT(컬럼)) : 0:00:02.955
그렇습니다. 실행결과를 보면 인덱스 거는거에 상관없이 COUNT(*)이 가장 빠르게 질의를 수행한다는 것을 알 수 있
을 것입니다. 누구나 다 아는 사실이지만, 참고가 될 수 있도록 글을 기재합니다.
[ 실행환경 ]
MySQL Version : 5.1.41-community
테이블 형태 : MyISAM
컬럼 형태 : varchar(50)
출처 : https://www.phpschool.com/gnuboard4/bbs/board.php?bo_table=tipntech&wr_id=77484
'Database ( DB ) > Database' 카테고리의 다른 글
MySQL 쿼리 실시간 모니터링 (0) | 2019.08.10 |
---|---|
[oracle] COUNT(*) 를 빠르게 하는 방법 (0) | 2019.08.10 |
mysql 날짜검색시 between 안에 포함되는 날짜전체 출력 (0) | 2019.08.10 |
DB key값이 무조건 대문자로 return 될 때 해결 방법 (0) | 2019.08.10 |
[mariaDB, MySQL] DB 연결 속도저하 해결 방법 (0) | 2019.08.10 |