首页 > 编程知识 正文

数据库mysql索引,数据库索引解释

时间:2023-05-06 04:42:32 阅读:215734 作者:3488

索引概述

数据库索引是用于提高数据库表的数据访问速度的。想要理解索引原理必须清楚一种数据结构「平衡树」(非二叉),也就是b tree或者 b+ tree,重要的事情说三遍:“平衡树,平衡树,平衡树”。当然, 有的数据库也使用哈希桶作用索引的数据结构 。然而,主流的RDBMS都是把平衡树当做数据表默认的索引数据结构的。

索引特点  避免进行数据库全表的扫描,大多数情况,只需要扫描较少的索引页和数据页,而不是查询所有数据页。而且对于非聚集索引,有时不需要访问数据页即可得到数据。聚集索引可以避免数据插入操作,集中于表的最后一个数据页面。在某些情况下,索引可以避免排序操作。聚集索引

我们平时建表的时候都会为表加上主键, 在某些关系数据库中, 如果建表时不指定主键,数据库会拒绝建表的语句执行。 事实上, 一个加了主键的表,并不能被称之为「表」。一个没加主键的表,它的数据无序的放置在磁盘存储器上,一行一行的排列的很整齐, 跟我认知中的「表」很接近。如果给表上了主键,那么表在磁盘上的存储结构就由整齐排列的结构转变成了树状结构,也就是上面说的「平衡树」结构,换句话说,就是整个表就变成了一个索引。没错, 再说一遍, 整个表变成了一个索引,也就是所谓的「聚集索引」。

这就是为什么一个表只能有一个主键, 一个表只能有一个「聚集索引」,因为主键的作用就是把「表」的数据格式转换成「索引(平衡树)」的格式放置。

    

上图就是带有主键的表(聚集索引)的结构图。其中树的所有结点(底部除外)的数据都是由主键字段中的数据构成,也就是通常我们指定主键的id字段。最下面部分是真正表中的数据。

假如我们执行一个SQL语句:  select * from table where id = 1256;

首先根据索引定位到1256这个值所在的叶结点,然后再通过叶结点取到id等于1256的数据行。这里不讲解平衡树的运行细节, 但是从图能看出,树一共有三层,从根节点至叶节点只需要经过三次查找就能得到结果。如下图

   

查找次数是以树的分叉数为底,记录总数的对数,用公式来表示就是:

    

因此,利用索引会使数据库查询有惊人的性能提升。

非聚集索引

非聚集索引和聚集索引一样, 同样是采用平衡树作为索引的数据结构。索引树结构中各节点的值来自于表中的索引字段, 假如给user表的name字段加上索引 , 那么索引就是由name字段中的值构成,在数据改变时, DBMS需要一直维护索引结构的正确性。如果给表中多个字段加上索引 , 那么就会出现多个独立的索引结构,每个索引(非聚集索引)互相之间不存在关联。 如下图

  

每次给字段建一个新索引, 字段中的数据就会被复制一份出来, 用于生成索引。 因此, 给表添加索引,会增加表的体积, 占用磁盘存储空间。

非聚集索引和聚集索引的区别

非聚集索引和聚集索引的区别在于, 通过聚集索引可以查到需要查找的数据, 而通过非聚集索引可以查到记录对应的主键值 , 再使用主键的值通过聚集索引查找到需要的数据,如下图

  

不管以任何方式查询表, 最终都会利用主键通过聚集索引来定位到数据, 聚集索引(主键)是通往真实数据所在的唯一路径

覆盖索引

然而, 有一种例外可以不使用聚集索引就能查询出所需要的数据, 这种非主流的方法 称之为「覆盖索引」查询, 也就是平时所说的复合索引或者多字段索引查询。

当为字段建立索引以后, 字段中的内容会被同步到索引之中, 如果为一个索引指定两个字段, 那么这个两个字段的内容都会被同步至索引之中。

例:我们把birthday字段上的索引写成双字段的覆盖索引

   create index index_birthday_and_user_name on user_info(birthday, user_name);

这句SQL语句的执行过程就会变为: 通过非聚集索引index_birthday_and_user_name查找birthday等于1991-11-1的叶节点的内容,然而, 叶节点中除了有user_info表主键ID的值以外, user_name字段的值也jzdxh, 因此不需要通过主键ID值的查找数据行的真实所在, 直接取得叶节点中user_name的值返回即可。

通过这种覆盖索引直接查找的方式, 可以省略不使用覆盖索引查找的后面两个步骤, 大大的提高了查询性能,如下图

  

数据库索引的大致工作原理就是像文中所述, 然而细节方面可能会略有偏差,这但并不会对概念阐述的结果产生影响 。

key 与 index

mysql的key和index多少有点令人迷惑,单独的key和其它关键词结合的key(如:primary key)实际表示的意义是不同,这实际上考察对数据库体系结构的了解的。

key 是数据库的物理结构,它包含两层意义和作用:

约束(偏重于约束和规范数据库的结构完整性),索引(辅助查询用的)。

mysql的key是同时具有constraint和index的意义,这点和其他数据库表现的可能有区别。

index 是数据库的物理结构,它只是辅助查询的,它创建时会在另外的表空间(mysql中的innodb表空间)以一个类似目录的结构存储。 因此,索引只是索引它不会去约束索引的字段的行为(那是key要做的事情)。

索引要分类的话,分为前缀索引、全文本索引等;

MySQL Key值(PRI, UNI, MUL)的含义:  PRI  主键约束; UNI  唯一约束; MUL 可以重复。

注:若是普通的key或者普通的index(实际上,普通的key与普通的index同义)。

当我们在desc 表名; 的时候,有一个Key值,表示该列是否含有索引
假设表结构如下所示

mysql> desc aa; +-------+---------+------+-----+---------+-------+| Field | Type | Null | Key | Default | Extra |+-------+---------+------+-----+---------+-------+| id | int(11) | YES | | NULL | |+-------+---------+------+-----+---------+-------+| xx | int(11) | YES | PRI | NULL | |+-------+---------+------+-----+---------+-------+| yy | int(11) | YES | UNI | NULL | |+-------+---------+------+-----+---------+-------+| zz | int(11) | YES | MUL | NULL | |+-------+---------+------+-----+---------+-------+1 row in set (0.00 sec)

我们看到Key那一栏,可能会有4种值,即: '啥也没有', 'PRI', 'UNI', 'MUL'
    1. 如果Key是空的, 那么该列值的可以重复,表示该列没有索引, 或者是一个非唯一的复合索引的前导列
    2. 如果Key是PRI,  那么该列是主键的组成部分
    3. 如果Key是UNI,  那么该列是一个唯一值索引的第一列(前导列),且不能含有空值(NULL)
    4. 如果Key是MUL,  那么该列的值可以重复, 该列是一个非唯一索引的前导列(第一列)或者是一个唯一性索引的组成部分但是可以含有空值NULL

注:
    1、如果对于一个列的定义,同时满足上述4种情况的多种,比如一个列既是PRI,又是UNI(如果是PRI,则一定是UNI)
    那么"desc 表名"; 的时候,显示的Key值按照优先级来显示 PRI->UNI->MUL, 那么此时,显示PRI。
    2、如果某列不能含有空值,同时该表没有主键,则一个唯一性索引列可以显示为PRI,
    3、如果多列构成了一个唯一性复合索引,那么一个唯一性索引列可以显示为MUL。(因为虽然索引的多列组合是唯一的,比如ID+NAME是唯一的,但    是每一个单独的列依然可以有重复的值,因为只要ID+NAME是唯一的即可)

End

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。