
다른 column들은 14108을 반환했는데 fd1 같은 경우에는 default 가 null이어서 그중에 null이 아닌녀석을 반환해서 숫자가 줄어든 것이다.
returns a count of the number of non-NULL values of expr in the rows retrieved by a SELECT statement
인자로 null을 주면 select count(NULL) = 0 이 된다.
where 조건 가진 Count
- Covering Index
- Non Covering Index
where 조건 없는 Count
- ha_records() 스토리지 API 사용
- ha_index_next() 스토리지 API 사용

fd1, fd2 둘다 row 갯수는 같다. Not NULL에 상관없이 두 컬럼 모두 다 row에 NULL이없이 값이 들어 있다.

Handler_read_rnd_next is a MySQL status variable that counts the number of times a row was read in a random order during table scans.
read_first가 1이고 rnd_next 값이 큰것은 primary index를 full scan했다는것을 의미한다.
왼쪽은 innodb 의 ha_records api를 딱 한번 호출해서 기록이 남지 않은 것이다.
innodb_parallel_read_threads 설정
- MySQL 8.0 버전은 조건없은 Count()쿼리에 대해서 병렬 처리 지원
- 병렬 처리를 비활성화하면 결과는?
- 실행 계획은 동일하지만 쿼리 성능은 달라진다.

- 모든 쿼리를 병렬로 처리할 수 있는 것은 아니다.기본 병렬로 처리할 수있는 스레드가 4이다.
- 위 예시는 1로 변경한 경우이다.
- fd2는 그대로인데 fd1은 병렬 처리를 비활성화하니까 훨씬 느려졌다.
- 이는 Innodb 스토리지 엔진이 내부적으로 레코더를 읽어서 컬럼을 추출해내는 작업을 했는지 여부에따라 성능이 달라진다.
- 병렬 처리가 활성화된 경우 fd1, *의 경우에는 컬럼을 추출해내는 작업을 하지 않았다. 이는 fd1이 not null이기 때문이다.
- 병렬처리가 비활성화된 경우 fd1, fd2 는 컬럼에서 추출해내는 작업을 해서 느려졌다. 엥간하면 *을 사용하는것이 좋겠다.
조건없는 Count
- Count(*) 와 Count (not_null_column)
- ha_records() 스토리지 엔진 API 사용
- 레코드 건수에 관계없이 , 1회만 호출된다.
- Count(*) 쿼리는 레코드로부터 컬럼 추출 수행하지 않는다.
- innodb_parallel_read_threads >= 2 의 경우 , Count(not_null_column) 쿼리는 컬럼 추출 수행하지 않는다.
- Count(nullable_column)
- ha_index_next() 스토리지 엔진 API 사용
- 레코드 건수 만큼 호출된다.
- 주어진 컬럼에 대해서 Eval 작업이 필요하다 (레코드의 컬럼 추출필요)

레코드수를 count하는데 index를 full scan하고 있다는것을 알 수 있다. mysql은 index가 null이 column도 포함하고 있다. 그래서 null 이들어간 column이든 아니든 정확한 record 건수를 가지고 올 수 있다.
Extra에 Using index는 커버링 인덱스로 처리되었다는것을 의미한다.
커버링인덱스 = 인덱스에 있는 column들만 읽어도 충분함 , 추가적으로 데이터를 읽지않아도 처리가능
primary key index를 읽지 않고 idx1 index를 읽었다는것이다. primary key index는 record의 데이터를 가지고 있기 때문에 크기가 매우 큰 반면에 idx1 인덱스는 컬럼 한개만 가진 인덱스이기 때문에 매우 크기가 작다. mysql에서는 최소의 disk 읽기만 해도 쿼리를 완료할 수 있는 작은 index를 선택한 것이다.

실행계획에서는 idx1 index를 사용한다고 하였지만 실제 쿼리가 실행되면서 buffer pool의 페이지를 조사해보니 primary key index가 사용된것을 알 수 있다.
이는 버그이다. where 없는 것은 맨날 primary key index를 사용하도록 작성이 되어있던것이다. 조만간 고쳐진다 한다.

ix1이 comment인것들 중에 fd1 이 null인지 아닌지도 확인을 해야한다.
그래서 Extra에 index라 안뜨는것이다.(covering index) , 인덱스뿐만아니라 데이터도 실제로 읽어서 확인을 해야하기 때문이다.
실행계획을 해석 해보면
ix1 인덱스를 통해서 comment 인지 확인해서 16개를 찾고 이 16개의 row의 primary key를 통해서 record를 한건식 찾은다음 fd1이 null인지 아닌지 확인하는 것이다.
count(*) 을 통해서 covering index를 활용하는것이 좋아보인다.

왼쪽은 covering index가 아니라 위위 예시처럼 null 을확인을 하고 있다.
'Database > Real MySQL Season1 ,2' 카테고리의 다른 글
19) JSON 타입 활용 (0) | 2024.10.30 |
---|---|
17) NoWait & Skip Locked , 18) Union vs Union All (0) | 2024.10.24 |
15) 풀스캔 쿼리 패턴 및 튜닝 (0) | 2024.10.22 |
14) UUID 사용 주의사항 (0) | 2024.10.10 |
13) 콜레이션 (0) | 2024.10.08 |