4. InnoDB 인덱스 및 알고리즘

열 주소 :

MySQL 시리즈 기사 칼럼



1. 공통 인덱스 모델

인덱싱의 목적은 데이터 쿼리 및 검색의 효율성을 높이는 것입니다. 일반적인 인덱스 모델은 해시 테이블, 정렬 된 배열 및 검색 트리 입니다.

해시 테이블

해시 테이블은 데이터를 키-값 형식으로 저장합니다. 저장 구조가 정렬되어 있지 않기 때문에 해시 인덱스는 범위 쿼리, 인덱스 완성 정렬 등에 적합하지 않지만 동등한 쿼리 시나리오에서는 절대적인 이점이 있습니다.

Redis ZSET에서는 해시 테이블을 기반으로 점프 테이블 구조가 추가되어 해시 액세스와 빠른 범위 쿼리를 모두 지원할 수 있습니다.

정렬 된 배열

정렬 된 배열은 동등한 쿼리 및 범위 쿼리 시나리오 모두에서 뛰어난 성능을 제공하며 시간 복잡성은 O (lgN)에 도달합니다. 그러나 데이터 추가 및 삭제 비용이 너무 높고 정적 스토리지 엔진에만 사용됩니다.

트리 검색

이진 트리의 특성은 다음과 같습니다. 각 부모 노드는 왼쪽 아들보다 크고 오른쪽 아들보다 작습니다. 쿼리의 시간 복잡도는 O (lgN)입니다. O (lgN) 쿼리 복잡도를 유지하려면이 트리를 균형 잡힌 이진 트리로 유지해야하므로 업데이트 작업도 O (lgN)입니다.

검색 트리에는 여러 분기가있을 수 있으며 자식 노드는 왼쪽에서 오른쪽으로 계속 증가합니다.

바이너리 트리의 검색 효율은 가장 높지만 데이터베이스 인덱스에서는 거의 사용되지 않는데, 그 이유는 인덱스가 메모리에있을뿐만 아니라 디스크에도 기록되기 때문입니다. IO 수를 줄이려면 쿼리 프로세스 중에 가능한 한 적은 수의 데이터 블록에 액세스해야합니다.

2. B + 트리 인덱스

B + Tree는 하드 디스크 또는 기타 외부 저장 소용으로 설계된 균형 잡힌 다중 경로 검색 트리 입니다 . 균형 잡힌 이진 검색 트리에 비해 B + Tree는 다중 트리 이고 각 노드는 여러 요소를 저장하며 높이가 낮아 효과적으로 줄일있습니다. IO 시간 .

MyISAM 엔진과 InnoDB는 모두 B + Tree를 인덱스 구조로 사용합니다. 차이점은 MyISAM 인덱스와 데이터가 분리되어 데이터의 주소가 B + 트리에 저장된다는 점입니다 .InnoDB에서는 테이블 데이터가 B + Tree에 따라 구성되고 리프 노드가 저장됩니다. 데이터 레코드의 경우이 테이블 구조를 인덱스 구성 테이블이라고합니다. 데이터베이스에서 B + Tree의 높이는 일반적으로 2 ~ 4 계층이며 쿼리 작업에는 2 ~ 4 배의 IO 만 필요합니다.

2.1 B- 트리 순서 배열 + 균형 잡힌 다중 트리

  1. m 차의 B + 트리에는 최대 m 개의 자식 노드와 노드 당 m-1 개의 키가 있습니다. (PS : m-1 키는 m 간격으로 나뉘며, 자식 노드는 부모 노드의 기존 요소가 나타나지 않으며 각 노드 요소는 한 번만 나타납니다. )
  2. 루트 노드와 리프 노드를 제외하고 각 노드에는 최소 m / 2 개의 자식 노드가 있습니다.
  3. 각 노드의 요소는 가장 작은 것부터 가장 큰 것까지 정렬됩니다.

여기에 사진 설명 삽입

2.2 B + 트리 순서 배열 + 연결 목록 + 균형 다중 분기 트리

  1. 노드 요소에는 동일한 수의 자식이 있습니다. (M 순서, m 요소, m 자식 노드)
  2. 상위 노드는 각 하위 트리의 최소값을 보유합니다 .
  3. 리프 노드가 모든 요소를 ​​저장 한다는 것을 2에서 알 수 있습니다 .
  4. 리프 노드는 포인터로 연결됩니다 (이중 연결 목록).

여기에 사진 설명 삽입

여기에 사진 설명 삽입

2.3 비교

B- 트리의 각 요소는 한 번만 나타나는 반면 B + 트리의 모든 요소는 리프 노드에 나타납니다. 따라서 B-Tree는 각 노드에 데이터를 저장해야하는 반면 B + Tree는 리프 노드에만 데이터를 저장하면 되므로 B + Tree의 내부 구조는 더 작고 순서는 더 커질 수 있습니다 . 추가 지원의 무작위 검색을 제외하고 B + 트리는 순차적 검색을 지원합니다 . B + Tree의 질의 효율은 더 안정적이며, 모든 요소에 대한 검색은 루트 노드에서 리프 노드로 이루어져야하며 경로 길이는 동일합니다.

2.4 B + 트리 작업

인덱스의 질서를 보장하기 위해 B + 트리는 인덱스가 변경 될 때 필요한 유지 관리가 필요합니다.

찾기

이진 트리 검색과 유사하게 이진 검색은 노드 내에서 사용됩니다.

증가하다

인덱스를 임의로 삽입하면 현재 데이터 페이지가 가득 차면 페이지 분할 이 발생합니다 . 새 데이터 페이지에 적용한 다음 데이터의 일부를 새 데이터 페이지로 이동합니다. 페이지 분할은 성능 손실 (디스크 작업 포함)을 유발하고 페이지 사용량도 감소시킵니다. InnoDB는 페이지 분할을 줄이기 위해 형제 노드가 꽉 찼을 때 회전 작업을 수행하고 레코드를 형제 노드로 전송합니다.

추가하면 페이지 분할이 발생하지 않지만 임의 삽입과 마찬가지로 부모 노드에 노드를 삽입하면 B + 트리가 위쪽으로 커집니다. 부모 노드 수도 초과되고 B + 트리가 높아집니다.

지우다

인접한 두 페이지가 삭제되고 사용률이 낮아지면 데이터 페이지가 병합됩니다. InnoDB는 채우기 비율을 사용하여 트리의 삭제 변경을 제어합니다.

2.5 InnoDB가 B + 트리를 선택하는 이유

B + Tree는 외부 메모리에 대한 임의 액세스를 위해 설계된 균형 잡힌 다중 경로 검색 트리입니다.

이진 트리와 비교할 때 각 노드는 더 많은 요소를 저장할 수 있고 각 IO는 더 많은 요소를 읽을 수 있습니다. 따라서 트리의 높이가 더 낮고 더 적은 IO가 필요합니다.

B-Tree와 비교할 때 B + Tree는 리프 노드에만 데이터를 저장하고 내부 구조가 더 콤팩트하고 순서가 더 크므로 IO 수가 적습니다 .B + Tree 쿼리 효율성이 더 안정적이며 순차 검색도 지원합니다.

그러나 루트 노드에 더 가까운 자식 노드의 경우 자식 노드에 Key와 Value (데이터 주소)가 모두 포함되어 있으므로 B-Tree가 더 빠르므로 리프 노드에 액세스 할 필요가 없습니다.

3. 인덱스 구성 테이블

InnoDB의 테이블 데이터는 기본 키에 따라 구성된 B + 트리로,이 저장 방식을 인덱스 구성 테이블이라고하며 기본 키 인덱스 트리의 리프 노드는 전체 데이터 레코드를 저장합니다.

3.1 클러스터형 인덱스

클러스터형 인덱스 (클러스터형 인덱스)는 테이블에있는 데이터의 저장 구조를 정의하며 InnoDB의 기본 키 인덱스는 클러스터형 인덱스라고도합니다.

InnoDB는 테이블에 기본 키가 있어야합니다 (MyISAM은 그렇지 않을 수 있음). 그렇지 않은 경우 InnoDB는 레코드를 기본 키로 고유하게 식별 할 수있는 열 (비어 있지 않은 고유 키)을 자동으로 선택합니다. 존재하지 않으면 6 바이트 숨겨진 필드 rowid를 기본 키로 생성합니다.

InnoDB에 기본 키가 있어야하는 이유 :

  1. 스토리지 구조는 인덱스로 구성된 테이블입니다.
  2. 테이블에 대한 보조 인덱스는 레코드를 쿼리하기 위해 기본 키를 사용해야합니다.

3.2 2 차 지수 (보조 지수)

비 기본 키 인덱스는 보조 인덱스라고도하며 리프 노드는 보조 인덱스와 해당 클러스터형 인덱스, 즉 기본 키를 저장합니다. InnoDB는 인덱스 정의 필드 뒤에 기본 키 필드를 배치하고 중복 제거하기도합니다. 기본 키 열 (복합 인덱스)의 일부에 이미 보조 인덱스가 포함되어있는 경우 해당 열은 반복적으로 기록되지 않습니다.

쿼리에 보조 인덱스를 사용하는 경우 쿼리에 기본 키를 사용하는 것과 비교하여 추가 테이블 백 작업이 필요합니다. 기본 키를 얻은 후 클러스터형 인덱스 트리에서 검색이 수행됩니다.

커버링 인덱스를 사용하면 반환 테이블 수를 줄일 수 있습니다. 동시에 InnoDB는 반환 테이블 수와 오버 헤드를 줄이기 위해 인덱스 푸시 다운MRR도입 합니다. 전자는 일부 쿼리 조건 (인덱스 및 기본 키에 포함 된 열)을 엔진 계층으로 푸시하고 InnoDB는 테이블을 반환합니다. 전자가 먼저 필터링되고 후자는 임의 IO를 줄이기 위해 테이블로 돌아 가기 전에 기본 키를 정렬합니다 (테이블 반환은 여전히 ​​행별로 기본 키 쿼리 임).

3.3 B + 트리가 저장할 수있는 데이터 양

InnoDB는 B + 트리를 스토리지 데이터 구조로 사용하는데, 이는 외부 메모리 랜덤 IO에 최적화 된 균형 잡힌 다중 경로 검색 트리이며 "N-ary"트리입니다. N의 크기는 데이터 페이지 및 인덱스의 크기에 따라 다릅니다.

InnoDB에서 데이터 페이지의 주소 포인터는 6 바이트이고 압축 된 페이지가 켜지지 않을 때 데이터 페이지의 크기는 16k입니다. 기본 키 인덱스가 8 바이트 bigint 유형을 사용한다고 가정하면 각 인덱스는 약 14 바이트를 차지합니다. B + 트리의 리프가 아닌 노드에서 데이터 페이지의 고정 오버 헤드를 무시하고 각 데이터 페이지는 약 16,384➗14 = 1170 개의 인덱스를 저장할 수 있으며 이는 1024 개로 추정됩니다.

각 레코드의 크기가 1k라고 가정하면 리프 노드의 각 데이터 페이지는 16 개의 레코드를 저장할 수 있습니다.

높이가 3 인 B + 트리는 크기가 1024 1024 16KB = 16GB 인 레코드 1024 1024 16 = 1677216 개를 저장할 수 있습니다 .

따라서 InnoDB에서 B + 트리의 높이는 일반적으로 1 ~ 3 개의 레이어로 수천만 개의 데이터 저장 공간을 만족시킬 수 있습니다. 데이터를 검색 할 때 페이지의 한 검색은 하나의 IO를 나타내므로 기본 키 인덱스 쿼리는 일반적으로 데이터를 찾는 데 1-3 개의 IO 작업 만 필요합니다 . 트리의 루트에있는 데이터 페이지가 일반적으로 메모리에 있다는 점을 고려할 때 IO의 수는 더 적습니다.

4. 해시 인덱스

InnoDB의 전체 아키텍처 및 핵심 기술에서 적응 형 해시 인덱스 AHI를 참조하십시오.

5. 전체 텍스트 검색

전체 텍스트 검색은 반전 된 인덱스를 사용하여 구현됩니다. 반전 된 인덱스는 단어에 따라 단어가 포함 된 문서 행렬을 빠르게 얻을 수 있으며 일반적인 형식은 키 = 단어, 값 = 문서 ID + 단어 위치입니다.

InnoDB는 반전 된 인덱스를 보조 테이블에 저장하며 병렬성을 개선하기 위해 여러 보조 테이블이 사용됩니다.

MySQL은 전체 텍스트 검색을 위해 MATCH ( 'Col Name') AGAINST ( 'Search')를 사용하며 결과 집합은 관련성 내림차순으로 정렬됩니다. 관련성은 문서에 단어가 나타나는지 여부, 단어가 나타나는 횟수 및 단어가 포함 된 다른 문서 수와 같은 요소를 기반으로 계산됩니다.

추천

출처blog.csdn.net/cooper20/article/details/108636464