MySQL - 索引优化案例实操
文章目录
- 生猛干货
- DB Version
- Table
- Case 1 : 联合索引第一个字段用范围不一定会走索引
- 优化一 强制走索引 force index(idx_name_age_position)
- 优化二 覆盖索引优化
- Case 2 : in和or在表数据量比较大的情况会走索引,在表记录不多的情况下会选择全表扫描
- Case 3 : like KK% 一般情况都会走索引
- 特殊例子
- 搞定MySQL
生猛干货
带你搞定MySQL实战,轻松对应海量业务处理及高并发需求,从容应对大场面试
DB Version
mysql> select version();
+------------+
| version() |
+------------+
| 5.7.29-log |
+------------+
1 row in set
默认隔离级别 RR 可重复读
Table
CREATE TABLE `employees` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(24) NOT NULL DEFAULT '' COMMENT '姓名',`age` int(11) NOT NULL DEFAULT '0' COMMENT '年龄',`position` varchar(20) NOT NULL DEFAULT '' COMMENT '职位',`hire_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '入职时间',PRIMARY KEY (`id`),KEY `idx_name_age_position` (`name`,`age`,`position`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='员工记录表';
重点
- 主键id PRIMARY KEY (
id
) - 联合索引 KEY
idx_name_age_position
(name
,age
,position
) USING BTREE
我们向表里写入10万来条数据
Case 1 : 联合索引第一个字段用范围不一定会走索引
mysql> EXPLAIN SELECT * FROM employees WHERE name > 'LiLei' AND age = 22 AND position ='manager';
+----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+-----------------------+
| 1 | SIMPLE | employees | NULL | range | idx_name_age_position | idx_name_age_position | 74 | NULL | 1 | 5 | Using index condition |
+----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+-----------------------+
1 row in setmysql> EXPLAIN SELECT * FROM employees WHERE name > 'Artisan' AND age = 22 AND position ='manager';
+----+-------------+-----------+------------+------+-----------------------+------+---------+------+--------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-----------+------------+------+-----------------------+------+---------+------+--------+----------+-------------+
| 1 | SIMPLE | employees | NULL | ALL | idx_name_age_position | NULL | NULL | NULL | 100175 | 0.5 | Using where |
+----+-------------+-----------+------------+------+-----------------------+------+---------+------+--------+----------+-------------+
1 row in setmysql>
当然了,也不是所有的情况都不走索引, MySQL会基于Cost选择一个合适的 ,如果没有走索引,可能mysql内部可能觉得第一个字段就用范围,结果集应该很大,回表效率不高,还不如就全表扫描
如果没有走索引想要去优化的话怎么办呢?
优化一 强制走索引 force index(idx_name_age_position)
mysql> EXPLAIN SELECT * FROM employees force index(idx_name_age_position) WHERE name > 'Artisan' AND age = 22 AND position ='manager';
+----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+-------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+-------+----------+-----------------------+
| 1 | SIMPLE | employees | NULL | range | idx_name_age_position | idx_name_age_position | 74 | NULL | 50087 | 1 | Using index condition |
+----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+-------+----------+-----------------------+
1 row in set
优化二 覆盖索引优化
mysql> EXPLAIN SELECT name , age , position FROM employees WHERE name > 'Artisan' AND age = 22 AND position ='manager';
+----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+-------+----------+--------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+-------+----------+--------------------------+
| 1 | SIMPLE | employees | NULL | range | idx_name_age_position | idx_name_age_position | 74 | NULL | 50087 | 1 | Using where; Using index |
+----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+-------+----------+--------------------------+
1 row in setmysql>
name , age , position 是联合索引,在索引树上,同时索引树上的叶子节点还会关联一个主键id , 如果查询 * 的话,还要根据id去主键索引上去查找其他字段,需要回表, 如果仅查询二级索引树idx_name_age_position
上的字段,那就无需回表操作了,效率自然高一些。
Case 2 : in和or在表数据量比较大的情况会走索引,在表记录不多的情况下会选择全表扫描
mysql> EXPLAIN SELECT * FROM employees WHERE name in ('LiLei','HanMeimei','Lucy') AND age = 22 AND position ='manager';
+----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+-----------------------+
| 1 | SIMPLE | employees | NULL | range | idx_name_age_position | idx_name_age_position | 140 | NULL | 3 | 100 | Using index condition |
+----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+-----------------------+
1 row in setmysql> EXPLAIN SELECT * FROM employees WHERE (name = 'LiLei' or name = 'HanMeimei') AND age = 22 AND position ='manager';
+----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+-----------------------+
| 1 | SIMPLE | employees | NULL | range | idx_name_age_position | idx_name_age_position | 140 | NULL | 2 | 100 | Using index condition |
+----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+-----------------------+
1 row in set
再搞个小表 ,和 employees 一模一样哈,连索引也得一样,插入3条数据 。
CREATE TABLE `employees_2` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(24) NOT NULL DEFAULT '' COMMENT '姓名',`age` int(11) NOT NULL DEFAULT '0' COMMENT '年龄',`position` varchar(20) NOT NULL DEFAULT '' COMMENT '职位',`hire_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '入职时间',PRIMARY KEY (`id`),KEY `idx_name_age_position` (`name`,`age`,`position`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='员工记录表';INSERT INTO employees_2(name,age,position,hire_time) VALUES('LiLei',22,'manager',NOW());
INSERT INTO employees_2(name,age,position,hire_time) VALUES('HanMeimei', 23,'dev',NOW());
INSERT INTO employees_2(name,age,position,hire_time) VALUES('Lucy',23,'dev',NOW());
mysql> EXPLAIN SELECT * FROM employees_2 WHERE name in ('LiLei','HanMeimei','Lucy') AND age = 22 AND position ='manager';
+----+-------------+-------------+------------+------+-----------------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------------+------------+------+-----------------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | employees_2 | NULL | ALL | idx_name_age_position | NULL | NULL | NULL | 3 | 100 | Using where |
+----+-------------+-------------+------------+------+-----------------------+------+---------+------+------+----------+-------------+
1 row in setmysql>
为什么呢? 就几条数据的话, 结合B+树的结构, MySQL认为从根节点开始向下找,还不如直接从叶子节点从头开始扫描快呢
Case 3 : like KK% 一般情况都会走索引
结合索引树 , like KK% 可以理解为就是按照 = KK 查询
mysql> EXPLAIN SELECT * FROM employees WHERE name like 'LiLei%' AND age = 22 AND position ='manager';
+----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+-----------------------+
| 1 | SIMPLE | employees | NULL | range | idx_name_age_position | idx_name_age_position | 140 | NULL | 1 | 5 | Using index condition |
+----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+-----------------------+
1 row in setmysql> EXPLAIN SELECT * FROM employees_2 WHERE name like 'LiLei%' AND age = 22 AND position ='manager';
+----+-------------+-------------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+-----------------------+
| 1 | SIMPLE | employees_2 | NULL | range | idx_name_age_position | idx_name_age_position | 140 | NULL | 1 | 33.33 | Using index condition |
+----+-------------+-------------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+-----------------------+
1 row in set
原因: 索引下推 MySQL -索引下推 Index Condition Pushdown 初探
特殊例子
一般情况 ,但也不绝对。看下面这个例子
假设你这个表 的name字段 是以Artisan开头的,从Artisan1 到Artisan100000
再去like的话 ,mysql会基于cost,自主选择 ,比如如下走了全表扫描。
搞定MySQL
MySQL - 索引优化案例实操相关推荐
- MySQL第12天:MySQL索引优化分析之性能优化案例实践
MySQL索引优化分析之性能优化案例实践 执行计划中各select_type含义可以看:MySQL第11天:MySQL索引优化分析之性能分析 https://weibo01.blog.csdn.net ...
- Mysql之索引优化案例
Mysql之索引优化案例 1.单表简单案例 1.1创建表 1.2 问题: 1.3 解决:新建索引 1.4 再次执行 2.双表简单案例 2.1创建表并插入数据 2.2 由于是LEFT JOIN,所以左表 ...
- MySQL——索引优化分析
为什么你写的sql查询慢?为什么你建的索引常失效?通过本章内容,你将学会MySQL性能下降的原因,索引的简介,索引创建的原则,explain命令的使用,以及explain输出字段的意义.助你了解索引, ...
- 尚硅谷大数据技术Spark教程-笔记09【SparkStreaming(概念、入门、DStream入门、案例实操、总结)】
尚硅谷大数据技术-教程-学习路线-笔记汇总表[课程资料下载] 视频地址:尚硅谷大数据Spark教程从入门到精通_哔哩哔哩_bilibili 尚硅谷大数据技术Spark教程-笔记01[SparkCore ...
- 大数据之Spark案例实操完整使用(第六章)
大数据之Spark案例实操完整使用 一.案例一 1.准备数据 2.需求 1:Top10 热门品类 3.需求说明 方案一. 实现方案二 实现方案三 二 .需求实现 1.需求 2:Top10 热门品类中每 ...
- mysql高级篇(二)mysql索引优化分析
mysql高级篇笔记 mysql高级篇(一)mysql的安装配置.架构介绍及SQL语句的复习. mysql高级篇(二)mysql索引优化分析. mysql高级篇(三)查询截取分析(慢查询日志).主从复 ...
- MySQL第10天:MySQL索引优化分析之索引介绍
MySQL索引优化分析之索引简介 1.索引是什么? 2.索引优势.劣势 3.索引分类.基本语法 4.索引结构 5.哪些情况需要创建索引? 6.哪些情况不需要创建索引? ---------------- ...
- MySQL索引优化分析
转载来源:https://www.cnblogs.com/itdragon/p/8146439.html MySQL索引优化分析 为什么你写的sql查询慢?为什么你建的索引常失效?通过本章内容,你将学 ...
- 数据模型同学看过来|代码案例实操来袭
去年年底,央行开出反洗钱罚单,多家银行合计被罚1040万元. 当时,中国人民银行石家庄中心支行披露的反洗钱行政处罚信息公示表显示,因涉及未按照规定履行客户身份识别义务等,中行.邮储.浦发三家银行以及阳 ...
最新文章
- 腾讯第100个开源项目:微信开源推理加速工具TurboTransformers
- 诚信,聪明,快乐,地位与竞争
- linux下文件的压缩和解压缩
- linux 五种IO模型 简介
- hdu4845 状态压缩BFS
- UNIX V6内核源码剖析——unix v6 全貌
- 改造消费方解决地址硬编码问题
- 揭开不一样的世界,这5部纪录片绝对不能错过!
- 新势力盯上了“新能源车险”
- arcgis离线地图Java_ArcGIS API For Android离线地图的实现
- 图书管理 python excel_爬取python异步社区图书并写入excel
- 程序员必备的八大排序算法
- vue+eleme upload 上传图片(含gif动图) canvas压缩,base64转blob对象
- makefile终极目标
- MSF编码与upx加壳过杀软
- 购买30万住房也能落户武汉
- PPP 协议及配置解析
- vscode 代码格式化及快捷键
- Vue-高德地图-立体多边形绘制
- HBase Windows 安装
热门文章
- android 之ListView总结(一个综合实例)
- 相对布局(RelativeLayout)
- EventBus3.0 List事件遇到的坑
- pytorch 入门(二) cnn 手写数字识别
- vue里面怎么删除部分页面_基于VUE选择上传图片并页面显示(图片可删除)
- Leetcode 739. 每日温度 (每日一题 20211014)
- Python~爬虫~2(requests)
- 文巾解题 20有效的括号
- Hadoop-2.2.0学习之二HDFS联盟
- 中兴服务器raid配置_-服务器Raid卡更换后如何恢复硬盘Raid组信息