MySQL 고급 인덱스 (매우 상세 !!!)

1. 인덱스 란 무엇입니까?

색인은 사전의 디렉토리와 같습니다.
우리는 보통 디렉토리로 가서 주요 부수 나 문자를 찾은 다음 조회합니다.
사전을 직접 조회하는 것보다 훨씬 빠릅니다.
여기에 사진 설명 삽입

2. 인덱스가 있어야하는 이유는 무엇입니까?

하지만 mysql 데이터베이스를 사용하면 인덱스가있는 사전처럼 쿼리하기도합니다.

2.1 질문 :

1. mysql 데이터는 어디에 저장됩니까?

디스크

2. 데이터 쿼리 속도가 느립니다. 일반적으로 어디에서 멈추나요?

나는

3. 데이터를 읽기 위해 디스크로 이동합니다. 읽는 데 얼마나 사용됩니까?

디스크 미리 읽기

지역성의 원칙 : 데이터와 프로그램은 함께 클러스터링되는 경향이 있으며 이전에 방문한 데이터는 다시 쿼리 될 가능성이 높습니다. 공간적 지역성, 시간적 지역성

디스크 미리 읽기 : 메모리와 디스크간에 데이터 상호 작용이있을 때 일반적으로 가장 작은 논리 단위 인 페이지가 있습니다. 페이지 크기는 일반적으로 운영 체제 (4k 또는 8k)에서 고려되며 데이터와 상호 작용할 때 페이지의 정수 배수를 사용하여 읽을 수 있습니다.

innodb 스토리지 엔진은 매번 데이터를 읽고 16k를 읽습니다.

4. 색인은 어디에 저장됩니까?

디스크, 데이터를 쿼리 할 때 인덱스가 먼저 메모리에로드됩니다.

5. 인덱스를 저장할 때 어떤 정보가 필요합니까? 어떤 필드 값을 저장해야합니까?

키 : 실제 데이터 행에 저장된 값

파일 주소

오프셋 : 오프셋

6.이 형식으로 데이터를 저장하려면 어떤 종류의 데이터 구조를 사용해야합니까?

키-값

해시 테이블, 트리 (바이너리 트리, 레드-블랙 트리, AVL 트리, B 트리, B + 트리)

7. mysql 인덱스 시스템이 방금 언급 한 형식으로 저장되지 않은 이유는 무엇입니까?

OLAP : 온라인 분석 처리 ---- 대량의 과거 데이터를 분석하고 의사 결정 전략 생성 ---- 데이터웨어 하우스 -Hive

OLTP : 온라인 트랜잭션 처리-해당 결과를 반환하는 데 매우 짧은 시간 필요-데이터베이스-관계형 데이터베이스 (mysql, oracle)

세, mysql 인덱스 데이터 구조

3.1 해시 테이블 :

여기에 사진 설명 삽입
HashMap 배열 및 연결 목록의 구조는 인덱싱 이유에 적합하지 않습니다.

1. 해시 충돌은 데이터 해싱을 고르지 않게 만들고 많은 수의 선형 쿼리를 생성하며 시간을 낭비합니다.

2. 범위 질의는 지원하지 않으며, 범위 질의를 수행 할 때는 하나씩 순회해야합니다.

3. 메모리 공간에 대한 요구 사항이 상대적으로 높습니다.


장점 : 동등한 쿼리 인 경우 매우 빠름


mysql에 해시 인덱스가 있습니까?

1. 메모리 저장 엔진은 해시 인덱스를 사용합니다.

2. innodb는 적응 형 해시를 지원합니다.

create table test(id int primary key,name varchar(30))
engine='innodb/memory/myisam'
-- 5.1之后默认innodb

3.2 나무 :

트리와 같은 많은 데이터 구조가 있으며 일반적인 것은
이진 트리, BST, AVL, 레드-블랙 트리, B 트리, B + 트리입니다.

① 바이너리 트리 : 순서없는 삽입
여기에 사진 설명 삽입
이것은 우리 트리의 구조도이지만 바이너리 트리의 데이터 삽입은 순서가 없어서 찾을 필요가있을 때 여전히 하나씩 탐색하고 찾아야 함을 의미합니다.

②BST (Binary Search Tree) :
삽입 된 데이터가 순서대로 정렬되고, 왼쪽 서브 트리는 루트 노드보다 작아야하며, 오른쪽 서브 트리는 루트 노드보다 커야합니다 .-------- 효율성을 높이기 위해 바이너리 검색을 사용합니다
여기에 사진 설명 삽입
. . 당신은 쿼리 데이터하려면 이진 검색은 시간 복잡도를 범위를 좁히고 감소 빠르게하는 데 사용할 수 있습니다
그러나, 삽입 순서를 오름차순 또는 내림차순의 경우, 같은 될 것 나무의 모양은 다음과 같습니다
여기에 사진 설명 삽입
이 때, 이진 검색 트리는 연결 목록으로 퇴화되고 시간 복잡도는 O (n)이됩니다.

③AVL : Balanced Binary Tree
위의 문제를 해결하기 위해 왼쪽 또는 오른쪽으로 회전하여 트리를 균형을 잡습니다.
가장 짧은 서브 트리와 가장 긴 서브 트리는 높이가 1을 초과 할 수 없습니다
여기에 사진 설명 삽입
. 그림에서 볼 수 있듯이 순차적으로 삽입하면 자동으로 회전합니다. 균형을 이루기 위해
성능 손실을 삽입하여 쿼리 성능 향상을 보상합니다.

데이터를 많이 삽입하고 쿼리가 매우 작 으면 삽입 된 데이터가 회전하므로 많은 시간.
④ 레드 - 블랙 트리 (해결 읽고 요청의 같은 수의 쓰기)
도 좌우 회전을 통해 나무를 균형 및 색상을 변경하는 동작입니다.
긴 하위 트리를 두 번 짧은 서브 트리를 초과하지 않는 .
여기에 사진 설명 삽입
쿼리 성능과 삽입 성능은 거의 균형을 이루고
있지만 데이터가 삽입되면 트리가 발견됩니다. 트리의 깊이가 깊어지고 트리의 깊이가 깊어 지므로 IO 시간이 늘어날수록 데이터 읽기의 효율성이 영향을받습니다.

⑤ B- 트리
과도한 데이터 삽입 및 트리 깊이 심화 문제를 해결하기 위해 B-tree
사용 하여 원래 순서대로 정렬 된 이진 트리를 정렬 된 다중 트리로 변환합니다.
여기에 사진 설명 삽입
예 : 쿼리를 원하는 경우 * id = 14 인 테이블?

  1. 첫 번째 단계는 디스크 1을 메모리에로드하고 14 <16을 찾은 다음 주소 디스크 2를 찾는 것입니다.
  2. 두 번째 단계는 디스크 2를 메모리에로드하고 14> 11을 찾은 다음 주소 디스크 7을 찾는 것입니다.
  3. 세 번째 단계는 디스크 7을 메모리에로드하고, 14 = 14를 찾고, 데이터를 읽고, 데이터를 꺼내고,
    생각을 끝내는 것 입니다. B- 트리가 완벽합니까?
    질문 1 : B- 트리는 범위 쿼리의 빠른 검색을 지원하지 않습니다. 데이터 범위를 쿼리하고 범위의 경계를 찾으면 루트 노드로 돌아가서 검색을 다시 탐색해야합니다. 다중 탐색이 필요합니다. 루트 노드에서 시간, 범위를 찾으더라도 다른 경계, 쿼리 효율성이 감소합니다.
    질문 2 : 데이터가 행 레코드를 저장하는 경우 열 수가 증가함에 따라 행 크기가 증가합니다. 이때 한 페이지에 저장할 수있는 데이터의 양이 줄어들고 트리가 그에 따라 더 커지며 디스크 IO의 수가 증가합니다.
    생각 2 : 3 단계 B- 트리는 몇 개의 레코드를 저장할 수 있습니까?
    답변 : 데이터가 1k라고 가정하면 innodb 스토리지 엔진은 한 번에 16k 데이터를 읽고 세 계층은 16 16 16 = 4096입니다.
    하지만 개발 중에는 테이블의 데이터가 4096보다 훨씬 큽니다. 레이어를 추가하려면 IO가 증가하지 않을까요?

4. B + 트리를 사용하는 이유는 무엇입니까?

실제로 테이블 데이터를 저장할 때 어떻게 저장합니까?

전체 데이터 행
변환 B + 트리 B + 트리는
여기에 사진 설명 삽입
B 트리를 개선하여 모든 데이터를 리프 노드에 배치하고 리프 노드 간의 양방향 포인터 연결을 사용하여 가장 낮은 리프 노드는 양방향 순서 연결 목록을 형성합니다.
예 : 쿼리 범위 select * from table where id between 11 and 35?

  1. 첫 번째 단계는 디스크를 메모리에로드하고 11 <28을 찾은 다음 주소 디스크 2를 찾는 것입니다.
  2. 두 번째 단계는 디스크 2를 메모리에로드하고 10> 11> 17을 찾아 주소 디스크 5를 찾는 것입니다.
  3. 세 번째 단계는 디스크 5를 메모리에로드하고 11 = 11, 데이터 읽기
  4. 네 번째 단계는 오른쪽으로 계속 쿼리하고, 디스크 5를 읽고, 35 = 35를 찾고, 11-35 사이의 데이터를 읽고, 끝
    이 범위 쿼리가 B- 트리보다 훨씬 빠르다는 것을 알 수 있습니다.

B- 트리와 B +-트리를 비교 하시겠습니까?

  • 리프 노드에만 데이터 저장

  • 리프가 아닌 노드에는 데이터가 저장되지 않습니다.

  • B + 트리의 각 노드에는 더 많은 노드가 포함되어 있습니다. 장점은 트리의 높이를 줄일 수 있고 데이터 범위를 여러 간격으로 변경할 수 있다는 것입니다. 간격이 많을수록 쿼리 속도가 빨라집니다.

질문 : 인덱스를 만들 때 int 또는 varchar를 사용합니까?

답변 : 상황에 따라 다르지만 키는 최대한 작게 만들어야합니다.

다섯, 인덱스 생성

인덱스를 생성하기 전에 스토리지 엔진
스토리지 엔진 에 대해 말씀 드리겠습니다 . 디스크에있는 서로 다른 데이터의 다양한 표현을 나타냅니다.
mysql 디스크 파일을 보면
innodb 를 찾을 수 있습니다 . innodb 데이터와 인덱스가 하나의 파일에 저장됩니다. . IDB
의 MyISAM : 의 MyISAM의 인덱스는 .MYI 파일에 저장되고, 데이터가 저장된다 .MYD

5.1 클러스터형 인덱스 및 비 클러스터형 인덱스

개념 : 클러스터형 인덱스인지 여부는 데이터와 인덱스가 innodb 파일에 있는지 여부에 따라 다릅니다
.

  1. 클러스터형 인덱스는 하나만있을 수 있지만 클러스터되지 않은 인덱스는 많습니다.
  2. innodb에 데이터를 삽입 할 때 인덱스의 키 값을 포함해야합니다.
  3. 이 인덱스의 키 값은 기본 키가 될 수 있습니다. 기본 키가 없으면 고유 키입니다. 고유 키가 없으면 자체 생성 된 6 바이트 rowid입니다.

myisam : 비 클러스터형 인덱스

MySQL—innodb—B + tree
인덱스와 데이터를 함께 저장하고 해당 데이터를 읽을 인덱스를 찾아
여기에 사진 설명 삽입
MySQL—myisam—B + 트리
인덱스와 저장된 데이터의 주소를 함께 찾아 인덱스를 찾아 주소 값을 얻은 다음 찾기 주소 별 해당 데이터
여기에 사진 설명 삽입

5.2 표로 돌아 가기

다음으로 케이스 테이블을 만들어서

CREATE TABLE user_test(
id INT PRIMARY KEY AUTO_INCREMENT,-- id为主键
uname VARCHAR(20) ,
age INT,
gender VARCHAR(10),
 KEY `idx_uname` (`uname`) -- 索引选择为名字
)ENGINE = INNODB;

INSERT INTO user_test VALUES(1,'张三',18,'男');
INSERT INTO user_test VALUES(NULL,'马冬梅',19,'女');
INSERT INTO user_test VALUES(NULL,'赵四',18,'男');
INSERT INTO user_test VALUES(NULL,'王老七',22,'男');
INSERT INTO user_test VALUES(NULL,'刘燕',16,'女');
INSERT INTO user_test VALUES(NULL,'万宝',26,'男');
select * from user_test where uname = '张三';
-- 当我们表中有主键索引的时候,我们再去设置一个uname为索引,那么此时这条sql语句的查询过程应该如下:

여기에 사진 설명 삽입
먼저 uname을 기반으로 id를 쿼리 한 다음 id를 기반으로 행 정보를 쿼리합니다.
이 작업은 두 개의 B + 트리를 이동하여 테이블로 돌아갑니다.
일반 인덱스를 기반으로 클러스터 된 인덱스의 키 값을 쿼리 한 후 cluster 인덱스에서 데이터를 가져
오면 이러한 작업이 시간 낭비라는 것을 알 수 있으므로 일상 작업에서 테이블로 돌아가는 횟수를 줄이십시오.

5.3 커버링 인덱스

select id,uname from table where uname = '张三';
-- 根据uname 可以直接查询到id,uname两个列的值,直接返回即可
-- 不需要从聚簇索引查询任何数据,此时叫做索引覆盖

5.4 맨 왼쪽 일치

맨 왼쪽 일치에 대해 이야기하기 전에 몇 가지 명사에 대해 이야기 해 봅시다
기본 키 (일반적으로 열) --------> 공동 기본 키 (여러 열)
index --------> 공동 색인 ( 여러 인덱스 열을 포함 할 수 있음)

-- 假设有一张表,有id,name,age,gender四个字段,id是主键,name,age是组合索引列
-- 组合索引使用的时候必须先匹配name,然后匹配age

select * from table where name = ? and age = ? ;-- 生效
select * from table where name = ?;-- 生效
select * from table where age = ? ;-- 不生效
select * from table where age = ? and name = ? ;-- 生效

--在mysql内部有优化器会调整对应的顺序

5.5 인덱스 푸시 다운

mysql5.7 이후 기본적으로 지원되는 기능은
다음과 같습니다.

select * from table where name = ? and age = ? ;
-- mysql里的三层架构:
-- 客户端:JDBC
-- 服务端:server
-- 存储引擎:数据存储
在没有索引下推之前,根据name从存储引擎中获取符合规则的数据,在server层对age进行过滤
有索引下推之后,根据name、age两个条件从存储引擎中获取对应的数据

분석 : 인덱스 푸시 다운의 이점이 있습니다. 데이터가 50 개 있으면 필터링을 통해 10 개의 데이터를 얻습니다. 인덱스 푸시 다운이 없으면 먼저 50 개를 얻은 다음 제외하여 10 개를 얻습니다. -다운, 우리는 스토리지 엔진에서 직접 10 개로 필터링합니다.

추천

출처blog.csdn.net/zjdzka/article/details/112148860