## 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 부모 테이블의 변경 작업이 대기하는 경우 - 체크를 위해 연관 테이블 읽기 잠금이 걸린다 - 트랜잭션이 다른 테이블로 확장(전파된다) >> 트랜잭션 범위가 너무 커지는 문제 발생 > 끝!