在我们的工作中,我们经常会用到索引。不管是普通索引还是唯一索引,都是一些常用的索引方法。目的是提高查询效率,避免业务请求超时等问题。那么,大家在使用索引的时候,是否想过以下问题:索引是如何实现的,一共有哪些索引?带着这些问题,我们开始吧~什么是索引?不知道大家第一次听到索引这个词,会不会觉得很抽象,很难理解。索引,什么是索引?索引实际上是一种数据结构。那么在计算机世界中,任何数据结构都有其用途,如栈、堆、树、队列等。那么,数据库为什么要使用索引呢?为了提高查询(检索)效率。所以,它就像书前面的目录,它的作用就是搜索和排序,大大提高你对数据的查询速度。因此,你可以理解为索引是一种帮助存储引擎高效获取数据的方式,就像你去图书目录高效获取书中的某条知识一样。索引实现方式索引通常使用称为B树(BTree)和B+树(B+Tree)的数据结构。哈希(Hash)也会被用作索引,我们会讲到这些方法。BTreeBTree指的是BalanceTree,是一种平衡树。先说说它的特点:它是一棵多路搜索树,所有叶子节点都在同一层。每个节点不仅包含数据的键值,还包含数据值。每个节点相当于一个磁盘块。你可以修改它来存储和排序数据,它的时间复杂度是O(logn),因为它是顺序读取、插入和删除的。B+树B+树是在B树的基础上实现的。它具有BTree的balance,而且因为是有序的,所以也可以通过指针顺序访问,时间复杂度还是O(logn):说说它的特点:每个叶子节点存储索引字段的key字段对应的值和数据。非叶子节点只存储索引字段的键值和指向子节点的指针,不存储数据。每个节点相当于一个磁盘块。同级的叶子节点以双向链表的形式连接起来。那么,既然有B树,为什么还需要B+树呢?其实B-tree和B+树最大的区别就是B+树的非叶子节点只存储指向下一个节点的地址,并不存储实际值。而且它所有的叶子节点都是用链表连接起来的,因为是有序的,所以遍历查找会比较快。因此,B+树具有B树所没有的优点。由于非叶子节点不存储数据,所以同一空间的内存页可以存储更多的key。这些key排列紧密,顺序排列,比B-tree进行数据查询更稳定,速度更快,因为它可以更好的利用空间局部性原理。Hash除了B-tree和B+-tree之外,还有一个索引,叫做hash。哈希索引基于哈希算法。对于每一行数据,数据库存储引擎会通过哈希算法为所有索引列计算一个哈希码,然后将哈希码存储在哈希索引中。由于是散列算法,所以使用散列索引有两个缺点:散列算法计算出来的散列值可能会有散列冲突,因为计算出来的值是一个值,所以不能进行范围查询。因此,B-树和B+树是数据库常用的两种索引数据结构,但是对于MySQLInnoDB存储引擎来说,它使用的是B+树。索引的分类刚才讲解的是索引的实现,所以索引也可以根据实际应用功能和物理实现来划分。按功能划分我们平时在写SQL或者建表的时候,会根据实际业务的查询频率、特点、数据量,为字段创建各种索引。那么这些索引根据实际应用可以分为:主键(PRIMARYKEY)、唯一索引(UNIQUE)、普通索引(INDEX)、全文索引(FULLTEXT)主键,只要在指定主键的时候创建一个表,就会产生相应的索引。为什么我这里说的是主键,而不是主键索引。很多人把主键和唯一索引、普通索引联系起来,称之为“主键索引”。其实这是不准确的。因为主键本质上是一种约束,而索引是一种用来提高查询效率的数据结构。两者不在一个层次,也有功能和质的区别。这里我把主键按照功能划分放了进去,因为它是这些索引乃至一张表的基础。对于MySQL的InnoDB存储引擎来说,一个表结构必须有一个主键,表中的数据必须是按照主键的顺序存储的。其他索引也依赖于主键来生成索引。如何创建主键:方法一:在创建表时指定主键。如果创建表时没有定义主键,InnoDB会通过以下规则创建主键:判断表中是否存在非空唯一索引。如果存在,则索引对应的字段名为主键。如果不存在,InnoDB会自动创建索引方法二:通过SQL语句:ALTERTABLE`table_name`ADDPRIMARYKEY`column_name`;那么,什么是我们常说的“主键索引”呢?我们稍后会讲到。唯一索引使用唯一索引作为索引,保证该行的索引列不包含重复值。所以它和非唯一索引的区别在于,除了具有索引的功能外,还限制了这个字段在数据库中不能有重复的记录。我们可以通过如下SQL创建唯一索引:ALTERTABLE`table_name`ADDUNIQUEindexName;普通索引很简单没有花哨的,最常见的索引类型。为一个或多个字段添加索引只是为了提高查询速度。Fancy在其工作中创建了最常见的索引。它的创建语句:ALTERTABLE`table_name`ADDINDEXindex_name;全文索引作为程序员,我们每天都要和搜索引擎打交道。不仅是搜索引擎,很多APP都有全文搜索功能:如果不使用一些中间件技术,每次搜索都得根据关键词到数据库中搜索。如果不使用索引,响应时间可能需要几秒才能从海量数据中筛选出你预期的结果。这对于用户来说无疑是不能接受的。因此,全文索引适合此类业务场景。如果要使用全文索引,必须指定存储引擎为MYISAM,因为InnoDB存储引擎不支持全文索引。因为全文索引有很多缺点,比如不支持大小写,创建索引慢,所以不推荐使用MySQL全文索引。在目前的场景下,我们一般会使用ElasticSearch等封装好的中间件来满足全局数据检索的需求。创建全文索引的方法:ALTERTABLE`table_name`ADDFULLTEXT`column`;按索引个数划分如果一个字段上加了一个索引,那么就是单列索引。但我们也可以将多个字段组合在一起创建一个索引,称为“联合索引”,也称为多列索引或复合索引。为了方便。以后我们统称为“联合索引”。注意:在多个单列索引不能称为组合索引之后,我们会单独详细说说这个组合索引和它的一些问题,本文先不做过多描述。根据物理实现来划分为了帮助大家更好的理解,我们现在创建一个表:createtablefancyFamily(idint(11)notnullauto_incrementcomment'家庭成员ID',namevarchar(16)notnullcomment'家庭成员姓名',ageint(11)defaultnullcomment'familymemberage',primarykey(id))engineInnoDBAUTO_INCREMENT=10defaultcharset=utf8;然后插入一定量的数据:insertintofancyFamily(id,name,age)values(1,'fancy',26);insertintofancyFamily(id,name,age)values(3,'小黄',25);insertintofancyFamily(id,name,age)values(8,'大芬',50);insertintofancyFamily(id,name,age)values(10,'rhubarb',55);insertintofancyFamily(id,name,age)values(13,'小蓝',18);insertintofancyFamily(id,name,age)values(16,'小白',15);聚集索引什么是聚集索引?刚才我们说了对于以B+树为数据结构创建的索引,只有叶子节点存储数据,叶子节点中的数据按照数据库表中的数据排成一行:我们将一种索引形式满足上述数据存储形式的称为“聚簇索引”。这里的重点是数据的存储形式,即在叶子节点中存储数据。又因为一张表的数据不能存放在两棵不同的B+树中。所以一张表只能有一个聚簇索引。那么我们现在有一个问题:一张表中只能有一个主键,也只能有一个聚簇索引,而聚簇索引在B+树中仍然是根据主键的数据存储形式生成的,所以不是聚集索引的主键?还是上面提到的知识点:主键是一个约束,用来提高表结构的数据完整性。聚集索引是一种索引,其目的是创建有序的数据以降低查询的时间复杂度。它是一个索引,索引的目的是为了提高查询效率。就像买房子和买车一样,它们的用途有着本质的区别。“主键索引”这个词呢?在InnoDB存储引擎中,一张表必须有一个主键,主键是使用索引提高效率的基础。只有主键才能用于排序和查询。只有建立了主键,才能生成聚簇索引的数据存储形式,所以生成表的主键时,也会生成对应的聚簇索引。所以也有人喜欢把聚簇索引称为“主键索引”。辅助索引有了聚簇索引,就会有非聚簇索引。聚簇索引以外的索引称为非聚簇索引,例如创建非主键字段的索引后构建的索引树。也称为二级索引或辅助索引,为方便起见,以后统称为辅助索引。那么它和聚簇索引有什么区别呢?最大的区别是聚簇索引的叶子节点包含了表结构的所有行数据,而辅助索引则没有。它仍然使用B+树,但是每个叶子节点存储了聚簇索引所在列的主键值:与聚簇索引不同的是,因为它不按照主键来排列和检索,所以可以有多个主键表中的关键索引。那么,如果我们现在创建辅助索引名称,查询名称小黄,会如何操作呢?select*fromworkerswherename='小黄';它的查询步骤如下:利用name='Xiaohuang'这个条件辅助索引找到对应叶子节点的键值,找到'Xiaohuang'对应的数据,即Xiaohuang对应的主键黄色行中的数据使用此主键返回聚簇索引。对聚簇索引的主键进行排序,到叶子节点中查找主键ID为3的黄色对应的数据。也就是说,如果使用辅助索引,就不会像主键那样index那样,直接去叶子节点找对应的数据,但是先去叶子节点找对应条件的主键,然后返回聚簇索引根据这个主键查找。我们把这种情况叫回表:也就是说,如果使用辅助索引,它比聚簇索引需要多一次树访问和遍历。综上所述,上面我们已经介绍了什么是索引,如何实现索引,以及索引的具体分类。可以通过索引的功能、数量、物理实现来区分不同的索引,并详细描述了聚簇索引和非聚簇索引的区别。我身边有工作多年的同事。他们的业务能力是优秀的,但是在涉及到数据库索引的时候,也有分不清和归纳不清的地方,所以我觉得把这些基础知识梳理一下是非常重要的。
