MySQL优化篇:单表索引失效
文章目录
- 1、准备环境
- 2、全值匹配我最爱
- 2、最佳作前缀法则
- 3、不要在索引列上做任何计算
- 3.1 在查询列上使用了函数
- 3.2 在查询列上做了转换
- 4、索引列上不能有范围查询
- 5、尽量使用覆盖索引
- 6、使用不等于(!=或者<>)的时候
- 7、字段的is not null和is null
- 8、like的前后模糊匹配
- 9、减少使用or
- 10、索引使用口诀
- 11、索引示例巩固
1、准备环境
建表并插入数据
CREATE TABLE `dept` (`id` INT(11) NOT NULL AUTO_INCREMENT,`deptName` VARCHAR(30) DEFAULT NULL, `address` VARCHAR(40) DEFAULT NULL, ceo INT NULL , PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;CREATE TABLE `emp` (`id` INT(11) NOT NULL AUTO_INCREMENT, `empno` INT NOT NULL , `name` VARCHAR(20) DEFAULT NULL, `age` INT(3) DEFAULT NULL, `deptId` INT(11) DEFAULT NULL, PRIMARY KEY (`id`)#CONSTRAINT `fk_dept_id` FOREIGN KEY (`deptId`) REFERENCES `t_dept` (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
2、全值匹配我最爱
执行以下SQL语句
EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE emp.age=30;
EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE emp.age=30 and deptid=4;
EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE emp.age=30 and deptid=4 AND emp.name = 'abcd';
以上语句执行情况如下所示:
mysql> explain select SQL_NO_CACHE * from emp where age=30;
+----+-------------+-------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+--------+-------------+
| 1 | SIMPLE | emp | ALL | NULL | NULL | NULL | NULL | 500493 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+--------+-------------+
1 row in setmysql> explain select SQL_NO_CACHE * from emp where age=30 and deptid=4;
+----+-------------+-------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+--------+-------------+
| 1 | SIMPLE | emp | ALL | NULL | NULL | NULL | NULL | 500493 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+--------+-------------+
1 row in setmysql> explain select SQL_NO_CACHE * from emp where age=30 and deptid=4 and name='abcd';
+----+-------------+-------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+--------+-------------+
| 1 | SIMPLE | emp | ALL | NULL | NULL | NULL | NULL | 500493 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+--------+-------------+
1 row in set
建立索引
CREATE INDEX idx_age_deptid_name ON emp(age,deptid,NAME);
再次执行上述SQL语句
mysql> explain select SQL_NO_CACHE * from emp where age=30;
+----+-------------+-------+------+---------------------+---------------------+---------+-------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------------+---------------------+---------+-------+-------+-------------+
| 1 | SIMPLE | emp | ref | idx_name_deptid_age | idx_name_deptid_age | 5 | const | 47248 | Using where |
+----+-------------+-------+------+---------------------+---------------------+---------+-------+-------+-------------+
1 row in setmysql> explain select SQL_NO_CACHE * from emp where age=30 and deptid=4;
+----+-------------+-------+------+---------------------+---------------------+---------+-------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------------+---------------------+---------+-------------+------+-------------+
| 1 | SIMPLE | emp | ref | idx_name_deptid_age | idx_name_deptid_age | 10 | const,const | 5 | Using where |
+----+-------------+-------+------+---------------------+---------------------+---------+-------------+------+-------------+
1 row in setmysql> explain select SQL_NO_CACHE * from emp where age=30 and deptid=4 and name='abcd';
+----+-------------+-------+------+---------------------+---------------------+---------+-------------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------------+---------------------+---------+-------------------+------+-------------+
| 1 | SIMPLE | emp | ref | idx_name_deptid_age | idx_name_deptid_age | 73 | const,const,const | 1 | Using where |
+----+-------------+-------+------+---------------------+---------------------+---------+-------------------+------+-------------+
1 row in setmysql>
结论:全值匹配我最爱指的是,查询的字段按照顺序在索引中都可以匹配到。
SQL中查询字段的顺序,跟使用索引中字段的顺序,没有关系。优化器会在不影响SQL执行结果的前提下,进行自动优化。
2、最佳作前缀法则
查询字段与索引字段顺序的不同会导致,索引无法充分使用,甚至索引失效。
原因:使用复合索引,需要遵循最佳左前缀法则,即如果索引包含多列,要遵守最左前缀法则,指的是查询从索引的最左前列开始并不跳过索引中的列
**结论:**过滤条件要使用索引必须按照索引建立时的顺序,依次满足,一旦跳过某个字段,索引后面的字段都无法被使用。
3、不要在索引列上做任何计算
不在索引列上做任何操作(计算、函数(自动or手动)类型转换),会导致索引失效而转向全表扫描。
3.1 在查询列上使用了函数
执行以下SQL语句
EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE age=30;
EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE LEFT(age,3)=30;
结论:等号左边无计算
3.2 在查询列上做了转换
首先建立索引,执行以下SQL语句
CREATE INDEX idx_name onemp(name);
explain select sql_no_cache * from emp where name='30000';
explain select sql_no_cache * from emp where name=30000;
字符串不加单引号,则会在name列上做一次转换。
结论:等号右边无转换!
4、索引列上不能有范围查询
explain SELECT SQL_NO_CACHE * FROM emp WHERE emp.age=30 and deptid=5 AND emp.name = 'abcd';
explain SELECT SQL_NO_CACHE * FROM emp WHERE emp.age=30 and deptid<=5 AND emp.name = 'abcd';
建议:将可能做范围查询的字段的索引顺序放在最后。
5、尽量使用覆盖索引
即查询列和索引列一致,不要写select *
!
explain SELECT SQL_NO_CACHE * FROM emp WHERE emp.age=30 and deptId=4 and name='XamgXt';
explain SELECT SQL_NO_CACHE age,deptId,name FROM emp WHERE emp.age=30 and deptId=4 and name='XamgXt';
6、使用不等于(!=或者<>)的时候
MySQL在使用不等于(!=或者<>)时,有时无法使用索引会导致全表扫描。
7、字段的is not null和is null
当字段允许为NULL的条件时:
结论:is not null用不到索引,is null可以用到索引
8、like的前后模糊匹配
结论:前缀不能出现模糊匹配!
9、减少使用or
使用union all或者union来替代:
union和union all的区别
UNION去重且排序;UNION ALL不去重不排序
- union:对两个或多个结果集进行并集操作,不包括重复行,同时进行默认规则的排序;
- union all:对两个或多个结果集进行并集操作,包括重复行,不进行排序
- union 和 union all都可以将多个结果集合并,而不仅仅是两个,你可以将多个结果集串起来
- 使用union和union all必须保证各个select 集合的结果有相同个数的列,并且每个列的类型是一样的
- union因为要进行重复值扫描,所以效率低。如果合并没有刻意要删除重复行,那么就使用union all
10、索引使用口诀
- 全值匹配我最爱,最左前缀要遵守;
- 带头大哥不能死,中间兄弟不能断;
- 索引列上少计算,范围之后全失效;
- LIKE百分写最右,覆盖索引不写*;
- 不等空值还有OR,索引影响要注意;
- VAR引号不可丢,SQL优化有诀窍。
11、索引示例巩固
假设建立索引index(a,b,c)
Where语句 | 索引是否被使用 |
---|---|
where a = 3 | Y,使用到a |
where a = 3 and b=5 | Y,使用到a,b |
where a = 3 and b=5 and c=4 | Y,使用到a,b,c |
where b=3或者where b=3 and c=4 或者 where c=5 |
N |
where a=3 and c=5 | 使用到a,但是c不可以,b中间断了 |
where a=3 and b>4 and c =5 |
使用到a,b c不能用在范围之后,b断了 |
where a is null and b is not null | is null支持索引,但是is not null不支持,所以a可以使用索引,b不可以使用 |
where a <> 3 | 不能使用索引 |
where abs(a) = 3 | 不能使用索引 |
where a = 3 and b like ‘kk%’ and c=5 | Y,使用到a,b,c |
where a = 3 and b like ‘%kk’ and c=5 | Y,只用到a |
where a = 3 and b like ‘%kk%’ and c=5 | Y,只用到a |
where a = 3 and b like ‘k%k%’ and c=5 | Y,使用到a,b,c |
MySQL优化篇:单表索引失效相关推荐
- 物理机存放mysql实例原则_MySQL优化笔记(四)--表的设计与优化(单表、多表)...
前面讲了SQL优化以及索引的使用.设计优化了,那么接下来就到表的设计与优化啦!!!真实地去设计优化单表结构以及讲述多表设计基本原则(结合真实的生产环境的取舍来讲述). 文章结构:(1)单表设计与优化: ...
- 【MySQL优化(六)】InnoDB索引优化与索引规约
序 上一篇讲解了建表规范后,本章重点分析下创建索引的一些规范 由于索引是工作在存储引擎层,所以以下规约都是基于InnoDB引擎 题外话 在满足语句需求的情况下, 尽量少地访问/消耗资源是数据库设计的重 ...
- 深入浅出Mysql - 优化篇(锁)
深入浅出Mysql - 优化篇(锁) 锁是计算机协调多个进程或线程并发访问某一资源的机制.在数据库中,除传统的计算资源(如CPU.RAM.I/O等)的争用以外,数据也是一种供许多用户共享的资源.如何保 ...
- Mysql原理篇之表空间---05
Mysql原理篇之表空间---05 前言 回顾 页面类型 页面通用部分 独立表空间结构 区(extent)的概念 段(segment)的概念 区的分类 整理 XDES Entry链表 链表基节点 链表 ...
- MySQL优化器选错索引情况
MySQL优化器选错索引情况 1. 优化器选错索引 2. 优化器的逻辑 3. 索引选择异常和处理 1. 优化器选错索引 之前MySQL架构以及执行sql查询语句介绍过MySQL优化器可以帮助我们优化s ...
- MySQL like查询后置%索引失效分析
MySQL like查询后置%索引失效分析 表结构 CREATE TABLE `t_food_shop` (`id` bigint(20) unsigned NOT NULL AUTO_INCREME ...
- 怎么看我装的sql能不能用_深入浅出sql优化(三)之单表索引优化
大家好,我是闲水,每天更新java最新最热技术,对java感兴趣的朋友记得关注一下哦. 注意 :这是SQL性能优化第三章,点击关注查看前置内容. 上篇文章我们主要了解了索引优化的标尺"Exp ...
- MySQL优化篇:索引
文章目录 1.概念 1.1 是什么 1.2 优缺点 2.MySQL的索引 2.1 Btree索引 2.2 B+Tree索引 3.MySQL索引分类 3.1 单值索引(普通索引) 3.2 唯一索引 3. ...
- 深入浅出Mysql - 优化篇(索引)
SQL优化 通过show status了解各种sql执行的频率 mysql> show status like 'Innodb_rows_%';+----------------------+- ...
最新文章
- Winform开发中常见界面的DevExpress处理操作
- Angular-cli生成组件修改css成less或sass
- Disruptor并发框架-1
- 跨平台(Android, iOS, WP, HTML5)游戏开发libGDX学习教程
- 微型计算机的硬件组成中ssd硬盘通常是指,2015年计算机一级msoffice选择题121道及答案...
- python telnetlib怎么下_Python telnetlib模块使用
- 箱包品牌Rimowa成为Vidy广告商,在Vogue新加坡使用VidyCoin购买广告业务
- Bailian4119 复杂的整数划分问题【DP】
- php----显示中文乱码的问题
- JavaScript日期对象Date总结(附实例)
- 计算机3c认证 标准,计算机3C认证怎么办理,检测标准是什么?
- oracle lead() over,Oracle数据库之lead over 和 lag over
- java 生成word 分页_Java 插入分页符和分节符到Word文档
- 奇葩经历之一_Hotmail邮箱无法查看和发送任何邮件
- ES6中...省略号的意思
- kali虚拟机安装提示安装系统步骤失败
- 中国的程序员只能支撑到30岁么
- [MachineLearning] 机器学习速成笔记 - Bilibili
- 复现计算机论文模型,COLING 2018 最佳论文解读:序列标注经典模型复现
- w ndows7与windows10区别,电脑系统windows 7和windows 10有什么区别?哪个更好?
热门文章
- 学习编程能够从事哪些行业?
- 优化自定义函数_10分钟教你手写8个常用的自定义hooks
- python猿辅导_如何用数据分析方法剖析“猿辅导”K12课程
- HTML中checked1001无标题,是否可以一键切换两个CSS`:checked`伪类?
- mysql-5.7.21-winx64_MySql-5.7.17 -winx64的安装配置
- python在bim中的应用_Revit元素类别——Dynamo Python系列教程(六)
- 五年一贯制专转本c语言真题,江苏省五年一贯制专转本《C语言程序设计》模拟试卷二(晓庄)...
- 【数据结构】 哈希表 详解
- 关于加载Fashion MNIST数据集时可能会出现的问题
- poj3169(差分约束+SPFA)