랜덤 엑세스란 무엇인가?

예전에 받았던 질문중에서

"MyBatis를 쓰고 실행 계획에 기반한 쿼리 튜닝을 통해서 성능을 많이 향상시킨다고 하셨는데, 랜덤 엑세스에 대해서 아시나요?"

라는 질문이 있었다.

 

랜덤 엑세스?? 분명 내가 보던 실행 계획에는 그런 워딩은 없었던 것 같다. 

단순히 slow를 유발하는 컬럼에 대해 인덱스를 생성하고 해당 컬럼에 대한 쿼리 플랜에 index scan이 일어나는 것을 확인하고 쿼리의 실행 속도정도만 확인했었다.

 

나는 확실히 where 절에 활용되는 컬럼만을 집중했었다.

 

랜덤엑세스

랜덤 엑세스란 데이터를 저장하는 블록을 한번에 여러 개 액세스하는 것이 아니라 한 번에 하나의 블록만을 액세스하는 방식이다. 한 번에 여러 개의 블록을 액세스한다면(랜덤 엑세스와 반대) 같은 양의 데이터에 대해 적은 횟수의 디스크 I/O가 발생하기 때문에 성능이 향상될 수 있다.

 

그렇다면 과연 어떤 작업에서 랜덤 액세스가 발생하는 것일까?

바로 인덱스를 액세스하여 확인한 ROWID를 이용하여 테이블을 액세스하는 경우 랜덤액세스가 발생하게 된다.

 

ROWID는 해당 데이터를 찾아가는 유일한 주소 값이며 우리가 인덱스를 이용한다는 것은 인덱스로부터 조건을 만족하는 인덱스 값을 액세스한 후 ROWID를 확인하여 ROWID 값으로 테이블을 액세스하는 것을 의미한다.

 

이처럼 인덱스 접근 후 테이블을 접근하는 경우에 발생하는 I/O는 블록을 하나씩 접근하는 랜덤 액세스가 발생하게 된다.

 


랜덤 엑세스의 종류

랜덤 엑세스에는 확인 랜덤엑세스, 추출 랜덤 엑세스, 정렬 랜덤 엑세스 세가지 종류가 있다. 이 세가지 종류의 랜덤 엑세스에 대한 고려가 쿼리 성능 향상에 중요한 영향을 미친다.

 

1. 확인 랜덤 엑세스

SQL의 WHERE절, HAVING절 조건에 의해 발생하는 랜덤 엑세스이다.

인덱스 a컬럼과 일반 b컬럼이 where절의 조건으로 활용되었다면, 인덱스 a 컬럼을 통해 처리범위가 감소하게 된다. 하지만 일반 b컬럼은 인덱스에서 확인할 수 없기 때문에 별도로 filter 역할을 하게 된다. 여기서 확인 랜덤 엑세스가 발생한다. 

인덱스 a컬럼을 조회하여 테이블의 rowid를 얻고 이 후 테이블 rowid를 통해 실제 테이블에 접근하여 랜덤 엑세스가 발생하게 된다. 이때, 기껏 조회한 rowid set 중에서 일반 b컬럼의 filter에 의해 몇개의 레코드들이 걸러지게 된다.

 

이처럼 WHERE절의 컬럼이 인덱스에 존재하지 않아 테이블을 액세스하는 랜덤 액세스확인 랜덤 액세스라고 한다.

 

확인 랜덤 엑세스는 랜덤 엑세스의 횟수(처음 인덱스 a컬럼에 의해 조회된 rowid의 갯수랑 같다고 봐도 될 것 같다.) 보다 최종의 결과가 더 적게 추출될 수 있다는 것이다. 일반 컬럼에 의해 버려지는 데이터가 존재할 수 있기 때문이다.

 

따라서, SQL 쿼리 플랜을 통해 쿼리 성능향상을 고민한다면 확인 랜덤 엑세스를 최소화하는 방안이 제일 중요하다.

 

 

2. 추출 랜덤 엑세스

SQL의 SELECT절에 의해 발생하는 랜덤 엑세스이다. 

 

확인 랜덤 엑세스를 제거하여 (where절의 모든 조건에 인덱스 부여했다면) 인덱스 접근 후 rowid를 확보했다면 select에서 해당 rowid에 해당하는 값들을 챙겨와야 한다. 그런데 인덱스에서 모두 챙겨올 수 있다면 좋겠지만 안타깝게도 select 절에 인덱스에 포함되지 않는 컬럼c가 있다. 이럴때 인덱스 엑세스 후 다시 테이블에 접근하여 해당 rowid를 토대로 컬럼c의 값을 가져와야 한다. 이러한 랜덤 엑세스를 추출 랜덤 엑세스라고 한다.

 

이 추출 랜덤 엑세스의 특징은 결과의 양이 랜덤 엑세스 횟수와 동일할 수 밖에 없다. select에서 where절처럼 레코드의 제한을 제어할 수는 없기 때문입니다.

 

따라서 추출 랜덤 엑세스는 where절의 조회 결과만큼 발생하게 됩니다.

 

 

3. 정렬 랜덤 엑세스

SQL의 ORDER BY, GROUP BY 절에 의해 발생하는 랜덤 엑세스이다.

 

select 이후 order by절에 의해 레코드가 정렬될 때 정렬 기준에 해당하는 컬럼이 인덱스에 존재하지 않을 때 발생할 수 있는 랜덤 엑세스입니다. 추출 랜덤 엑세스와 마찬가지로 결과의 양과 랜덤 엑세스 횟수가 동일합니다.

 


위의 내용과 같이 추출, 정렬 랜덤 액세스는 랜덤 액세스의 횟수와 추출되는 데이터의 건수에는 변화가 없다.

하지만, 확인 랜덤 액세스는 추출되는 데이터의 건수가 감소할수 있으며 그렇기 때문에 버려지는 데이터가 존재할 수 있다.

이 때문에 확인 랜덤 액세스가 랜덤 액세스 중에서 가장 많은 부하를 발생시키고 개발자는 최우선적으로 확인 랜덤 액세스를 제거하기 위해 노력해야 합니다.

 

 

따라서 위의 질문에서 나는 쿼리플랜을 통해 index scan을 확인했다면 이후 랜덤 엑세스에 대한 고민이 필요했었다고 생각한다! 

 

 

reference : http://www.gurubee.net/lecture/2230

'Database' 카테고리의 다른 글

mysql 컬럼 추가 / 변경 삭제 쿼리 정리 (ALTER TABLE)  (0) 2022.08.31

댓글

Designed by JB FACTORY