INDEX
개발자로서 MySQL을 사용한다면
InnoDB Storage에 대해서 이해를 하고 → 동시성 처리를 위해 인덱스 잠금 방식에 대해서 이해하고 있는 것이 기본일 필요가 있다.
먼저 Disk 읽기 방식
하드 디스크 드라이브(HDD)와 솔리드 스테이트 드라이브(SSD)
- 기계식 하드 디스크 드라이브를 대체하기 위해 전자식 저장 매체인 SSD가 많이 출시
- 기존 하드 디스크 드라이브에서 데이터 저장용 플래터를 제거하고 그 대신 플래시 메모리를 장착하고 있음 디스크 원판을 회전시킬 필요가 없으므로 아주 빨리 데이터를 읽고 쓸 수 있음
결론이 무엇인가?
📝 DBMS의 인덱스도 인덱스가 많은 테이블은 당연히 INSERT나 UPDATE, DELETE 문장 처리가 느림
하지만 이미 정렬된 “찾아 보기”용 표를 가지고 있기 때문에 SELECT 문장은 매우 빠르게 처리할 수 있음 그래서 결론적으로, DBMS에서 인덱스는 데이터의 저장(INSERT, UPDATE, DELETE)성능을 희생하고 그 대신 데이터의 읽기 속도를 높이는 기능
INDEX 그러면 무조건 사용하면 좋은가?
📝 SELECT 쿼리 문장의 WHERE 조건절에 사용되는 칼럼이라고 해서 전부 인덱스로 생성하면 데이터 저장 성능이 떨어지고 인덱스의 크기가 비대해져서 오히려 역효과만 불러올 수 있음
📝 데이터 저장 방식 별로 구분할 경우 사실 상당히 많은 분류가 가능하겠지만 대표적으로 B - Tree 인덱스와 Hash 인덱스로 구분할 수 있다. 최근에는 Fractal - Tree 인덱스나 로그 기반의 Merge-Tree 인덱스와 같은 알고리즘을 사용하는 DBMS도 개발되고 있음
B - Tree 인덱스
B-Tree 인덱스는 대표적인 인덱스 알고리즘 중 하나입니다. 이진 트리(Binary Tree)와 유사하지만, 트리의 균형을 맞추기 위한 다양한 구현 방법이 존재합니다. 이 구현 방법들로 인해 B-Tree 인덱스는 대부분의 DBMS에서 사용되고 있습니다. B-Tree 인덱스는 각 노드가 여러 개의 키 값을 가지고 있으며, 이 키 값으로 정렬된 데이터에 대한 탐색을 가능하게 합니다. 이진 트리와 달리, B-Tree 인덱스는 매우 큰 데이터셋에서도 효율적인 탐색을 보장합니다.
📝 구조 및 특성
기본적인 구조는 B - Tree는 트리 구조의 최상위에 하나의 “루트 노드(Root node)” 가 존재하고 그 하위에 자식 노드가 붙어 있는 상태이다. 트리 구조의 가장 하위에 있는 노드를 “리프 노드(Leaf Node)”라고 하고, 트리 구조에서 루트 노드도 아니고 리프 노드도 아닌 중간의 노드를 “브랜치 노드(Branch Node)”라고 한다. 데이터베이스에서 인덱스와 실제 데이터가 저장된 데이터는 따로 관리되는데, 인덱스의 리프 노드는 항상 실제 데이터 레코드를 찾아가기 위한 주솟값을 가지고 있음
- B - Tree 인덱스 키 추가
- 테이블의 스토리지 엔진에 따라 새로운 키 값이 즉시 인덱스에 저장될 수도 있고 그렇지 않을 수도 있다. B - Tree에 저장될 때는 저장될 키 값을 이용해 B- Tree상의 적절한 위치를 검색
- 저장될 위치가 결정되면 레코드의 키 값과 대상 레코드의 주소 정보를 B - Tree 리프 노드에 저장
- 리프 노드가 꽉 차서 더는 저장할 수 없을 때는 리프 노드가 분리돼야 하는데, 이는 상위 브랜치 노드까지 처리의 범위가 넓어짐
- 비용이 높음
- B - Tree 인덱스 삭제
- 해당 키 값이 저장된 B - Tree의 리프 노드를 찾아서 그냥 삭제 마크만 하면 작업이 완료
- B - Tree 인덱스 키 변경
- 단순히 인덱스 상의 키 값만 변경하는 것은 불가능
- 먼저 키 값을 삭제한 후, 다시 새로운 키 값을 추가하는 형태로 처리
- B - Tree 인덱스 검색
- INSERT, UPDATE, DELETE 작업을 할 떄 인덱스 관리에 추가 비용을 감당하면서 인덱스를 구축하는 이유는 빠른 검색을 위해서다. 루트 노드부터 최종 리프 노드까지 이동하면서 비교 작업을 수행 → 이 과정을 “트리 검색”이라고 함
- SELECT 뿐만 아니라 UPDATE, DELETE를 처리하는데도 먼저 검색이 필요할 경우가 있음
MBR
📝 이 사각형들의 포함 관계를 B - Tree 형태로 구현한 인덱스가 R - Tree
전문 검색 인덱스
일반적인 용도의 B - Tree 인덱스를 사용할 수 없음
문서 전체에 대한 분석과 검색을 위한 인덱싱 알고리즘을 전문 검색(Full Text Search) 인덱스
사용자가 검색하게 될 키워드를 분석해 내고, 빠른 검색용으로 사용할 수 있게 키워드로 인덱스를 구축
키워드를 인덱싱하는 기법에 따라 어근 분석과 n - gram 분석으로 분류
어근 분석
- 불용어 처리 (가치가 없는 내용들은 필터링해서 제거하는 작업)
- 어근 분석 ( 오픈 소스를 활용한 형태소 분석 -> 시간과 비용)
n - gram
- 단순히 키워드 검색해 내기 위한 인덱싱 알고리즘
- 보통 2 - gram, 생성된 토큰들에 대해 불용어 처리 + 사용자 정의도 가능
SELECT * FROM 테이블 WHERE doc_body LIKE '%애플%';
SELECT * FROM 테이블 WHERE MATCH(doc_body) AGAINST('애플' IN BOOLEAN MODE);
가상 칼럼을 이용한 인덱스와 함수를 이용한 인덱스
- 가상 칼럼을 추가하여 검색에 대한 효과 : virtual
- 함수를 이용한 인덱스를 통해 테이블의 구조 변경 없이 함수를 직접 사용하는 인덱스를 생성할 수 있음
- 주의 사항 : 함수 생성시 명시된 표현식과 쿼리의 WHERE 조건절에 사용된 표현식이 일치해야함
Multi - Value Index
JSON의 배열 타입의 필드에 저장된 원소들에 대한 인덱스 요건들이 발생
EX) 몽고 DB -> JSON 형태로 데이터를 보여주고 저장, 검색기능을 사용할때도 JSON 문법에 맞게 출력해줌
MySQL -> JSON 타입의 칼럼만 지원했지만 8.0넘어오면서 JSON 관리 기능이 MongoDB에 비해서도 부족함이 없는 상태
- MEMBER OF()
- JSON_CONTAINS()
- JSON_OVERLAPS()