MySQL索引

什么是索引

索引类似于书本的目录,是存储引擎用于提高数据库表的访问速度的一种数据结构。在mysql内部,将热点数据,以B+树的形式将所有page页,进行组织成一定的数据结构,再用其配套的查找算法进行查找,叫做索引查询。

为什么要有索引

数据是存储在磁盘上的,查询数据时,如果没有索引,会加载所有数据到内存,依次进行检查,读取磁盘的次数较多。

有了索引,就不需要加载所有数据,因为B+树的高度一般在2-4层,最多只需要读取2-4次磁盘,大大提升了查询速度。

索引的类型

按照数据结构分类:

BTree索引

MySQL数据库使用最多的索引类型就是BTree索引,底层基于B+树的数据结构来实现的。B+树是基于B树和叶子节点顺序访问指针进行实现,它具有B树的平衡性,并且通过顺序访问指针来提高区间查询的性能。

哈希索引

哈希索引是基于哈希表实现的,对于每一行数据,存储引擎会对索引列进行哈希计算得到哈希码,并且哈希算法要尽量保证不同的列值计算出来的哈希码值是不同的,将哈希码的值作为哈希表的key值,将数据行的指针作为哈希表的value值。

全文索引(fulltext)

目前只有MyISAM引擎支持(InnoDB在1.2.x之后也支持)。只有char、varchar、text列上可以创建全文索引。

RTree索引

RTree在MySQL很少使用,仅支持geometry数据类型。相对于BTree,RTree的优势在于范围查找。

为什么不是其他数据结构

B+ vs 链表

链表需要线性遍历,搜索效率低。

B+ vs 二叉搜索树

二叉搜索树的搜索效率不稳定,在极端情况下会退化成线性结构,同样存在搜索效率低的问题。

B+ vs AVL树/红黑树

虽然AVL树和红黑树是平衡或者近似平衡,但毕竟是二叉结构,相比较多阶B+,意味着树整体过高,同样是自顶向下查找,层高越低,意味着系统与磁盘有着更少的IO交互。

B+ vs 哈希

B+索引与哈希索引的区别:

  1. 哈希索引不支持排序,因为哈希表是无序的。

  2. 哈希表不支持范围查找。

  3. 哈希表不支持模糊查询及多列索引的最左前缀匹配。

  4. 因为哈希表中会存在哈希冲突,所以哈希索引的性能是不稳定的,而B+树索引的性能是相对稳定的,每次查询都是从根节点到叶子节点。

官方的索引实现方式中,MySQL是支持哈希索引的,不过InnoDB和MyISAM并不支持。虽然哈希的查找速度很快,但对于范围查找就明显不行。

B+ vs B

B+树与B树的区别:

  1. B树节点,既有数据,又有Page指针,而B+,只有叶子节点有数据,其它目录页,只有键值和Page指针。

  2. B+叶子节点,全部相连,而B没有。

为何选择B+:

  1. 非叶子节点不存储data,这样一个节点就可以存储更多的key,可以使得树更矮,所以IO操作次数更少。

  2. 叶子节点相连,更便于范围查找。

聚簇索引和非聚簇索引

聚簇索引

 

像InnoDB这种,将用户数据与索引数据放在一起的索引方案,叫做聚簇索引。

非聚簇索引

 

向MyISAM这种,将用户数据与索引数据分离的方案,叫做非聚簇索引。

区别

1.叶节点存放数据不同

MyISAM引擎同样使用B+树作为索引结果,叶节点的data域存放的是数据记录的地址。MyISAM最大的特点是,将索引Page和数据Page分离,也就是叶子节点没有数据,只有对应数据的地址。相较于InnoDB索引,InnoDB是将索引和数据放在一起的。

2.MyISAM不需要回表查询

MySQL除了默认会建立主键索引外,用户也有可能建立按照其他列信息建立的索引,一般这种索引叫做辅助(普通)索引。

对于MyISAM,建立辅助(普通)索引和建立主键索引没有差别,无非就是主键不饿能重复,而非主键可以重复。叶子节点放的同样是指向改行数据的指针。

而对于InnoDB,InnoDB的非主键索引中的叶子节点并没有数据,而只有对应记录的key值,所以通过辅助(普通)索引,找到目标记录,需要两遍索引:首先检验辅助索引获得主键,然后用主键到主键索引中检索获得记录。这种过程,就叫做回表查询。

总结

这样看来MyISAM引擎是优于InnoDB引擎的,因为MyISAM做到了将用户数据与索引数据进行解耦,一方面降低了数据之间的耦合度,另一方面,提升了查找效率。而且MyISAM还支持全文索引,更方便用于进行查找,但为什么InnoDB任然是主流呢?是因为InnoDB支持事务,而MyISAM并不支持。

索引设计原则

  1. 使用区分度高的字段作为索引列,索引效果更好。

  2. 比较频繁作为查询条件的字段应该创建索引。

  3. 不会出现在where子句中的字段不该创建索引。

  4. 更新非常频繁的字段不适合创建索引。

  5. 尽量使用短索引,对于较长的字符串进行索引时,应该指定一个较短的前缀长度,因为较小的索引使得目录页中能存放更多的目录,能有效的减少高度,使系统与磁盘的IO次数减少,查询速度加快。

  6. 索引不是越多越好,每个索引都需要额外的物理空间,维护也需要花费时间。

索引失效

1.对于组合索引,不使用组合索引最左边的字段,则不会使用索引。

2.以%开头的like查询如%abc,无法使用索引;非%开头的like查询,如abc%,相当于范围查询,会使用索引。

3.查询条件中列类型是字符串,没有使用引号,可能会因为类型不同发生隐式转换,使索引失效。

4.判断索引列是否不等于某个值时。

5.对索引列进行运算。

6.查询条件使用 or 连接。

索引操作

创建主键索引

方式一:

-- 在创建表的时候,直接在字段名后指定 primary key create table user1(id int primary key, name varchar(30));

方式二:

-- 在创建表的最后,指定某列或某几列为主键索引 create table user2(id int, name varchar(30), primary key(id));

方式三:

create table user3(id int, name varchar(30)); -- 创建表以后再添加主键 alter table user3 add primary key(id);

创建唯一索引

方式一:

-- 在表定义时,在某列后直接指定unique唯一属性。 create table user4(id int primary key, name varchar(30) unique);

方式二:

`-- 创建表时,在表的后面指定某列或某几列为unique create table user5(id int primary key, name varchar(30), unique(name));

方式三:

create table user6(id int primary key, name varchar(30)); alter table user6 add unique(name);

创建普通索引

方式一:

create table user8(id int primary key, name varchar(20), email varchar(30), index(name) --在表的定义最后,指定某列为索引 );

方式二:

create table user9(id int primary key, name varchar(20), email varchar(30)); alter table user9 add index(name); --创建完表以后指定某列为普通索引

方式三:

create table user10(id int primary key, name varchar(20), email varchar(30)); -- 创建一个索引名为 idx_name 的索引 create index idx_name on user10(name);

创建全文索引

当对文章字段或有大量文字的字段进行检索时,会使用到全文索引。MySQL提供全文索引机制,但是有要求,要求表的存储引擎必须是MyISAM,而且默认的全文索引支持英文,不支持中文。如果对中文进行全文检索,可以使用sphinx的中文版(coreseek)。

CREATE TABLE articles ( id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, title VARCHAR(200), body TEXT, FULLTEXT (title,body) )engine=MyISAM;

查询索引

方式一:show keys from 表名;

方式二:show index from 表名;

方式三(信息比较简略):desc 表名;

删除索引

方式一:

-删除主键索引:alter table 表名 drop primary key;

方式二:

-其他索引的删除: alter table 表名 drop index 索引名; 索引名就是show keys from 表名中的Key_name 字段。

方式三:

drop index 索引名 on 表名;

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习编程?其实不难,不过在学习编程之前你得先了解你的目的是什么?这个很重要,因为目的决定你的发展方向、决定你的发展速度。
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面设计类、前端与移动、开发与测试、营销推广类、数据运营类、运营维护类、游戏相关类等,根据不同的分类下面有细分了不同的岗位。
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生学习Java开发,但要结合自身的情况,先了解自己适不适合去学习Java,不要盲目的选择不适合自己的Java培训班进行学习。只要肯下功夫钻研,多看、多想、多练
Can’t connect to local MySQL server through socket \'/var/lib/mysql/mysql.sock问题 1.进入mysql路径
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 sqlplus / as sysdba 2.普通用户登录
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服务器有时候会断掉,所以写个shell脚本每五分钟去判断是否连接,于是就有下面的shell脚本。
BETWEEN 操作符选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。
假如你已经使用过苹果开发者中心上架app,你肯定知道在苹果开发者中心的web界面,无法直接提交ipa文件,而是需要使用第三方工具,将ipa文件上传到构建版本,开...
下面的 SQL 语句指定了两个别名,一个是 name 列的别名,一个是 country 列的别名。**提示:**如果列名称包含空格,要求使用双引号或方括号:
在使用H5混合开发的app打包后,需要将ipa文件上传到appstore进行发布,就需要去苹果开发者中心进行发布。​
+----+--------------+---------------------------+-------+---------+
数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一个数组变量,比如 numbers,然后使用 nu...
第一步:到appuploader官网下载辅助工具和iCloud驱动,使用前面创建的AppID登录。
如需删除表中的列,请使用下面的语法(请注意,某些数据库系统不允许这种在数据库表中删除列的方式):
前不久在制作win11pe,制作了一版,1.26GB,太大了,不满意,想再裁剪下,发现这次dism mount正常,commit或discard巨慢,以前都很快...
赛门铁克各个版本概览:https://knowledge.broadcom.com/external/article?legacyId=tech163829
实测Python 3.6.6用pip 21.3.1,再高就报错了,Python 3.10.7用pip 22.3.1是可以的
Broadcom Corporation (博通公司,股票代号AVGO)是全球领先的有线和无线通信半导体公司。其产品实现向家庭、 办公室和移动环境以及在这些环境...
发现个问题,server2016上安装了c4d这些版本,低版本的正常显示窗格,但红色圈出的高版本c4d打开后不显示窗格,
TAT:https://cloud.tencent.com/document/product/1340