文章目录

  • 一、索引
  • 1、什么是索引?
  • 2、索引的优缺点
  • 3、使用索引
  • @ 查看索引
  • @ 创建索引
  • @ 删除索引
  • 4、总结索引
  • 二、重点:索引在MySQL中的数据结构
  • 1、数据结构分析
  • 2、索引中的数据结构总结


一、索引

1、什么是索引?

可以对表中的一列或者多列创建索引,各类索引有各自的数据结构实现

原理:当查询某一项时,使用索引后,查询不是从原表中查所有数据再显示目标项,而是将索引拿来查询,数据量大大减少,从而提高查询效率。

2、索引的优缺点

优点:

  • 加快了查询操作,提高效率,因为在实际中,查的比增删改多很多。

缺点:

  • 索引提高了增删改的开销。因为索引相当于一本书的目录,每次增删改后,需要同时改变这个目录,即改索引。
  • 索引会多占用空间

3、使用索引

前提:我创建了一个student表,id为主键,还有一个name字段

mysql> desc student;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int         | NO   | PRI | NULL    |       |
| name  | varchar(20) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

@ 查看索引

创建表时,有主键/unique/外键,都会自动创建索引

-- 查看索引
show index from 表名
mysql> show index from student;
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table   | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| student |          0 | PRIMARY  |            1 | id          | A         |           0 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
1 row in set (0.04 sec)

@ 创建索引

对于一个非主键,非唯一约束,非外键约束的字段,可以采用普通索引

-- 创建索引
create index 索引名 on 表名(字段名)
mysql> create index ind_name_stu on student(name);
Query OK, 0 rows affected (0.06 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show index from student;--可以看到,多出了关于name的索引
+---------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table   | Non_unique | Key_name     | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+---------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| student |          0 | PRIMARY      |            1 | id          | A         |           0 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
| student |          1 | ind_name_stu |            1 | name        | A         |           0 |     NULL |   NULL | YES  | BTREE      |         |               | YES     | NULL       |
+---------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
2 rows in set (0.04 sec)

@ 删除索引

-- 删除索引
drop index 索引名 on 表名

4、总结索引

  1. 创建表时,有主键/unique/外键,都会自动创建索引
  2. 对于一个非主键约束,非唯一约束,非外键约束的字段,可以采用普通索引
  3. 索引创建好后,查询时会自动使用索引去查,而不需要手动操作。因为SQL是通过数据库的 “执行引擎” 来执行的,这会涉及到 “优化” 操作,即在操作结果不变的前提下,“执行引擎” 去决定是否使用索引,它会选择更优的方法去操作。
  4. 索引最好在表创建之初就创建好。不然当表中数据量很大很大才创建索引时,会吃掉大量的磁盘IO,花很长时间(几十分钟到几个小时)。并且在这段时间内,数据库无法被正常使用。
  5. 基于上一条原因,和数据库删库删表一样,索引也是一个危险操作
  6. 对一个字段有重复内容时,索引可以支持,但是可能不能提高效率,比如我对学生表的性别字段给个索引,不能提高查找效率,这其实是没有意义的。

二、重点:索引在MySQL中的数据结构

1、数据结构分析

哈希表:

  • 用哈希表查询元素,时间复杂度为O(1),查找效率极高。但是它在MySQL数据库中有个致命缺陷:它只能比较是否相等,不能进行大于小于这样的范围查询,而数据库经常需要范围查询。

二叉搜索树(BST=>Binary Search Tree):

  • 二叉搜索树,又叫二叉排序树。时间复杂度最坏为O(N)(节点个数就是树的高度时最坏)。在二叉搜索树平衡时,即是平衡二叉树(AVL=>AVL是由三个人创建的,取自他们的名字),才是O(logn)(注意:logn是非常高效的,n越大,logn函数图像越平,就越接近O(1))
  • 二叉搜索树可以范围查询,在数据库中可以满足哈希表的缺陷,即实现范围查询(找到起始点和终点就行)。但是二叉搜索树因为是二叉而不是n叉,所以树的高度会比较高,即使它变成平衡的AVL树,而树的高度就代表了查询元素需要的比较次数,在数据库比较元素时,是需要读写硬盘进行IO操作的,所以高度越高,查询效率越低

N叉搜索树(B树=>Binary Tree):

  • 又叫B树(B-Tree),有些人又叫B-树,不是B减树,而是叫做B杠树。例如B+树其实是B±树(B加杠树),因为不美观,所以省掉杠叫做B+树。而B树可以加上杠就是(B-树)。
  • 虽然比较次数不变,但是硬盘IO操作减少了。因为从硬盘读取一个节点时,每个节点里面就包含了多个数据,所以减少了硬盘IO操作。下面就是B树的数据结构简图。

B+树:

  • 和B树一样,高度降低后,硬盘读写次数减少,效率提高
  • 适合范围查询。 因为B+树的数据都在叶子节点上,并且叶子节点用链表串起来,只要找到起点和终点所在的节点,用链表查询就很方便,所以非常适合范围查询。
  • 查询操作比较均衡。 因为所有数据都在叶子节点上用链表连接起来 ,无论查询哪个元素,硬盘IO次数差不多都要到叶子节点。而如果是B树,因为在非叶子节点上的数据也要看,所以对于查询一个数据可能IO次数减少,但查询一个范围的数据时,IO次数会大大增加。
  • 因为B+树的非叶子节点不存放数据行,只存放索引,因此空间大大降低,这时,内存可能就可以放下这个结构,进一步降低了硬盘的IO,提高效率。
  • 综上所有分析,B+树是非常适合于做数据库的索引背后的数据结构的。

2、索引中的数据结构总结

  1. 主键索引会随着表的创建而自动创建(如果用B+树实现),当手动创建非主键索引时会再创建一棵B+树,这棵B+的非叶子节点里面存的都是这一列的key(比如创建name2索引 ),到了叶子节点这一行,存的就不是数据行了,而是存主键(id)。
  2. 如果使用主键列来索引来查询,只查一次第一棵B+树即可; 而如果用非主键列来查询,要先查一遍这个非主键列索引的B+树,然后再查主键列索引的B+树。
  3. 回表:就是用非主键列索引在叶子节点查出主键id,在根据id去主键列索引查询数据行。
  4. MySQL的InnoDB这个主流的数据库引擎,就是使用的B+树。不同的引擎可能使用不同的数据结构。哈希表增删查改效率极高,因此在特定情况下也可能使用哈希表。