mysql索引_MySQL索引介绍和实战

索引是什么

MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。

可以得到索引的本质:索引是数据结构,索引的目的是提高查询效率,可以类比英语新华字典,根据目录定位词语

如果没有目录呢,就需要从A到Z,去遍历的查找一遍,一个一个找和直接根据目录定位到数据,差的就是天壤之别

索引底层数据结构

数据库除了存储数据本身之外,还维护着一个满足特定查找算法的数据结构,这些结构以某种方式指向数据,这样就可以基于这些数据结构实现高效查找算法。这种结构就是索引,MySQL中索引是B+树实现的,每个索引都对应一棵B+树

6a02a969f2fe3da45b3c3adebee757dd.png

索引的优势

提高数据检索效率,降低数据库IO成本

通过索引列对数据进行排序,降低数据排序成本,降低了CPU消耗

索引的劣势

一个索引都为对应一棵B+树,树中每一个节点都是一个数据页,一个页默认会占用16KB的存储空间,所以一个索引也是会占用磁盘空间的。(空间的代价)

索引是对数据的排序,当对表中的数据进行增、删、改操作时,都要维护修改内容涉及到的B+树索引。所以在进行这些操作时需要额外的时间进行一些记录移动,页面分裂、页面回收等操作来维护索引(时间上的代价)

索引语法

以test_user表为例,建表sql如下

CREATE TABLE`test_user` (

`id`int(11) NOT NULL AUTO_INCREMENT COMMENT '主键id',

`user_id` varchar(36) NOT NULL COMMENT '用户id',

`user_name` varchar(30) NOT NULL COMMENT '用户名称',

`phone`varchar(20) NOT NULL COMMENT '手机号码',

`lan_id`int(9) NOT NULL COMMENT '本地网',

`region_id`int(9) NOT NULL COMMENT '区域',

`create_time`datetime NOT NULL COMMENT '创建时间',PRIMARY KEY(`id`),KEY `idx_user_id` (`user_id`)

) ENGINE=InnoDB AUTO_INCREMENT=1010001 DEFAULT CHARSET=utf8mb4;

1.查看索引:SHOW INDEX FROM table_name\G

SHOW INDEX FROM test_user;

4e564236426badd02b30321dfe1adbca.png

2.删除索引:DROP INDEX [indexName] ON mytable;

DROP INDEX idx_user_id ON test_user;

0e2631dd6a53b353c584e1f88136abba.png

3.创建索引 alter tableName add [unique] index [indexName] on (columnName (length) )

ALTER TABLE test_user ADD INDEX idx_user_id(user_id);

d151917386788c500c33db24237fc3d6.png

哪些情况需要建索引

主键自动建立唯一索引

频繁作为查询的条件的字段应该创建索引

查询中与其他表关联的字段,外键关系建立索引

频繁更新的字段不适合创建索引:因为每次更新不单单是更新了记录还会更新索引,加重IO负担

Where条件里用不到的字段不创建索引

单间/组合索引的选择问题(在高并发下倾向创建组合索引)

查询中排序的字段,若通过索引去访问将大大提高排序的速度

查询中统计或者分组字段

哪些不适合建索引

表记录太少

经常增删改的表

数据重复且分布平均的表字段,如果某个数据列包含许多重复的内容,为它建立索引就没有太大的实际效果。

索引实战

我们在test_user表中有100万数据

4409aef8fc0a6b01822cbef6a0f16e5d.png

优化一:使用全部索引

1.不加索引,关闭缓存查一条数据

SELECT SQL_NO_CACHE * FROM `test_user` WHERE phone='15190427892' AND lan_id=317 AND region_id=92

605971eca37e7e8e68f7992b07d9fe9c.png

2.加一条复合索引

ALTER TABLE test_user ADD INDEX idx_phone_lan_region(phone,lan_id,region_id);

再查一次,看结果

ddf48e13e9c3f948142d4f8d92fe4ab9.png

可以看到,加了索引以后,查询效率提高了很多

这里我们建立的复合索引包含的3个字段,查询的时候全部用到了,而且where中的条件严格按照索引顺序,这样查询效率是最高的

我们使用EXPLAIN关键字看一下

37ca17c89b8f5c5261d607976eb22063.png

优化二:最左前缀法则

我们把上面那个例子的第一个插件条件删掉

EXPLAIN SELECT SQL_NO_CACHE * FROM `test_user` WHERE lan_id=317 AND region_id=92;

我们使用EXPLAIN关键字看一下

de2c1486a74d724ae04e745340f193e0.png

因此,我们得出结论:如果建立的是复合索引,索引的顺序要按照建立时的顺序,即从左到右,如:a->b->c(和 B+树的数据结构有关)

无效索引举例

a->c:a 有效,c 无效

b->c:b、c 都无效

c:c 无效

优化三:不要对索引做以下处理

计算,如:+、-、*、/、!=、<>、is null、is not null、or

函数,如:sum()、round()等等

手动/自动类型转换,如:id = "1",本来是数字,给写成字符串了

我们以!=为例演示,我们使用EXPLAIN关键字看一下

a727dd30234b55b267323ef744915b87.png

优化四:索引不要放在范围查询右边

比如复合索引:a->b->c,当 where a="" and b>10 and c="",这时候只能用到 a 和 b,c 用不到索引,因为在范围之后索引都失效(和 B+树结构有关)

如下

EXPLAIN SELECT SQL_NO_CACHE * FROM `test_user` WHERE phone='15190427892' AND lan_id>317 AND region_id=92;

我们使用EXPLAIN关键字看一下

4ccadb63f203e0308178b0dc019e6353.png

我们把最后一个条件删除,再看一下

91c2553f39ee6ca5ed349f79220c0a0d.png

优化五:减少 select * 的使用

select *会查询很多不必要的字段,造成不必要的网络传输和IO消耗

优化六:like 模糊搜索

失效情况

like "%张三%"

like "%张三"

4ff84f17bac4e9baad7cc01d813da118.png

解决方案

使用复合索引,即 like 字段是 select 的查询字段,如:select name from table where name like "%张三%"

使用 like "张三%"

ec00941b313db3ecc44f8f6780aeebb1.png

1bcfd4a01f70249eeac45f852fd064ad.png

优化七:order by 优化

当查询语句中使用 order by 进行排序时,如果没有使用索引进行排序,会出现 filesort 文件内排序,这种情况在数据量大或者并发高的时候,会有性能问题,需要优化。

filesort 出现的情况举例

order by 字段不是索引字段

order by 字段是索引字段,但是 select 中没有使用覆盖索引,如:select * from staffs order by age asc;

order by 中同时存在 ASC 升序排序和 DESC 降序排序,如:select a, b from staffs order by a desc, b asc;

order by 多个字段排序时,不是按照索引顺序进行 order by,即不是按照最左前缀法则,如:select a, b from staffs order by b asc, a asc;

如下情况没有索引

21e385fb31d45ef1846ebd10ebdf9233.png

filesort 文件内排序会在内存开辟一块空间,然后把数据复制了一份放到这个空间内,再进行排序,这个是很影响性能的

我们可以为这个字段建一个索引

ALTER TABLE test_user ADD INDEX idx_create_time(create_time);

0208c0b38110e739d3249c5e0e8cf706.png

索引层面解决方法

使用主键索引排序

按照最左前缀法则,并且使用覆盖索引排序,多个字段排序时,保持排序方向一致

在 SQL 语句中强制指定使用某索引,force index(索引名字)

不在数据库中排序,在代码层面排序

优化八:group by

其原理也是先排序后分组,其优化方式可参考order by。where高于having,能写在where限定的条件就不要去having限定了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/527195.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql安装需要注意什么意思_mysql 安装过程及注意事项

1.1. 下载&#xff1a;我下载的是64位系统的zip包&#xff1a;下载zip的包&#xff1a;下载后解压&#xff1a;D:\软件安装包\mysql-5.7.20-winx641.2. 配置环境变量&#xff1a;变量名&#xff1a;MYSQL_HOME变量值&#xff1a;E:\mysql-5.7.20-winx64path里添加&#xff1a;%…

gitlab 端口_安装Gitlab-注意端口

文档本身并没有什么特殊&#xff0c;安装也很简单&#xff0c;只是修改端口这里如果有需要的可以看一下安装Gitlab[rootdeploy ~]# sudo yum -y install gitlab-ce默认端口是8080&#xff0c;避免冲突还是修改一下[rootlocalhost ~]# cat /etc/gitlab/gitlab.rb |grep 192.168.…

MySQL read-c_技术分享 | MySQL C API 参数 MYSQL_OPT_READ_TIMEOUT 的一些行为分析

作者&#xff1a;戴岳兵MYSQL_OPT_READ_TIMEOUT 是 MySQL c api 客户端中用来设置读取超时时间的参数。在 MySQL 的官方文档中&#xff0c;该参数的描述是这样的&#xff1a;MYSQL_OPT_READ_TIMEOUT (argument type: unsigned int *)The timeout in seconds for each attempt t…

mysql解释中fitered_MySQL的explain中的参数说明

1、id每个被独立执行的操作的标识&#xff0c;表示对象被操作的顺序&#xff1b;id值大&#xff0c;先被执行&#xff1b;如果相同&#xff0c;执行顺序从上到下。若没有子查询和联合查询&#xff0c;id则都是1。Mysql会按照id从大到小的顺序执行query&#xff0c;在id相同的情…

vue脚手架搭建项目_复习之vue脚手架搭建项目的两种方法

安装脚手架node 版本要求&#xff1a; > 8.9 。关于旧版本&#xff1a;如果在这之前已经全局安装了旧版本的vue-cli(1.x 或 2.x)&#xff0c;那么需要先卸载掉。卸载旧版本运行&#xff1a;npm uninstall vue-cli -g 或 yarn global remove vue-cli。安装vue/cli&#xff1a…

pythonsocket中tcp通信接收不到数据_TCP 为什么三次握手而不是两次握手(正解版)...

先说结论为了实现可靠数据传输&#xff0c; TCP 协议的通信双方&#xff0c; 都必须维护一个序列号&#xff0c; 以标识发送出去的数据包中&#xff0c; 哪些是已经被对方收到的。 三次握手的过程即是通信双方相互告知序列号起始值&#xff0c; 并确认对方已经收到了序列号起始…

mysql无法启动如何备份文件_mysql 5.7 停电导致无法启动、如何备份数据,重新安装mysql...

用于记录服务器停电导致&#xff0c;mysql启动失败后&#xff0c;如何备份数据&#xff0c;重新安装mysql&#xff0c;主要分为数据备份&#xff0c;mysql重新安装。1、mysql无法启动时&#xff0c;进行数据备份。执行&#xff1a;systemctl start mysqld&#xff0c;启动失败。…

python tkinter entry默认值_Python ---(六)Tkinter窗口组件:Entry

The Tkinter Entry Widget##简介Entry(输入框)组件通常用于获取用户的输入文本。##何时使用 Entry 组件&#xff1f;Entry 组件仅允许用于输入一行文本&#xff0c;如果用于输入的字符串长度比该组件可显示空间更长&#xff0c;那内容将被滚动。这意味着该字符串将不能被全部看…

java 静态块初始化_简单了解java中静态初始化块的执行顺序

这篇文章主要介绍了简单了解java中静态初始化块的执行顺序,文中通过示例代码介绍的非常详细&#xff0c;对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下在java中&#xff0c;其应该是先于所有的方法执行。下面是测试代码&#xff1a;public class Test1 {st…

java 常量区存放 new_java---堆、栈、常量池的存储数据

说到Java中堆、栈和常量池&#xff0c;首先还是看看他们各自存放的数据类型吧&#xff01;栈&#xff1a;Java的JVM的内存可分为3个区&#xff1a;堆(heap)、栈(stack)和方法区(method)也叫静态存储区。堆区:(存放所有new出来的对象&#xff1b;)1.存储的全部是对象&#xff0c…

log加时间 securecrt_SecureCRT配置自动记录日志

很多人用SecureCRT时&#xff0c;希望自动记录日志&#xff0c;一个是方便以后查阅&#xff0c;一个是对自己的操作有个记录。可以看看自己做了什么操作&#xff0c;有时甚至可以看看之前是不是犯了什么错&#xff0c;是个很不错的功能。设置很简单&#xff0c;还可以根据连接的…

java泛型改进_java泛型高级篇 - 真正理解协变与逆变 | 鱼儿的博客

无论你是否听过java泛型的协变与逆变&#xff0c;我们直接进入例子&#xff0c;一起来看一下java泛型比较高级的用法。例子1&#xff1a;copy函数第1个例子我们实现copy函数&#xff0c;它将List中的元素复制到List中。JavaList src Arrays.asList(1,2,3,4,5);List dst new A…

java实训遇到问题解决_「instantiationexception」关于java出现 java.lang.InstantiationException异常的分析与解决方案 - seo实验室...

instantiationexceptionjava.lang.instantiationexception 是指不能实例化某个对象&#xff0c;一般在我们使用java反射机制去创建某个对象的时候实例化到了一个抽象类或者接口(java中抽象类和接口是不能被实例化)&#xff0c;而今天我遇到的则是我在使用反射机制实例化某个持久…

java对外发布接口文档_java之接口文档规范

一、xxxxxx获取指定任务爬取的所有url的接口接口名称&#xff1a;xxxxxx获取指定任务爬取的所有url的接口访问链接&#xff1a;http://IP:PORT/crwalTask/findUrlExceptionById?ctIdctIdVal&timetimeVal&limitlimitVal传入参数类型&#xff1a;String,int参数内容:返回…

java画好看坦克_坦克大战第一节——画出自己的坦克(新手篇)

刚刚开始学习java&#xff0c;对java不是很熟悉&#xff0c;但是自己的兴趣挺喜欢java。现在自己在自学java做一个小游戏&#xff0c;坦克大战。自己现在完成了画出自己的坦克和坦克的移动方向。希望各位大神指导一下我这个刚刚学java的新手小白。我会每完成一个阶段&#xff0…

java中timer类包_Java~util包中Timer的使用, 演示cancel方法 和 对比schedule和scheduleAtFixedRate方法...

TimerTimer类的主要作用就是设置计划任务&#xff0c;但封装任务的类却是TimerTask类执行计划任务的代码要放人TimerTask的子类中&#xff0c;因为TimerTask是一个抽象类。而且要重写其run方法 因为这是一个抽象方法.常见问题任务执行完了, 但进程并没有销毁,通过源码查看构造方…

centos eclipse java_CentOS7 安装 Eclipse

咳咳&#xff0c; 虽然大神的 Linux 都是命令行的&#xff0c; 但是谁让 LZ 是 LJ&#xff0c; 桌面开俩终端不觉得更好么。。。CentOS7 安装 Eclipse&#xff0c; 比在 Window 系统下安装 Eclipse 要复杂得多。。参考 &#xff1a; https://segmentfault.com/a/11900000026517…

java opencv orb_opencv python ORB算法

理论ORB(Oriented FAST and Rotated BRIEF)是一种快速特征点提取和描述的算法,这个算法是由Ethan Rublee, Vincent Rabaud, Kurt Konolige以及Gary R.Bradski在2011年一篇名为“ORB&#xff1a;An Efficient Alternative to SIFTor SURF”的文章中提出.ORB算法分为两部分&#…

php中define的参数_php中define的用法有哪些

php中define的用法&#xff1a;1、【define()】函数定义一个常量&#xff1b;2、定义常量名称及值&#xff0c;代码为【define(name,value,case_insensitive)】&#xff1b;3、定义一个大小写敏感的常量。php中define的用法&#xff1a;1、define()函数理解1define()函数定义一…

php 登陆微博,PHP调用微博接口实现微博登录的方法示例

在平时项目开发过程中&#xff0c;除了注册本网站账号进行登录之外&#xff0c;还可以调用第三方接口进行登录网站。这里以微博登录为例。微博登录包括身份认证、用户关系以及内容传播。允许用户使用微博帐号登录访问第三方网站&#xff0c;分享内容&#xff0c;同步信息。1、首…