테이블 스캔 방식에 따른 DB Block IO 전략

데이터베이스가 쿼리에서 요구하는 데이터를 검색하기 위해 테이블에 접근하는 방식의 종류는 다양하다.

가장 주요하고 크게는 인덱스를 활용하는지에 따라 갈리고, 인덱스를 어떤 방식으로 스캔할지에 대해서도 종류가 나뉜다.

각 스캔 방식들은 내부 작동 방식에 따라 서로 다른 Block IO 전략을 가지게 되는데, 이러한 내부 작동의 차이를 이해하면 왜 DB가 해당 방식을 사용했는지에 대한 이해도를 높일 수 있다.

Block IO

데이터베이스에서 IO를 하는 단위를 Block으로 하기 때문에, DB 엔진에 따라 1회의 IO에서 8KB내지 16KB의 데이터를 불러온다. 이러한 IO의 단위가 Block이 되어 데이터를 읽어와 버퍼 캐시에 적재하는 과정을 Block IO라고 한다.

Single Block IO vs Multi Block IO

Single의 경우 한 번에 하나의 Block만 읽어오고, Multi 의 경우 한 번에 여러 개의 Block을 불러온다.

이때 한 번의 시스템 콜을 기준으로 하면 Multi 가 더 많은 데이터를 불러오기 때문에, 표면적으로는 Multi가 더욱 유용하게 생각될 수 있다.

Single Block IO

를 사용하는 스캔 방식은 아래와 같다.

  • Index Range Scan
  • Index Full Scan (인덱스를 통해 추가적인 테이블 스캔 소요가 있는 경우에 한함)
  • Index Unique Scan
  • Index Skip Scan

즉, 인덱스에 의존한 채 정렬된 인덱스를 순차적으로 탐색하는 방식이라는 것이다.

하나의 인덱스 구조에 대한 요소들은 여러 Block에 나뉘어 저장되고, 이는 인덱스의 논리적 정렬을 무의미하게 만든다.

따라서, 논리적으로 정렬된 인덱스 구조를 따라 탐색을 진행하려면 한 번에 하나의 Block만을 읽어가며 확인해야한다.

즉, 인덱스 기반 탐색을 진행하려면 Multi로 데이터를 불러오면 안된다는 것이다. 만일 불러온다고 해도 하나만 읽어야 인덱스 기반 탐색이 유의미해진다.

다만, 만일 Single Block IO를 통해 읽어내야할 데이터 수가 증가하게 되면, 시스템 콜을 그만큼 더 수행해야하기 때문에 CPU점유율이 선형적으로 증가할 수 있다.

인덱스를 이용한 스캔이 모든 경우에 대해 더 빠른 선택지가 아닌 이유이다. 인덱스를 활용해도 되지만 종종 DB가 전체 테이블을 읽는 것도, DB내부 Optimizer가 위 논리에 따라 더 빠른 방식을 자체적으로 계산했기 때문이다.

Index Full Scan의 경우, Multi Block IO방식을 사용하는 경우도 있다.

이 방식은 인덱스의 논리적 정렬 구조를 완전히 무시한 채, 여러 Block 을 한 번에 버퍼에 가져와 읽어내는 방식이다.

정렬 구조를 무시하기 때문에 버퍼에 읽어왔을 때는 정렬 상태가 유지되지 않는다는 단점이 존재한다.

즉, 정렬 상태는 유지되지 않지만, 인덱스만으로 필요한 모든 칼럼을 빠르게 가져올 수 있으므로 전체 테이블을 읽지 않아도 필요한 데이터를 효율적으로 조회할 수 있게 됨을 의미한다.

Ref