TIL

2021.09.16 기록장

Gisungcu 2021. 9. 16. 21:41

ToDo

  • 알고리즘 문제 풀기
  • 책 읽기
  •  

Done

  • 책 읽기

Weekly goal

  • 책 읽기

216p.

랜덤 io와 순차 io

랜덤 io는 3개의 페이지를 디스크에 io작업을 할 때 3번 움직인다고 볼 수 있다.

순차 io는 모았다가 한 번의 디스크 헤드 이동으로 io작업을 한다.

이를 위해 mySQL에서는 그룹 커밋이나, 바이너리 로그 버퍼 또는 innoDB 로그 버퍼 등의 기능이 내장되어 있다.

 

인덱스 레이지 스캔은 데이터를 읽기 위해 주로 랜덤 io를 하며, 풀 스캔은 순차 io를 한다.

그래서 큰 테이블의 대부분의 자료를 읽을 때는 인덱스를 사용하지 않고 풀 스캔을 사용하는 경우도 있다.

 

218p.

인덱스는 insert나 delete 등 데이터 저장의 성능을 어느 정도 포기하고 select의 성능을 올리는 것이다.

그래서 무턱대고 인덱스를 걸어버리면 저장능력은 떨어지고 인덱스의 크기는 비대해질 것이다.

 

데이터 저장 방식(알고리즘) 별로 인덱스를 구분할 수 있다. 대표적으로는 B-tree와 해쉬 등이 있다.

B-tree인덱스는 칼럼의 값을 변형하지 않고 원래의 값을 이용해(물론 앞부분만 잘라서 관리하긴 하지만..) 인덱 싱하는 알고리즘이다.

MySQL에는 위치 기반 검색을 지원하기 위해 R-Tree 인덱스도 있지만 이도 B-tree를 응용한 것이다.

 

해쉬 인덱스는 칼럼의 값으로 해시값을 만들어 인덱싱 한다. 이는 매우 빠른 select를 보장하지만 값을 변형해서 저장하므로 전방(prefix) 일치와 같이 값의 일부만 검색하거나 범위를 검색할 때는 해시 인덱스를 사용할 수 없다.

 

유니크 인덱스는 사용자가 보기에는 그저 하나만 저장되는 특징이 있지만 옵티마이저의 입장에서는 하나만 찾으면 더 이상 select하지 않아도 된다는 보장 효과를 준다.

 

220p.

데이터 베이스에서는 인덱스와 실제 데이터가 저장된 데이터를 따로 관리되는데, 인덱스의 리프 노드는 항상 실제 데이터 레코드를 찾아가기 위한 주솟값을 가지고 있다.

 

루트는 인덱스 키와 자식 노드의 주소를 가지고 있고

브랜치 또한 인덱스 키와 자식 노드의 주소를,

리프 노드는 해당 인덱스 키가 시작되는 곳의 프라이머리 키를 가지고 있다.

인덱스의 키 값은 모두 정렬되어 있지만 데이터 파일의 레코드는 정렬되어 있지 않다.

 

222p.

innoDB 테이블에서 인덱스를 통해 레코드를 읽을 때는 데이터 파일을 바로 찾아가지 못한다.

인덱스(B-tree 구조)에 저장되어 있는 프라이머리 키 값(정렬되어 있음)을 이용해서 프라이머리 키 인덱스를 한번 더 검색한 후, 프라이머리 키 인덱스의 리프 페이지에 저장되어 있는 레코드를 읽는다.

즉, innoDB 스토리지 엔진에서는 모든 세컨더리 인덱스 검색에서 데이터 레코드를 읽기 위해서는 반드시 프라이머리 키를 저장하고 있는 B-tree를 다시 한번 검사해야 한다.

 

즉 2번의 B-tree를 타는 것이다. 첫 번째 B-tree에서는 페이지의 위치를 찾기 위해서 타고 리프에서 프라이머리 키를 반환한다. 두 번째 B-tree에서는 프라이머리 키를 가지고 다시 다음 페이지를 찾고 리프 노드는 실제 값을 가지고 있는 것이다.

프라이머리 키 까지만 필요하면 b-tree를 한번 타겠지만 레코드까지 필요하면 2번 타게 된다.

 

225p.

innoDB에서의 인덱스는 더 특별한 의미가 있다.

innoDB 테이블에서 지원하는 레코드 잠금이나 넥스트 키락이 검색을 수행한 인덱스를 잠근 후 테이블의 레코드를 잠그는 방식으로 구현돼 있다. 따라서 update나 delete시 적절한 인덱스가 없으면 많은 레코드를 잠글 수 있다. 

 

인덱스의 키값의 크기가 작을수록 읽을 수 있는 페이지는 늘어나고 depth도 줄어든다.

 

227p.

카디널리티, 즉 기수성은 인덱스에서 중복되지 않는 것의 수이다.

100개의 인덱스 중 중복되지 않는 것이 10개라면 카디널리티는 10이다.

이는 인덱스로 잡기 좋지 않은 칼럼이다.

 

레인지 스캔 시 범위를 정하고 그 범위 내에서 랜덤 io가 일어난다.

그래서 인덱스를 통한 io작업은 그냥 io작업보다 비용이 많이 든다.

예로 100만 건 중 50만 건을 읽어야 하는데 인덱스를 사용해 읽는 거보다 풀스 캔을 하며 조건을 걸어주는 것이 더 빠르다.

읽어야 하는 레코드가 20~25%를 넘으면 인덱스를 통한 읽기보다는 테이블의 데이터를 직접 읽는 것이 더 효율적인 처리 방식이 된다.

 

 

인덱스 풀 스캔은 인덱스에 포한된 칼럼만으로 칼럼을 처리할 수 있는 경우에 실행된다.