단일-헤드 디스크 시스템에서는 특정 데이터 블록을 읽거나 쓰려면, 헤드를 데이터가 존재하는 트랙으로 이동시키고+ 원하는 데이터가 저장된 섹터가 헤더 아래도 회전돼 올때까지 기다리는 시간+ 데이터를 전송하는 과정이 필요하다.
이 모든 과정을 수행하는 데 걸리는 시간을 디스크 접근시간이라고 한다. 탐색 시간(Seek Time)은 헤드를 데이터가 존재하는 트랙으로 이동시키는 과정에서 소요되는 시간이다. 기계적인 이동이기 떄문에 시동 시간이 필요하다. 액세스할 데이터들의 지역성이 높은 경우에는, 헤드의 이동 거리가 짧아지기 때문에 평균 탐색 시간을 단축할 수 있다.
회전 지연 시간(Rotational Latency) 은 원하는 데이터가 저장된 섹터가 헤드 아래로 회전되어 올 때까지 기다리는데 소요되는 시간을 의미한다.
데이터 전송 시간(Data Transfer Time) 데이터를 전송하는데 소요되는 시간을 의미한다. 주로, 블록의 크기, 회전 속도, 트랙의 저장 밀도, 버스 전송률 및 제어기 내부 전자회로의 속도에 따라 결정된다.
하드 디스크에서 랜덤 액세스보다 순차 액세스가 더욱 빠른 이유가 무엇일까?
랜덤 액세스는 디스크 다른 위치에 흩어져 있는 데이터 블록을 읽어야 하기 때문에 헤드를 여러분 움직이며 ,각 블록에 접근할 때마다 회전 지연 시간을 기다려야 한다. 이러한 기계적인 이동으로 발생하는 지연으로 인해 랜덤 액세스가 순차 액세스보다 상대적으로 느리다.
반면, 순차 액세스는 데이터가 연속적인 경우 발생한다. 상대적으로 랜덤 액세스에 비해 기계적인 이동이 적기 때문에 빠른 속도를 보인다.
SSD는 하드 디스크 드라이브에서 데이터 저장용 플래터(원판)을 제거하고, NAND 플래시 메모리를 장착한다. 디스크 원판을 기계적으로 회전시킬 필요가 없어져서 HDD에 비해 아주 빨리 데이터를 읽고 쓸 수 있다. 플래시 메모리는 전원이 공급되지 않아도 데이터가 삭제되지 않는 특징을 가진다
순차 I/O와 랜덤 I/O 모두 하드 디스크 드라이브의 원판을 돌려서 읽어야 할 데이터가 저장된 위치로 디스크 헤더를 이동시켜야 한다.
그렇다면, 무슨차이가 있을까?
여러개의 데이터를 입력할 때 순차 I/O는디스크 헤드를 한번만 움직이지만, 랜덤 I/O는 디스크 헤더를 데이터 개수만큼 움직여야 한다. (이 부분은 순차 I/O가 읽어야 할 데이터가 연속적이기 때문이다)
디스크 헤더를 움직이는 시간은 디스크에 데이터를 읽고 쓰는 데 걸리는 시간에서 가장 시간을 많이 차지하고, 병목도 가장 크다. 그래서, 여러 번 쓰기 또는 읽기를 요청하는 랜덤 I/O 작업이 작업 부하가 훨씬 더 크다.
SSD는 디스크 원판(플래터)를 가지지 않으므로 랜덤 I/O와 순차 I/O의 차이가 없어보이지만, 실제론 그렇지 않다. SSD 에서도 랜덤 I/O는 순차 I/O보다 처리율(Throughput)이 떨어진다.
SSD는 물리적으로 NAND 플래시 메모리에 저장된 데이터를 직접 읽고 쓰지 않는다. 내부적으로 논리적인 주소를 물리적인 주소로 맵핑하는 테이블을 사용한다.
매핑 테이블을 업데이트 하려면, NAND 플래시 메모리의 물리적인 위치를 찾아가야 하므로 랜덤 I/O는 이 과정이 추가로 발생해 전체 처리율이 떨어진다.(데이터를 찾을 수 있는 표가 있는 것으로 이해했다)
순차I/O라면, 논리적인 위치를 통해 알아낸 물리적인 위치를 통해 나머지 항목들도 업데이트해주면 된다.
랜덤 I/O와 순차 I/O 모두 파일에 쓰기를 실행하면, 반드시 동기화 (fsync, flush 작업)이 필요하다. 순차 I/O 더라도, 파일 동기화 작업이 빈번히 발생한다면 랜덤I/O 와 같이 비효율적인 형태로 동작하게 된다. 그래서, 캐시 메모리가 장착된 RAID 컨트롤러를 사용해 순차 I/O를 효율적으로 처리할 수 있게 도와준다.
일반적으로 쿼리를 튜닝하는 것은 랜덤 I/O 자체를 줄여주는 것이 목적이다. 즉 랜덤 I/O를 줄인다는 것은 쿼리를 처리하는 데에 꼭 필요한 데이터만 읽도록 쿼리를 개선하는 것을 의미한다.
인덱스 레인지 스캔(Index Range scan)은 데이터를 읽기 위해 주로 랜덤 I/O를 이용하고, 풀 테이블 스캔(Full Table scan)은 순차 I/O 를 사용한다.
그래서 큰 테이블의 레코드 대부분을 읽는 작업에서는 인덱스를 사용하지 않고 풀 테이블 스캔을 사용하도록 옵티마이저가 유도하기도 한다.
클러스터링 인덱스를 활용한 스캔은 "순차 I/O"
PK를 이용해서 레인지 스캔을 하면 순차 I/O를 쓰게 된다. 클러스터링 인덱스는 메모리 상에 저장된 데이터 페이지의 논리적인 위치와 물리적으로 저장된 위치가 동일한 순서로 정렬된다.
여러 개의 데이터를 조회하거나 수정할 때, 바로 옆의 데이터를 조회하면 된다. 랜덤 I/O 방식대로 동작할 이유가 없고, 순차 I/O 방식으로 동작하는 것이 훨씬 효율적이다.
하지만, 클러스터링 인덱스를 통해서 조회하더라도, 순서대로 조회하는 것이 아니라 띄엄띄엄 조회하게 된다면 랜덤 I/O 방식으로 동작한다.
물론, 클러스터링 인덱스 또한 하나의 데이터에 대해 조회하거나 업데이트하는 것은 랜덤 I/O 방식이라고 봐도 무방하다.
세컨더리 인덱스를 활용한 스캔은 "랜덤 I/O"
세컨더리 인덱스는 클러스터링 인덱스와는 달리, 데이터 페이지의 위치와 물리적인 위치가 동일한 순서가 아니다. 세컨더리 인덱스는 인덱스 구조를 봐도, 물리적인 저장위치를 저장하는 것이 아니라, 클러스터링 인덱스의 위치를 저장하고 있다.
즉, 세컨더리 인덱스를 이용해 조회하는 명령은 여러 곳에 분산된 데이터를 조회하게 되므로, 랜덤 I/O 방식으로 동작한다. 수정 작업 또한 인덱스를 활용하므로, 여러 데이터를 동시에 수정하는 작업도 랜덤 I/O 방식으로 동작한다.
참고자료