问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

mysql有几种索引类型?使用索引时都有那些地方要注意

发布网友 发布时间:2022-04-24 06:18

我来回答

3个回答

懂视网 时间:2022-04-07 18:45

一、什么是索引?

??在关系数据库中,索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。

??当表中有大量记录时,若要对表进行查询,第一种搜索信息方式是全表搜索,是将所有记录一一取出,和查询条件进行一一对比,然后返回满足条件的记录,这样做会消耗大量数据库系统时间,并造成大量磁盘I/O操作;第二种就是在表中建立索引,然后在索引中找到符合查询条件的索引值,最后通过保存在索引中的ROWID(相当于页码)快速找到表中对应的记录。

??MySQL5.5以后InnoDB储引擎使用的索引数据结构主要用:B+Tree;本篇文章带大家以B+Tree前世今生为主线来聊一聊;

**Mark**

B+Tree可以对<,<=,=,>,>=,BETWEEN,IN,以及不以通配符开始的LIKE使用索引。(MySQL5.5后)

??这些事实或许会颠覆你的一些认知,比如在你读过的其他文章或书中。以上这些都属于“范围查询”,都是不走索引的!

??没错,早先5.5以前优化器是不会选择通过索引搜索的,优化器认为这样取出的行多与全表扫描的行,因为还要回表查一次嘛,可能会涉及I/O的行数更多,被优化器放弃。

??经过算法(B+Tree)优化后,支持对部分范围类型的扫描(得利与B+Tree数据结构的有序性)。该做法同时也违反了最左前缀原则,导致范围查询后的条件无法用到联合索引,我们在后面详细说明。

二、索引的优缺点

1、优点

  1. 索引大大减小了服务器需要扫描的数据量
  2. 索引可以帮助服务器避免排序和临时表
  3. 索引可以将随机I/O变成顺序I/O

2、缺点

  1. 虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存索引文件。
  2. 建立索引会占用磁盘空间的索引文件。一般情况这个问题不算严重,但如果你在一个大表上创建了多种组合索引,且伴随大量数据量插入,索引文件大小也会快速膨胀。
  3. 如果某个数据列包含许多重复的内容,为它建立索引就没有太大的实际效果。
  4. 对于非常小的表,大部分情况下简单的全表扫描更高效;

??因此应该只为最经常查询和最经常排序的数据列建立索引。(MySQL里同一个数据表里的索引总数限制为16个)

??数据库存在的意义之一就是是解决数据存储和快速查找的。那么数据库的数据存在哪?没错,是磁盘,磁盘的优点是啥?便宜!缺点呢?相比内存访问速度慢。

??那么你知道MySQL索引主要使用的数据结构么?

??B+树!你脱口而出。

??那 B+树 是什么样的数据结构?MySQL索引又是为什么选择了B+树呢?

??其实最终选用 B+树 是经历了漫长的演化:

二叉排序树 → 二叉平衡树 → B-Tree(B树) → B+Tree(B+树)

??有小伙伴问我“B树 跟 B-树有什么区别”?这里普及一下,MySQL数据结构只有B-Tree(B树)和B+Tree(B+树),多只是读法不同罢了,“B-Tree” 一般统称为B树,你叫他B-树也行~~

??还有小伙伴提到的红黑树,是编程语言中的存储结构,不是MySQL的;如Java的HashMap就是用的链表加红黑树。

??好了,今天就带着大家一起看一下演化成 B+树 的过程吧。

三、B+Tree索引的前世今生

1、二叉排序树

??理解B+树之前,简单说一下二叉排序树,对于一个节点,它的左子树的孩子节点值都要小于它本身,它的右子树的孩子节点值都要大于它本身,如果所有节点都满足这个条件,那么它就是二叉排序树。(此处可以串一下二分查找的知识点)
在这里插入图片描述

上图是一颗二叉排序树,你可以尝试利用它的特点,体验查找9的过程:

  • 9比10小,去它的左子树(节点3)查找
  • 9比3大,去节点3的右子树(节点4)查找
  • 9比4大,去节点4的右子树(节点9)查找
  • 节点9与9相等,查找成功
  • 一共比较了4次,那你有没有想过上述结构的优化方式?

    2、AVL树 (自平衡二叉查找树)

    在这里插入图片描述

    上图是AVL树,节点个数和值均和二叉排序树一摸一样

    再来看一下查找9的过程:

  • 9比4大,去它的右子树查找
  • 9比10小,去它的左子树查找
  • 节点9与9相等,查找成功
  • ??一共比较了3次,同样的数据量比二叉排序树少了一次,为什么呢?因为AVL树高度要比二叉排序树小,高度越高意味着比较的次数越多;不要小看优化的这一次,假如是200w条数据,比较次数会明显地不同。

    ??你可以想象一下一棵 100 万节点的平衡二叉树,树高 20。一次查询可能需要访问 20 个数据块。在机械硬盘时代,从磁盘随机读一个数据块需要 10 ms 左右的寻址时间。也就是说,对于一个 100 万行的表,如果使用二叉树来存储,单独访问一个行可能需要 20 个 10 ms 的时间,这个查询可真够慢的!

    3、B树(Balanced Tree)多路平衡查找树 多叉的

    B树是一种多路自平衡搜索树,它类似普通的二叉树,但是B书允许每个节点有更多的子节点。B树示意图如下:

    在这里插入图片描述

    B树的特点:

    1. 所有键值分布在整个树中
    2. 任何关键字出现且只出现在一个节点中
    3. 搜索有可能在非叶子节点结束
    4. 在关键字全集内做一次查找,性能逼近二分查找算法

    ??为了提升效率,要尽量减少磁盘I/O的次数。实际过程中,磁盘并不是每次严格按需读取,而是每次都会预读。

    ??磁盘读取完需要的数据后,会按顺序再多读一部分数据到内存中,这样做的理论依据是计算机科学中注明的局部性原理:

  • 由于磁盘顺序读取的效率很高(不需要寻址时间,只需很少的旋转时间),因此对于具有局部性的程序来说,预读可以提高I/O效率.预读的长度一般为页(page)的整倍数。
  • MySQL(默认使用InnoDB引擎),将记录按照页的方式进行管理,每页大小默认为16K(可以修改)。
  • B-Tree借助计算机磁盘预读机制:

    ??每次新建节点的时候,都是申请一个页的空间,所以每查找一个节点只需要一次I/O;因为实际应用当中,节点深度会很少,所以查找效率很高.

    ??那么最终版的 B+树 是如何做的呢?

    4、B+ Tree (B+树是B树的变体,也是一种多路搜索树)

    在这里插入图片描述

    从图中也可以看到,B+树与B树的不同在于:

    1. 所有关键字存储在叶子节点,非叶子节点不存储真正的data,从而可以快速定位到叶子结点。
    2. 为所有叶子节点增加了一个链指针,意味着所有的值都是按顺序存储的,并且每一个叶子页到根的距离相同,很适合查找范围数据。

    **因此,B+Tree可以对<,<=,=,>,>=,BETWEEN,IN,以及不以通配符开始的LIKE使用索引。**

    B+树的优点:

    比较的次数均衡,减少了I/O次数,提高了查找速度,查找也更稳定。

  • B+树的磁盘读写代价更低
  • B+树的查询效率更加稳定
  • ??要知道的是,你每次创建表,系统会为你自动创建一个基于ID的聚集索引(上述B+树),存储全部数据;你每次增加索引,数据库就会为你创建一个附加索引(上述B+树),索引选取的字段个数就是每个节点存储数据索引的个数,注意该索引并不存储全部数据。

    四、为什么MySQL索引选择了 B+树 而不是 B树?

    1. B+树更适合外部存储(一般指磁盘存储),由于内节点(非叶子节点)不存储data,所以一个节点可以存储更多的内节点,每个节点能索引的范围更大更精确。也就是说使用B+树单次磁盘I/O的信息量相比较B树更大,I/O效率更高。
    2. mysql是关系型数据库,经常会按照区间来访问某个索引列,B+树的叶子节点间按顺序建立了链指针,加强了区间访问性,所以B+树对索引列上的区间范围查询很友好。而B树每个节点的key和data在一起,无法进行区间查找。

    五、程序员,你应该知道的索引知识点

    1、回表查询

    比如你创建了name, age索引 name_age_index,查询数据时使用了

    select * from table where name ='陈哈哈' and age = 26;
    1复制代码

    ??由于附加索引中只有name 和 age,因此命中索引后,数据库还必须回去聚集索引中查找其他数据,这就是回表,这也是你背的那条:少用select * 的原因。

    2、索引覆盖

    结合回表会更好理解,比如上述name_age_index索引,有查询

    select name, age from table where name ='陈哈哈' and age = 26;
    1复制代码

    ??此时select的字段name,age在索引name_age_index中都能获取到,所以不需要回表,满足索引覆盖,直接返回索引中的数据,效率高。是DBA同学优化时的首选优化方式。

    3、最左前缀原则

    ??B+树的节点存储索引顺序是从左向右存储,在匹配的时候自然也要满足从左向右匹配;通常我们在建立联合索引的时候,也就是对多个字段建立索引,相信建立过索引的同学们会发现,无论是Oracle还是 MySQL 都会让我们选择索引的顺序,比如我们想在a,b,c三个字段上建立一个联合索引,我们可以选择自己想要的优先级,a、b、c,或者是b、a、c 或者是c、a、b等顺序。 为什么数据库会让我们选择字段的顺序呢?不都是三个字段的联合索引么?这里就引出了数据库索引的最左前缀原理。

    ??在我们开发中经常会遇到明明这个字段建了联合索引,但是SQL查询该字段时却不会使用索引的问题。比如索引abc_index:(a,b,c)是a,b,c三个字段的联合索引,下列sql执行时都无法命中索引abc_index的;

    select * from table where c = '1';
    
    select * from table where b ='1' and c ='2';
    123复制代码

    以下三种情况却会走索引:

    select * from table where a = '1';
    
    select * from table where a = '1' and b = '2';
    
    select * from table where a = '1' and b = '2' and c='3';
    12345复制代码

    从上面两个例子大家是否阔以看出点眉目?

    ??是的,索引abc_index:(a,b,c),只会在(a)、(a,b)、(a,b,c) 三种类型的查询中使用。其实这里说的有一点歧义,其实(a,c)也会走,但是只走a字段索引,不会走c字段。

    ??另外还有一个特殊情况说明下,下面这种类型的也只会有 a与b 走索引,c不会走。

    select * from table where a = '1' and b > '2' and c='3';
    1复制代码

    ??像上面这种类型的sql语句,在a、b走完索引后,c已经是无序了,所以c就没法走索引,优化器会认为还不如全表扫描c字段来的快。

    **最左前缀:顾名思义,就是最左优先,上例中我们创建了a_b_c多列索引,相当于创建了(a)单列索引,(a,b)组合索引以及(a,b,c)组合索引。**

    ??因此,在创建多列索引时,要根据业务需求,where子句中使用最频繁的一列放在最左边。

    4、索引下推优化

    还是索引name_age_index,有如下sql

    select * from table where name like '陈%' and age > 26;
    1复制代码

    该语句有两种执行可能:

  • 命中name_age_index联合索引,查询所有满足name以"陈"开头的数据, 然后回表查询所有满足的行。
  • 命中name_age_index联合索引,查询所有满足name以"陈"开头的数据,然后顺便筛出age>20的索引,再回表查询全行数据。
  • 显然第2种方式回表查询的行数较少,I/O次数也会减少,这就是索引下推。所以不是所有like都不会命中索引。

    六、使用索引时的注意事项

    1、索引不会包含有null值的列

    ??只要列中包含有null值都将不会被包含在索引中,复合索引中只要有一列含有null值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时建议不要让字段的默认值为null。

    2、使用短索引

    ??对串列进行索引,如果可能应该指定一个前缀长度。例如,如果有一个char(255)的列,如果在前10个或20个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。

    3、索引列排序

    ??查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引。

    4、like语句操作

    ??一般情况下不推荐使用like操作,如果非使用不可,如何使用也是一个问题。like “%陈%” 不会使用索引而like “陈%”可以使用索引。

    5、不要在列上进行运算

    这将导致索引失效而进行全表扫描,例如

    SELECT * FROM table_name WHERE YEAR(column_name)<2017;
    1复制代码

    6、不使用not in和<>操作

    这不属于支持的范围查询条件,不会使用索引。

    我的体会

    ??曾经,我一度以为我很懂MySQL。

    ??刚入职那年,我还是个孩子,记得第一个需求是做个统计接口,查询近两小时每隔5分钟为一时间段的网站访问量,JSONArray中一共返回24个值,当时菜啊,写了个接口循环二十四遍,发送24条SQL去查(捂脸),由于那个接口,被技术经理嘲讽~~表示他写的SQL比我吃的米都多。虽然我们山东人基本不吃米饭,但我还是羞愧不已。。
    然后经理通过调用一个dateTime函数分组查询处理一下,就ok了,效率是我的几十倍吧。从那时起,我就定下目标,深入MySQL学习,万一日后有机会嘲讽回去?

    ??筒子们,MySQL路漫漫,其修远兮。永远不要眼高手低,一起加油,希望本文能对你有所帮助。

    热心网友 时间:2022-04-07 15:53

    MySQL索引类型包括:
    一、普通索引
    这是最基本的索引,它没有任何*。有以下几种创建方式:
    1.创建索引
    代码如下:

    CREATE INDEX indexName ON mytable(username(length));
    如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定 length,下同。

    2.修改表结构

    代码如下:
    ALTER mytable ADD INDEX [indexName] ON (username(length)) -- 创建表的时候直接指定。
    CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, INDEX [indexName] (username(length)) );

    -- 删除索引的语法:
    DROP INDEX [indexName] ON mytable;

    二、唯一索引
    它与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式:

    代码如下:
    CREATE UNIQUE INDEX indexName ON mytable(username(length))
    -- 修改表结构
    ALTER mytable ADD UNIQUE [indexName] ON (username(length))
    -- 创建表的时候直接指定
    CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, UNIQUE [indexName] (username(length)) );

    三、主键索引
    它是一种特殊的唯一索引,不允许有空值。一般是在建表的时候同时创建主键索引:

    代码如下:
    CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, PRIMARY KEY(ID) );

    当然也可以用 ALTER 命令。记住:一个表只能有一个主键。
    四、组合索引
    为了形象地对比单列索引和组合索引,为表添加多个字段:

    代码如下:
    CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, city VARCHAR(50) NOT NULL, age INT NOT NULL );

    为了进一步榨取MySQL的效率,就要考虑建立组合索引。
    二:使用索引的注意事项
    使用索引时,有以下一些技巧和注意事项:
    1.索引不会包含有NULL值的列
    只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为NULL。
    2.使用短索引
    对串列进行索引,如果可能应该指定一个前缀长度。例如,如果有一个CHAR(255)的列,如果在前10个或20个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。
    3.索引列排序
    MySQL查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引。
    4.like语句操作
    一般情况下不鼓励使用like操作,如果非使用不可,如何使用也是一个问题。like “%aaa%” 不会使用索引而like “aaa%”可以使用索引。
    5.不要在列上进行运算

    select * from users where YEAR(adddate)<2007;
    将在每个行上进行运算,这将导致索引失效而进行全表扫描,因此我们可以改成:

    select * from users where adddate<‘2007-01-01';

    6.不使用NOT IN和<>操作。

    三:sql优化原则
    常见的简化规则如下:
    1.不要有超过5个以上的表连接(JOIN)
    2.考虑使用临时表或表变量存放中间结果。
    3.少用子查询
    4.视图嵌套不要过深,一般视图嵌套不要超过2个为宜。
    5.连接的表越多,其编译的时间和连接的开销也越大,性能越不好控制。
    6.最好是把连接拆开成较小的几个部分逐个顺序执行。
    7.优先执行那些能够大量减少结果的连接。
    8.拆分的好处不仅仅是减少SQL Server优化的时间,更使得SQL语句能够以你可以预测的方式和顺序执行。

    如果一定需要连接很多表才能得到数据,那么很可能意味着设计上的缺陷。

    热心网友 时间:2022-04-07 17:11

    大部分开发会了解这样的《开发规范》:创建索引要选择区分度高的字段。他们会认为区分度低的字段不适合创建索引或者不适合添加到组合索引里面。但是这样的操作会导致很多慢查。举例来说:

    select  * from  tab where a=1 and b=2;


    场景 1 

    符合 a=1的记录数有 10w 条记录 ,b=2 有 1000 条记录。如果只是创建idx_a(a),sql 请求通过索引idx_a访问 10w 条件记录,然后还要逐一匹配 10w 条记录中的 status,找到符合 b=2的记录。这个动作会导致慢查。如果创建组合索引idx_ab(a,b),sql 请求通过索引idx_ab可以直接定位到 1000 条记录,无需额外的过滤。这样减少访问 9900 条记录的时间,提升查询速度。

    场景 2 

    符合 a=1的有 100 条记录,status=2 有 10 条记录。其实场景 2 因为数据量比较少,直接访问 100 条记录和定位到 10 条记录的时间消耗相差不大,量变不足以引发质变,可以忽略了。

    Tips:

    声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
    viipoo是不是山寨手机呢? viipoo手机是正规品牌手机吗? 重访湘西有感并怀洞庭湖区作品赏析 怎么查找邮政快递单号查询 ...长小水泡,不疼也不痒,还有我的身上和腿上老痒,但不是..._百度... 有时候晚上老痒 越挠越痒 一抓就一片一片的红 过一阵子就没事了 吃... 最近手老痒,而且越抓越痒?是怎么回事? 最近一个多月晚上身上老痒,一般都在下半夜,手一挠就起一条条的,越挠... 输液多了会有哪些危害 德人易行靠谱吗-德人易行是真是假 求经典特搞笑的笑话 mysql “索引”能重复吗?“唯一索引”与“索引”区别是什么? 求搞笑简短口头禅。 Mysql索引生效条件是什么? 有没有什么特搞笑的喜剧片? 我想知道这个上学的孩子叫什么?特搞笑的头像 求10个特搞笑的笑话 求农村搞笑头像 求卡通情侣头像,特萌特搞笑的那种。尽量多一点,谢谢 求奥特曼动态搞笑头像 你们有没有那种特别搞笑的头像 你有哪些又傻气又好笑的头像? 服装导购员的工作总结与计划 怎样写店铺的人,货,场这三方面来做工作总结 服装销售的工作总结要怎么写? 2021年砖厂发砖开票年终总结怎样写 icloud登陆不进去却一直要我看邮箱验证怎么办 QQ邮箱,如何添加icloud邮箱帐户? 怎么登录iphone的邮箱?手机里icloud里显示帐户未验证,请参阅发送到某某... 苹果手机ID是手机号该怎么登陆iCloud邮箱?! 最近流行的词(特搞笑)是什么? MySQL索引使用限制有哪些 特别搞笑的句子有哪些? mysql有几种索引类型?使用索引时都有那些地方要注意?sql优化原则是什么... 中国拒绝特蕾莎修女的原因是什么? 简述一下mysql的索引匹配规则,有哪些常用的mysql优化方案 什么电影超搞笑? 如何幽默调侃头像很丑 MySql是怎么使用的索引,在哪些情况下会使用 解释mysql中什么是索引?它的作用是什么? 手机桌面怎么设置显示时间和天气? mysql索引? mysql索引优化的规则注意事项 常见降三高的方法有哪些? MySQL的btree索引和hash索引的区别 快速降高血压的方法有哪些? 怎么降低身高啊? 手机怎么设置桌面显示天气和时间? 怎样降三高 vivo手机无法root怎么办?