## 8.4 R-Tree 인덱스
- Rectangle Tree
- MBR: Minimum Bounding Rectangle
- Spatial Index (공간 인덱스) 라고 부르기도 함
- 반면 B-Tree 는 Scalar Index 임
- RDBMS 에서의 스칼라와 벡터
- 스칼라 : 값
- 벡터 : 값 사이의 콜릴레이션(방향?)
### 8.4.1 구조 및 특성
- 모든 도형(삼각형, 사각형, 다각형)
- R-Tree 인덱스와 B-Tree 인덱스 사이의 차이는 저장하는 데이터의 차이
- 어떤 도형을 감싸는 최소 크기의 사각형으루 변환
### 8.4.2 R-Tree 인덱스의 용도
- 사용예시 : 공간관련, 두 점 사이의 거리가 중요한 경우
- aribnb 서비스 : 거리
- 카카오택시
- 포켓몬고
- 아이작 리포 링크 : https://github.com/janeljs/airbnb/issues/97
- 포인트 : 한점에서 반경 N거리 사이의 뭔가를 찾기
- mysql 아니고 다른 DB 쓰는경우도 있음
- 엘라스틱서치에 편리한거 많음..
## 8.5 전문 검색 인덱스
- 전문검색 : 문서 내용 전체를 인덱스화해서 키워드가 포함된 문서 검색
### 8.5.1 인덱스 알고리즘
- 두가지로 나뉘며
- 어근분석
- n-gram 알고리즘
#### 8.5.1.1 어근분석
- 언어별로 차이가 많다
- MeCab 일본어용
- 동양어? 일본어/한글 어근분석보다는 형태소 분석해서 명사/조사 구분 기능이 더 중요
- 사전이 필요하다.. : 학습
- 예시
- (범주/뛰어가다, 뛰어가서, 뛰다보니..) >> (어근)뛰다 >> 여기에 연결된것들이 검색됨
#### 8.5.1.2 n-gram
- 문장을 이해하는 알고리즘
- 키워드 검색을 위한 인덱싱
- 예시 (n=2)
- 뛰어가다 >> 뛰어, 어가, 가다
#### 8.5.1.3 불용어 변경 및 삭제
- 의미없는 불용어 필터링
- 사용자가 직접 등록할수 있다.
### 8.5.2 전문 검색 인덱스의 가용성
- 사용하기 위한 두가지 조건
- 쿼리 문장이 전문검색위한 문법 사용
- 인덱스를 보유해한다
- (추가내용)**MySQL InnoDB full text index 는 inverted index 를 갖는다** @todo질문
- https://dev.mysql.com/doc/refman/8.0/en/innodb-fulltext-index.html#innodb-fulltext-index-design
- 더 알아보기
- ES 인버티드 인덱스
- ELK 기술스텍
- 코퍼스(말뭉치)
- 언어 올림피아드..
## 8.6 함수 기반 인덱스
- 함수 기반 인덱스 구현방법
- 가상 칼럼을 이용한 인덱스
- 함수를 이용한 인덱스
- B-Tree 와 동일하다 구조 및 유지관리 방법에는
### 8.6.1 가상 칼럼을 이용한 인덱스
- 인덱스는 걸려있는데, 인덱스 걸린값이 컬럼에는 저장되어있지 않음
- 사용자 입장에서는 안보이고, 내부적으로는 알아서 추가할지도??
- 데이터 정합성을 맞추기 위해서 필요해보임
- Full-N = first-N + last-N
- 15.8절에서 가상컬럼(파생컬럼) 에서 더욱 자세히 학습예정
- 스토어드, 버츄얼 : 성능상의 차이를 그떄 공부해보자
@todo질문
### 8.6.2 함수를 이용한 인덱스
- 테이블의 구조를 변경하지 않고 함수를 직접 사용하는 인덱스
## 8.7 멀티 밸류 인덱스
- JSON, 잘 지원한다.
## 8.8 클러스터링 인덱스
- 클러스터링
- 여러개를 하나로 묶는다!
- 레코드들이 PK 별로 묶어서 File에 저장되는 형태
- PK가 비슷한 인근값들을 동시에 조회하는 경우가 확률상 높기 때문
- 다른 스토리지 엔진(MyISAM 등등..) 에서는 지원되지 않는다
- 면접질문 : InnoDB 랑 다른 스토리지 엔진이랑 차이에 대해 알고 계신가요
### 8.8.1 클러스터링 인덱스
- 클러스터링 인덱스
- InnoDB 스토리지 엔진에서 사용
- PK가 비슷한 인근 레코드들끼리 묶여서 같은 File 에 저장되는 방식
- 뒤집어서 말하면 PK값에 의해서 레코드의 저장 위치가 결정되고, PK가 변경되면 저장되는 File의 위치가 변경된다
- 인덱싱 알고리즘이 아니라 데이블 레코드의 저장방식
- (장점) PK 검색속도가 매우 빠르다, select 성능이 좋다
- (단점) 저장이나(insert), PK 변경이 상대적으로 느리다(update PK)
- B트리 인덱스 VS 클러스터링 인덱스 차이가 뭔가요
- B트리 인덱스 : 인덱스가 Key 순서로 정렬되어 저장
- 클러스터링 인덱스 : 인덱스가 Key 순서로 정렬되어 저장 + PK이어야 함 + 레코드도 PK 순서로 File에 저장되어 있음
- 한줄요약 : 클러스터링 인덱스 = B트리인덱스 + PK임 + 레코드도 동일한 순서로 저장
> 클러스터링 인덱스 장점
- PK가 저장되는 파일위치가 된다!!
- PK 를 변경하면 일어나는 일
- 사진으로 대체
- PK 가 없는경우?
- PK가 없으면 InnoDB는 저장하지 못한다. 그래서 PK를 대체할 컬럼을 선택하고 그 우선순위는
```
1. PK 있으면 PK를 클러스터링 키
2. NOT NULL + unique 컬럼들 중 첫번째 인덱스 (첫번째로 생성되는 인덱스라는 의미인듯?)
3. 내부적으로 PK 추가 (NOT NULL + unique + Auto increment 한 컬럼을 알아서 만듬)
```
- 프라이머리 키를 명시적으로 생성하자! : InnoDB 테이블에서 테이블당 단 하나만 가질수 있는 엄청난 혜택
#### 클러스터링 인덱스 from 데이터베이스 시스템
- ~클러스터링 필드라고 한다~
- 클러스터드 인덱스 컬럼 : 레코드가 해당 인덱스 순서로 정렬이 되어서 저장되어 있다!
- MySQL 은 PK 를 기준으로~~
### 8.8.2 세컨더리 인덱스에 미치는 영향
- Quiz) PK랑 NN UNIQUE INDEX 랑은 차이가 뭐가 있나요?
- Dong : 어..없지 않을까요...?
- 정답 : 스토리지엔진별로 차이가 있어요
- MyISAM , MEMORY 엔진 사용 테이블은 아무런 차이가 없다
- InnoDB 엔진 테이블 에서는
- NN UNIQUE INDEX 는 인덱스중 하나일뿐이고
- PK 는 인덱스이면서 동시에 PK 기준으로 정렬되어 파일에 저장되어 있기 때문에 특별
- 274페이지 실습(해봐야함)
### 8.8.3 클러스터링 인덱스의 장점과 단점
| | 특징 | 장점 | 단점 |
| -- | -- | --- | --- |
|1| 테이블의 모든 세컨더리 인덱스가 프라이머리 키를 가지고 있기 때문에 | 인덱스만으로 처리될수 있는 경우가 많음 (커버링인덱스) | 클러스터링 키 값의 크기가 클 경우 모든 인덱스의 크기가 같이 커짐 |
|2| 인덱스를 활용한 검색 | PK 검색시 매우빠름 ,특히 PK기준 범위검색 | 세컨더리 인덱스를 통해 검색해도 결국은 PK로 검색해야하므로 비교적 처리가 느림 |
|3| insert | | 프라이머리 키에 의해 레코드가 저장되는 파일의 위치가 결정됨 |
|4| update PK | | PK 업데이트시 : delete >> insert 하기 때문에 처리성능이 느림 |
- 4번 항목(update PK) 의 경우, RDB 에 올라가는 데이터를 delete 날리는 경우는 거의 없고 대부분 log 성으로 쌓는 usecase 가 대부분이 때문에 큰 문제는 아닐꺼같습니다.
- 275p 1/3 지점 : 일반적인 웹서비스와 온라인 트랜잭션 환경에서는 읽기 비율이 80~90% 정도이므로, PK 기준의 읽기속도가 빠른 InnoDB 가 성능이 좋습니다
- 1번 항목이 클러스터링 인덱스를 설명할때 꼭 들어가야하는 내용이라고 생각합니다
- 케이 && 어거스트 생각
- PK 로만 검색하는것보다는 다른 인덱스 타고 검색하는 경우가 많은데, 이런 상황에서는 성능저하 이슈
- 인조키 VS 자연키 : mysql 자연키로 검색할때, 앞에 LEFT 가 일치해야 하는 또 제약조건
- 예시) 자연키로 주민등록번호 가 PK 일때 (880603)
- 출생년도로 검색 : 인덱스 탐(88XXXX)
- 출생월로 검색 : 인덱스 X (XX06XX) : 비지니스 로직에 의미가 있음
- 출생 일로 검색 : 인덱스 X (XXXX03)
- 검색에 한해서는 ES 사용하는게 좋을꺼같음 PK 통짜로 검색하는 경우가 적음!
- 그럴바에는 안전성있는 인조키 쓰는게 안전쓰..
- 트랜잭션, 데이터 정합성이 필요 없다면 >> 해시인덱스 더욱 매력적..
### 8.8.4 클러스터링 테이블 사용 시 주의사항
- 클러스터링 엔진을 사용하는 테이블에서 주의사항
#### 8.8.4.1 클러스터링 인덱스 키의 크기
- PK 가 커지면 >> 다른 세컨더리 인덱스 전체도 크기가 커진다
- 왜냐하면 클러스터링 테이블의 경우 모든 세컨더리 인덱스가 PK 값을 가지고 있기 때문
- 인덱스가 커지면 같은 성능을 내기 위해 메모리또한 더 커져야하므로 InnoDB 테이블의 프라이머리 키는 신중하게 선택해야합니다
#### 8.8.4.2 PK를 업무적인 컬럼으로 선택하는 경우(자연키)
- 자연키를 사용할수 있고, 검색에 빈번하게 사용하는 경우 자연키를 PK로 선택하자.
- 설정 그 칼럼의 크기가 크더라도 업무적으로 해당 레코드를 대표할수 있다면! 자연키가 BEST
- 의견)
- 자연키가 아니더라도 인공적으로 의미를 나타낼수 있다면?
- 상품분류코드의 경우
- PK = (대분류+중분류+소분류)+유니크
- or 대분류,중분류,소분류 각각을 모두 세컨더리 인덱스로 가져가는 경유
- trade-off : PK 커지면 >> 모든 인덱스가 같이 증가한다
- PK 자연키가 위험한 이유
- 카테고리별로 조회하는 경우가 많다.. (PK의 일부가 의미를 갖는 경우)
- PK의 일부가 상위도메인으로 올라가는 경우
- 도메인 요구사항이 변경되는 경우
- 레딧 설계 : 스키마 두개로 끝남
- 외래키 거느냐 마느냐 : 외래키 거는 단점
- 설계가 완벽하지 않을수 있다 @@@
- 기술부채 : 미사용 컬럼 삭제
#### 외래키의 위험한
- 두 테이블간의 강력한 (데이터)의존성
- 두 객체 사이의 커플링, 결합도
- 최근 트렌드는 MSA 라서 의존성 낮추는게 좋음
- RDBMS 에 모든 데이터를 집중하기엔 스케일업이 어려움 : 샤딩
- 유지보수가 진짜 어렵다
- 코드랑 설계랑 따로논다 >> 문서가 없을수도
- 코드랑 문서랑 따로논다
#### 8.8.4.3 PK는 꼭 명시하자
- 어차피 사용자가 명시적으로 생성하지 않아도 InnoDB 는 내부적으로 PK컬럼을 만들어낸다
- ROW 기반 복제 ??
- 정상적인 복제를 위해서는 PK가 필요하다??
#### 8.8.4.4 PK에 인공키 (AUTO-INCREMENT)
- 로그테이블로 INSERT 위주의 테이블들은 AUTO-INCREMENT 이용하면 도움이 된다
- 여러개의 컬럼이 복합으로 프라이머리 키가 만들어지는 경우 프라이머리 키가 길어질 떄가 가끔 있다 >> 이런경우 인공키를 써라
## 8.9 유니크 인덱스
- INDEX 없이 유니크 제약을 설정하는건 불가능하다(insert 성능이 최소 O-n)
### 8.9.1 유니크 인덱스와 일반 세컨더리 인덱스의 비교
#### 8.9.1.1 유니크 인덱스 읽기
- 유니크 인덱스와 유니크하지 않은 인덱스 사이에 성능차이는 크지 않다
- 왜냐하면 해당작업은 CPU 작업이니까! DB 성능은 DISK IO 줄이기 싸움
#### 8.9.1.2 유니크 인덱스 쓰기
- 인덱스 쓰기에서는 유니크 제한이 쓰기성능이 더 느리게 동작(유니크 인덱스는 쓰기성능이 나쁘다)
- 쓰기동작에서 중복인지 아닌지를 체크하기 위해 락이 걸린다
- 버퍼링도 할수 없다.
### 8.9.2 유니크 인덱스 사용 시 주의사항
- 도메인관점에서 비지니스 로직에 꼭 필요한 경우에만 유니크 제약을 추가하자
## 8.10 외래키
- 외래키 제약이 설정되면 연관테이블에 컬럼에는 인덱스가 자동으로 생긴다
### 8.10.1 자식 테이블의 변경이 대기하는 경우
- 자식 테이블의 외래키 컬럼의 변경은 부모테이블의 확인이 필요하고
- 이 상태에서 부모 테이블의 해당 레코드가 쓰기 잠금이 걸려있으면 해제시까지 대기한다
- 자식테이블의 외래키아닌 컬럼은 그런거 없다 잠금도 대기도 없다
### 8.10.2 부모 테이블의 변경 작업이 대기하는 경우
- 체크를 위해 연관 테이블 읽기 잠금이 걸린다
- 트랜잭션이 다른 테이블로 확장(전파된다) >> 트랜잭션 범위가 너무 커지는 문제 발생
> 끝!