zoukankan      html  css  js  c++  java
  • mysql索引详解

    Mysql的索引详讲

    一、定义

    数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库的表结构。

    Mysql的数据是以文件的形式存储到磁盘上面的,每一行数据都有它的磁盘地址,没有索引的话,查找数据,就要去检索表中的每一条数据进行匹配,直到找到要查询的数据。

    如果使用数据库的索引就可以了,它是专门用来检索的一种数据结构,通过索引可以很快的找到相应的数据地址,然后通过地址得到这条数据。

     

    二、创建索引

    1、三种索引类型

    普通(Normal):也叫非唯一索引,是最普通的索引,没有任何的限制。

    唯一(Unique):唯一索引要求键值不能重复。另外需要注意的是,主键索引是一

    种特殊的唯一索引,它还多了一个限制条件,要求键值不能为空。主键索引用primay key

    创建。

    全文(Fulltext):针对比较大的数据,比如我们存放的是消息内容,有几KB的数

    据的这种情况,如果要解决like查询效率低的问题,可以创建全文索引。只有文本类型

    的字段才可以创建全文索引,比如char、varchar、text。

    MyISAM和InnoDB都支持全文索引。

     

    2、操作语句如下:

    创建;

    (1)、PRIMARY  KEY(主键索引)

            mysql>ALTER  TABLE  `table_name`  ADD  PRIMARY  KEY (  column  ) 

    (2)、UNIQUE(唯一索引)

            mysql>ALTER  TABLE  `table_name`  ADD  UNIQUE (column ) 

    (3)、INDEX(普通索引)

            mysql>ALTER  TABLE  `table_name`  ADD  INDEX index_name (  column )

    (4)、FULLTEXT(全文索引)

            mysql>ALTER  TABLE  `table_name`  ADD  FULLTEXT ( column )

    (5)、多列索引

            mysql>ALTER  TABLE  `table_name`  ADD  INDEX index_name (  column1,  column2,  column3)

    或者:

    create index index_name on table_name (column_list) ;
    create unique index index_name on table_name (column_list) ;

     

    删除:

    drop index index_name on table_name ;
    alter table table_name drop index index_name ;
    alter table table_name drop primary key ;

     

    修改索引:

    alter table table_name rename index before_name to after_name;

    在mysql5.7之前没有修改,只能先删除,在添加。

     

    查询表的索引:

    show index from user_innodb;

     

     

    三、索引的存储结构推演

     

    1、二叉查找树(Binary Search Tree)

    所有左子树节点小于父节点,右子树节点大于父节点,如图所示。

     

    既能快速查找,又可以快速删除,但是如果插入的数据是一直增大或者一直减小的话,他就会编程链表(“斜树”),这种情况和顺序查找检索是相同的,比如为10,7,3,2,1那么他就变成了一个链表,复杂度又变成了O(n)。

     

    什么原因导致的呢?

    究其原因就是不平衡。

     

    2、平衡二叉树(AVL Tree)(Balanced Binary Search Tree)

    除了有了二叉查找树的特性外,又多了平衡的特性,左右子树深度差绝对值不能超过1。

    平衡二叉树是一棵高度平衡的二叉查找树,当插入3的时候,通过右旋来保持平衡,左旋类似,nice,问题解决。

     

     

     

    3、节点结构以及存在的问题

    (1)、首先说节点结构

    包含三部分:索引的键值、磁盘地址、左右子节点的引用大概的结构如下:

     

     

      如果是这样存储数据的话,我们来看一下会有什么问题。首先,索引的数据,是放在硬盘上的。查看数据和索引的大小:当我们用树的结构来存储索引的时候,因为拿到一块数据就要在Server层比较是不是需要的数据,如果不是的话就要再读一次磁盘。访问一个节点就要跟磁盘之间发生一次IO。InnoDB操作磁盘的最小的单位是一页(或者叫一个磁盘块),大小是16K(16384字节)。那么,一个树的节点就是16K的大小。如果我们一个节点只存一键值+数据+引用,例如整形的字段,可能只用了十几个或者几十个字节,它远远达不到16k的容量,所以访问一个树节点,进行一次IO的时候,浪费了大量的空间。所以如果每个节点存储的数据太少,从索引中找到我们需要的数据,就要访问更多的节点,意味着限磁盘交互次数就会讨多。导致效率真的很低。

     

    所以我们的解决方案是什么呢?

    就是让每个节点存储更多的数据,节点上的关键字的数量越多,我们的指针数也越多,也就是意味着可以更多的分叉(我们把它叫做“路数”)。因为分叉数越多,树的深度就会减少(根节点是O)。这样就诞生了我们新的数据结构。

     

     

    4、多路平衡查找树(B Tree)

      这个就是我们的多路平衡查找树,叫做B Tree (B代表平衡)。跟AVL树一样,B树在枝节点和叶子节点存储键值、数据地址、节点引用。它有一个特点:分叉数(路数)永远比关键字数多1。如下图:

     

     

    但是B Tree是怎样保持平衡的呢,显然左旋右旋肯定不行了

     

    通过分列,如果在进来5,那么5和3合并即可。

     

    5、B+ 树

    如下图:

     

    MySQL中的+Tree有几个特点:

    1、它的关键在于关键字数和路数是相同的。

    2、B+Tree的根节点和枝节点中都不会存储数据,只有叶子节点才存储数据,直接存储的数据。

    3、B+Tree的每个叶子节点增加了一个指向相邻叶子节点的指针,它的最后一个数

    据会指向下一个叶子节点的第一个数据,形成了一个有序链表的结构。

     

    InnoDB中的B+Tree这种特点带来的优势:

    1)它是B Tree的变种,BTree能解决的问题,它都能解决。B Tree解决的两大问题是什么?(每个节点存储更多关键字;路数更多)

    2)扫库、扫表能力更强(对表进行全表扫描,只需要遍历叶子节点就可以了,不需要

    遍历整棵B+Tree拿到所有的数据)

    3)B+Tree的磁盘读写能力相对于BTree来说更强(根节点和枝节点不保存数据区,

    所以一个节点可以保存更多的关键字,一次磁盘加载的关键字更多)

    4)排序能力更强(因为叶子节点上有下一个数据区的指针,数据形成了链表)

    5)效率更加稳定(B+Tree永远是在叶子节点拿到数据,所以IO次数是稳定的)

     

     

    四、在存储引擎中的应用

     

    1、MyISAM

    在MylSAM里面,另外有两个文件:

    一个是.MYD文件,D代表Data,是MylSAM的数据文件,存放数据记录。

    一个是.MYI文件,l代表Index,是 MylSAM的索引文件,存放索引。

    MylSAM的B+Tree里面,叶子节点存储的是数据文件对应的磁盘地址。所以从引文件.MYI中找到键值后,会到数据文件.MYD中获取相应的数据记录。在MylSAM里面,辅助索引也在这个.MYI文件里面。辅助索引跟主键索引存储和检索数据的方式是没有任何区别的,一样是在索引文件里面找到磁盘地址,然后到数据文件里面获取数据。

     

    2、InonoDB

    在InnoDB里面,它是以主键为索引来组织数据的存储的,所以索引文件和数据文件是同一个文件,都在.ibd文件里面。在InnoDB的主键索引的叶子节点上,它直接存储了我们的数据。

    聚集索引(聚簇索引)︰就是索引键值的逻辑顺序跟表数据行的物理存储顺序是令致的。(比如字典的目录是按拼音排序的,内容也是按拼音排序的,按拼音排序的这种目录就叫聚集索引)。在InnoDB里面,它组织数据的方式叫做叫做(聚集)索引组织表(clustered indexorganize table),所以主键索引是聚集索引,非主键都是非聚集索引。主键之外的索引,比如在name字段上面建的普通索引,又是怎么存储和检索数据的呢?

    InnoDB中,主键索引和辅助索引是有一个主次之分的。辅助索引存储的是辅助索引和主键值。如果使用辅助索引查询,会根据主键值在主键索引中查询,最终取得数据。

     

    如果一张表没有主键索使用什么机制呢?

    1、如果我们定义了主键(PRIMARY KEY),那么InnoDB会选择主键作为聚集索引。

    2、如果没有显式定义主键,则 InnoDB会选择第一个不包含有NULL值的唯一索引

    作为主键索引。

    3、如果也没有这样的唯一索引,则InnoDB会选择内置6字节长的ROWID作为隐

    藏的聚集索引,它会随着行记录的写入而主键递增。

     

    五、使用索引的注意点

    1、散列度

    select (select count(distinct(id)) from user_innodb) / (select count(*) from user_innodb)

    散列度越高,使用索引越合适。

     

    2、联合索引最左匹配原则

    比如user表给name和phone建立了一个联合索引。

    ALTER TABLE uscr_innodb DROP INDEX comidx_namc_phonc;

    ALTER TABLE user_innodb add INDEX comidx_name_phone (name.phone);

     

    联合索引在B+Tree中是复合的数据结构,它是按照从左到右的顺序来建立搜索树的

    (name在左边,phone在右边)。name相同,phone才是有序的。

    所以如果name是空一定是用不到索引的。

     

    3、覆盖索引

    回表:

    非主键索引,我们先通过索引找到主键索引的键值,再通过主键值查出索引里面没有的数据,它比基于主键索引的查询多扫描了一棵索引树,这个过程就叫回表。

    在辅助索引里面,不管是单列索引还是联合索引,如果select的数据列只用从索引中就能够取得,不必从数据区中读取,这时候使用的索引就叫做覆盖索引,这样就避免回表。

     

  • 相关阅读:
    docker私有仓库harbor的安装及使用
    docker 搭建 zipkin
    docker安装redis并以配置文件方式启动
    docker 安装 mysql5.7.25
    什么是反射?可以解决什么问题?
    什么是死锁?如何防止死锁?
    说说TCP和UDP的区别
    什么是XSS攻击?
    怎么更改Visual Studio项目名字
    windows上使用getopt和getopt_long
  • 原文地址:https://www.cnblogs.com/mcjhcnblogs/p/13828182.html
Copyright © 2011-2022 走看看