2023-java-study / book-study

북 스터디 기록 레포지토리
0 stars 0 forks source link

[8.3.4.1] 인덱스 스캔의 작업 비용 #169

Open NuhGnod opened 11 months ago

NuhGnod commented 11 months ago

P.232 이 때, 리프 노드에 저장된 레코드 주소로 데이터 파일의 레코드를 읽어오는데, 레코드 한 건 한 건 단위로 랜덤 I/O 가 한번씩 일어난다. ... 중략 ... 그리고 인덱스를 통해 읽어야 할 데이터 레코드가 20~25% 를 넘으면 인덱스를 통한 읽기보다 테이블의 데이터를 직접 읽는 것이 더 효율적인 처리 방식이 된다.

지금 8.3.4.1 내용들은 p.230의 select * from employees where first_name between 'Ebbe' and 'Gad'; 쿼리에 대한 내용입니다. 그래서 위 문장에서 리프 노드에 저장된 레코드 주소로 데이터 파일의 레코드를 읽어 오는 이유가 select * 로 전체 데이터를 요청했기 때문이라고 이해했습니다.

여기서 의문점은 그럼 인덱스를 통해 조회하는게 아니라 실제 데이터 파일 을 읽는것은 랜덤 I/O 가 일어나지 않는 다는 것인가? 입니다. 만약 그렇다면 어떻게 데이터를 들고오는지!

gmelon commented 11 months ago

저는 인덱스를 통해 디스크의 데이터에 접근하게 되면 실제 데이터가 저장되어 있는 순서와 다르게 계속해서 임의의 주소에 접근하게 되기 때문에 인덱스를 통한 데이터 읽기는 매번 랜덤 I/O가 발생한다고 이해했습니다.

즉 아래와 같은 그림이 될 것 같아요 (각 데이터가 서로 다른 페이지에 있다고 가정)

image

반면 애초부터 모든 데이터를 읽겠다고 마음먹고(?) 디스크를 전체적으로 읽으면 한 페이지에 있는 데이터를 읽는 동안은 랜덤 I/O가 아니라 캐싱해온 데이터를 쭉 읽어올 수 있으므로 모든 데이터를 읽어야할 경우에는 이렇게 하는 쪽이 랜덤 I/O로 인한 오버헤드는 더 적구나 하고 이해했었습니다.

ssstopeun commented 11 months ago

인덱스를 통해서 인덱스 탐색 후에 레코드 주소를 찾은 후에 랜덤 I/O를 통해 데이터파일을 읽는 것이 아니고 실제 데이터 파일을 바로 읽어오는 것도 인덱스 탐색만 안하는 것이고 랜덤 I/O는 사용하는 것으로 이해했습니다.

그리고 리프 노드에 저장된 레코드 주소로 데이터 파일의 레코드를 읽어 오는 이유가 select * 로 전체 데이터를 요청했기 때문이라고 이해하셨다고 했는데 왜 그렇게 이해하신지 궁금합니다! 전체 데이터를 요청하지 않고 일부 데이터만 요청하더라도 우선 인덱스 탐색으로 리프노드에 저장된 레코드 주소를 알아 낸 후 랜덤 I/O를 통해 데이터파일의 레코드를 읽어온 후 그 레코드 속에서 필요한 데이터를 가져올 수 있지 않나요?