MySQL의 색인 및 데이터 구조

해시 인덱스

주요 변경 사항이 발생하는 경우 (1)는 해시 값의 변화를 따릅니다., 정확한 값을 계산하는 해시 함수로 사용합니다. 그리고 해시 충돌 상황을 여전히 존재한다.

(2) 공동 해시 인덱스 (ID + 이름) = 해시 값을 인덱스 쿼리 범위 쿼리의 일부를 지원할 수 없다.

 

레드 - 블랙 트리

(1) 나무가 너무 높은, 너무 여러 번 디스크, 1,2,4,8,16을 읽는 것입니다 ......

  은 N 진 트리 인 경우에만 메모리, 디스크를 읽고, 그것이 데이터 걸리는 것 같은 데이터의 제 1 층은, 디스크에 데이터를 얻기 위해 판독 될 수있다 .... N

(2) 각 디스크는 너무 많은 쓰레기를 읽고

따라서, 데이터베이스 색인에 적합하지, 결국 그냥 이진 트리, 디스크 IO의 낭비이다.

 

레드 - 블랙 트리 HashMap의 이유?

HashMap의 메모리의 데이터 구조 때문에, 그렇게 두 한 상기의 문제는 없다

 

B 트리

B - 트리, B + 트리, B * 트리

 

N은 B-트리 이진 정렬 나무입니다.

M BTREE 순서의 몇 가지 중요한 특징 :

m 개의 서브 트리 (포인터), m-1 개의 키워드 (데이터 저장 공간)을 함유하는 1 결절 (m> 2)

2. 루트 노드 및 리프 노드들에 추가하여, 각각의 노드는 적어도 올림에 갖는 (m / 2) 서브 - 노드 시엘 반올림. 스플릿는 중간에서 분리되어 예를 들어, 5/2 = 2.5 (반올림)을 3 = 두 개의 하위 트리로 구분.

3. 루트 노드는 다음 두 개 이상의 하위 트리 리프 노드가 아닌 경우

 

  5를 만들 BTREE 순서가 삽입 된 데이터는 BTREE, 즉 5 차 BTREE 디스크 공간까지의 특성에 따라, 3 14 7 1 8 5 11 17 13 6 23 12 20 26 4 16 18 24 25 19 (사용자 ID 데이터베이스)이 5 포인터 (저장 검색 경로), 네 가지 키워드 (에 저장된 MySQL의 데이터)

 

 

이제 8 삽입,가, 분할 될 루트에 중간 요소로 이동합니다, 충분한 공간을 발견

 

 

 

 

 

 

이제 다시 일어날 분할의 충분한 오른쪽 하위 트리 공간 (13), 7,하지를 삽입하지만,이 요구는 13 (7)의 뒷면에 삽입되어 있음을 주목해야한다

 

 

 

 

약간 공정 뒤, 최종 구조는도.

 

 

그런 다음 B + 트리 구조를 비교

 

MySQL은 공동 인덱스를 작성하는 방법은?

假设我们使用user_id+name+age建联合索引, MySQL的底层还是使用user_id字段来创建的索引,只不过使用user_id创建的这颗索引树的叶子节点不再是存储的MySQL数据,它存储的是 user_id+name+age+ 数据地址(这个地址指向了数据库的真实数据).

所以,在使用联合索引查询数据的时候,首先是通过user_id查找这颗树的叶子,然后在叶子节点中找到 user_id+name+age 对应的这条数据地址,然后再使用这个地址去磁盘读取数据.

联合索引也体现了最左原则,所以在使用联合索引查询的时候,如果没有user_id,MySQL根本就找不到索引树.所以,索引就会失败.

 

MySQL索引树一个节点存储关键字的多少 = 页大小(16K)/索引大小

每个节点上关键字越多,树就应该越矮, 查找速度也就更快, 所以,建索引的字段应该越小越好.

 

再来一个小示例

 

mysql> select * from tb_emp;
+----+--------+------+
| id | name | age |
+----+--------+------+
| 1 | 乔峰 | 123 |
+----+--------+------+
1 row in set (0.00 sec)

 


mysql> show index from tb_emp;
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| tb_emp | 0 | PRIMARY | 1 | id | A | 2 | NULL | NULL | | BTREE | | |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)

 

 

# 创建一个name+age 的联合索引

 


mysql> alter table tb_emp add index `name_age_index`(name,age);
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0


mysql> show index from tb_emp;
+--------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| tb_emp | 0 | PRIMARY | 1 | id | A | 2 | NULL | NULL | | BTREE | | |
| tb_emp | 1 | name_age_index | 1 | name | A | 1 | NULL | NULL | YES | BTREE | | |
| tb_emp | 1 | name_age_index | 2 | age | A | 1 | NULL | NULL | YES | BTREE | | |
+--------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
3 rows in set (0.00 sec)

索引创建成功!

 

(1) name_age_index索引存在 

mysql> explain select * from tb_emp where age =123;
+----+-------------+--------+------------+-------+---------------+----------------+---------+------+------+----------+--------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+-------+---------------+----------------+---------+------+------+----------+--------------------------+
| 1 | SIMPLE | tb_emp | NULL | index | NULL | name_age_index | 88 | NULL | 2 | 50.00 | Using where; Using index |
+----+-------------+--------+------------+-------+---------------+----------------+---------+------+------+----------+--------------------------+
1 row in set, 1 warning (0.00 sec)

 

(2) drop name_age_index索引

mysql> drop index name_age_index on tb_emp;
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0

 

mysql> explain select * from tb_emp where age =123;
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | tb_emp | NULL | ALL | NULL | NULL | NULL | NULL | 2 | 50.00 | Using where |
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

 

在原先的认知, name+age创建的组合索引name_age_index后,如果查询条件中没有使用name,仅使用age是不会走索引的.

然而,通过上面的测试可知,Extra给出的解释是Using where; Using index ,说明它即使用了索引, 也回了表.

 

删除name_age_index后,Extra给出的解释只有Using where, 说明只是回表查询.

 

why? 不知道!

추천

출처www.cnblogs.com/z-qinfeng/p/12122223.html