MySQL命令学习5 - 索引、查询优化、explain分析

我的MySQL版本是5.7.29

1. SQL慢原因、MySQL瓶颈

SQL慢原因
1. 查询语句写的差
2. 索引失效 - (例:频繁的增删改数据导致索引B+树局部失效)
3. 太多连接join
4. 服务器没有进行调优参数(缓冲、线程)
MySQL瓶颈
1. CPU饱和一般发生在从磁盘中读取数据入内存
2. IO:即将读取入内存的数据远大于内存容量

2. 索引 - 排好序的快速查找数据结构

实际上索引也是一张表 - 保存了索引字段、指向数据记录的地址

索引优势
IO成本降低:提高检索效率
CPU运行成本降低:索引已经对数据排序

2.0 基础知识 - 每条SQL只能使用一个索引

默认开启 主键索引和当前查询使用的索引合并

  1. 通俗理解索引: 查询英文单词cat,肯定是在字典索引页中查找到C开头的一块,然后在查找ca开头的单词,最后从中检索到cat单词。如果没有索引页。那么查找cat单词,你则需要从第一页开始查找是否有cat单词。
  2. 通常所说的索引: 一般是B+树(多路搜索树)索引 - 叶子节点才存储真实信息
  3. 索引劣势: 一旦建立索引,我们需要维护数据库文件、以及对应的索引文件,频繁的变动数据库数据(增删改),都要同时更新索引文件与数据库文件的一 一对应( 但利远大于弊 )
  4. 覆盖索引: 不包含where,则selec必须只能包含索引列
  5. 复合索引: 只能依次从左到右使用
  6. 建议:
    1. 一张表建议不要超过5个索引、
    2. 范围查询会导致部分索引列失效、
    3. 表连接时小表驱动大表(后面的大表会使用到索引进行筛选行数据 - 加快检索效率)


2.1 索引原理 - 简单解析

图片来自:https://blog.csdn.net/v_JULY_v/article/details/6530142

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YIjgFg5Z-1587797807542)(en-resource://database/31364:1)]



B树 - 每检索一个节点,都有关键字对应的数据地址信息 - 缩小数据入内存的次数 - 最后搜索的终点不一定是叶子节点 - 访问磁盘的次数比B+树多。因为同大小的节点存储的索引信息比B+树少
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AuCohLb7-1587797807550)(en-resource://database/31356:1)]


每个节点存储的信息
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5ODo6PYH-1587797807558)(en-resource://database/31358:1)]


B+树 - 非叶子节点只存储关键字以及子节点指针信息 - 最后找到叶子节点才是数据库数据地址信息 - 并且叶子节点有序且用链表相连起来 - 故与B树相比非叶子节点存储更小的信息,只具有查找下一个节点的作用而已 - 最后搜索的终点都是叶子节点
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NedtAm6P-1587797807566)(en-resource://database/31360:1)]

单列索引 - B+树检索
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gOS47Aqm-1587797807570)(en-resource://database/31368:1)]

复合索引 - B+树的检索
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A1AAF0Gz-1587797807574)(en-resource://database/31366:1)]


叶子节点存储 - 真实数据加上对应的对应数据项的硬盘地址
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y3uDyl7w-1587797807580)(en-resource://database/31352:1)]

2.2 索引分类
分类
单列索引:主键( primary key )、外键(foreign key 其实也是主键)、普通单列索引
唯一索引:unique
复合索引:一个索引包含多列

2.3 创建索引情况 - 适合、不适合

字段值越是唯一,创建索引后查询的效率越高。公式 ( distinct(字段)/总记录数 - 越接近1,值的唯一性越高,创建索引后查询效率越高 )

适合创建索引条件
1. 主键、外键、唯一键 本身就是索引
2. 频繁作为查询条件的字段
4. 高并发下倾向建复合索引
5. 排序的字段若通过索引将提高排序速度 - 因为索引已经排好序了
6. 查询中的统计、分组字段
不适合创建索引条件
1. 表记录少
2. 频繁增删改的表:由上面的B+树图,索引是要维护索引列的值
3. 数据重复、分布平均的字段
2.3.1 索引失效
情况
1. 全值匹配
2. 最佳左前缀法则 - 带头大哥不能死,中间兄弟不能断
3. where时不在索引列上做任何操作 - 索引列别进行函数计算
4. 存储引擎不能使用索引中范围条件右边的索引列 - (5.7会优化成索引下推,问题不大)
5. 尽量使用覆盖索引,避免使用*
6. !=、<>、is not null、or都会导致索引失效 - is null会使用到索引下推
7. like模糊匹配,尽量避免通配符开头'%abc%',会导致索引失效
8. 字符串不加单引号,导致隐式调用函数转换成字符、从而导致索引失效
9. order by排序按前面已架好的梯子进行排序字段 - 否则失效
2.3.2 案例

1. 全值匹配 - 与索引列顺序必须一致,且不能跳过索引列

explain select * from member  where  name ='6190c108b6' ;

explain select * from member  where name ='6190c108b6' and year = 57 ;

explain select * from member  where name ='6190c108b6' and year = 57 and nickname='6a54008181' ;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BJQRCzcg-1587797807584)(en-resource://database/31522:1)]


2. 最佳左前缀原则 - 必须按索引列顺序进行where

explain select * from member  where  year = 57 ;

explain select * from member  where nickname='6a54008181' ;

explain select * from member  where name ='6190c108b6' and nickname='6a54008181' ;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bxdReK39-1587797807588)(en-resource://database/31524:1)]


3. where时不在索引列上做任何操作,否则索引失效

explain select * from member  where name like'619%';

explain select * from member  where name  like concat(substr('6190c108b6', 1, 3), '%');

explain select * from member  where substr(name, 1, 3) like '619%';

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RaGWZZeM-1587797807591)(en-resource://database/31526:1)]


4. 覆盖索引:selec不能出现索引列

explain select * from member;

# 覆盖索引
explain select name from member;
explain select name,year from member;
explain select name,year,nickname from member;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AFk36vjv-1587797807595)(en-resource://database/31528:1)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Plbi4U4l-1587797807600)(en-resource://database/31530:1)]


5. 使用!=、<>、is not null、or都会导致索引失效 - is null会使用到索引下推

explain select * from member where name != '6190c108b6';
explain select * from member where name <> '6190c108b6';
explain select * from member where name is not null;
explain select * from member where name like '619%' or year > 25;

# 使用到索引下推ICP
explain select * from member where name is null;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UtWmWq1H-1587797807603)(en-resource://database/31532:1)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a2TXsoe4-1587797807606)(en-resource://database/31540:1)]


6. like模糊匹配,尽量避免通配符在开头被使用

explain select *from member where name like '%619%';
explain select *from member where name like '619%';
explain select *from member where name like '61%9';

# 解决开头是通配符,索引失效的方法 - select时不要使用*,而是使用当前索引的索引列 - select不用遵从索引列顺序 - 一旦非当前索引列,索引列会失效
explain select id,name,year,nickname from member where name like '%619%'
explain select year from member where name like '%619%'
explain select year,nickname from member where name like '%619%'

#索引失效
explain select name,hobby from member where name like '%619%'

# select主键列也可使得索引不失效
explain select id from member where name like '%619%'


# 在添加一个 idx_name_hobby 索引 - 这样也可以使索引不失效 - 因为name已经架好梯子
explain select id,hobby from member where name like '%619%';

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OFIkvdpH-1587797807610)(en-resource://database/31536:1)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ISuUZOrJ-1587797807614)(en-resource://database/31538:1)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ej4yHAjg-1587797807616)(en-resource://database/31548:1)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-95dlkgII-1587797807620)(en-resource://database/31544:1)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tzLUvISW-1587797807624)(en-resource://database/31546:1)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3sGk1jdn-1587797807627)(en-resource://database/31554:1)]


6. 字符串不加单引号,导致索引列隐式调用函数转换成字符、从而导致索引失效

explain select * from member where hobby = 1;
# 上面等价于:
#   ① explain select * from member where hobby+0 = 1;
#   ② explain select * from member where CONVERT(hobby, SIGNED) = 1;


explain select * from member where hobby = '1';

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CkiaBP97-1587797807631)(en-resource://database/31550:1)]


7. order by排序按前面已架好的梯子进行排序字段 - 否则失效"

explain select * from member where name = '6190c108b6' order by year;

explain select * from member where name = '6190c108b6' and nickname = '6a54008181' order by year;

# 没有用到索引排序
explain select * from member where name = '6190c108b6' order by nickname;

explain select * from member where name = '6190c108b6' order by year,nickname;


# 没有用到索引排序
explain select * from member where name = '6190c108b6' order by nickname,year;

# 没有用到索引排序 - 只有name用到索引排序,后面的二级排序需要数据行入内存进行快速排序
explain select * from member where name = '6190c108b6' order by name,nickname;

explain select * from member where name = '6190c108b6' order by name,year;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tRFR21iF-1587797807634)(en-resource://database/31556:1)]


7. order by时,前面的where是范围查询的那个索引字段失效,则where塔好的路从范围查询索引字段不起作用,order by排序时需要重新按最左前缀进行排序字段 - 否则索引排序失效

# 强迫使用索引进行检索、排序数据
explain select * from member force index(idx_name_year_nickname) where name like '%619%' order by name;

# 不强迫使用索引、如果要用到索引,只能select索引列才可以
explain select id,name,year,nickname from member where name like '%619%' order by name;
explain select id,name,year,nickname from member where name like '%619%' order by name,year;
explain select id,name,year,nickname from member where name like '%619%' order by year;
explain select * from member where name like '619%' order by year;
explain select * from member where name like '619%' order by name,year;

# 如果order by 没有使用索引排序,可以强制使用索引排序
explain select * from member force index(idx_year_name)  where year >50 order by year;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yFpIigFR-1587797807640)(en-resource://database/31560:1)]


2.4 Explain、show Warnings - 分析SQL - 模拟优化器执行SQL语句

语法 - 下面两个语句必须同时选中运行

# 查看SQL语句使用索引的情况
explain SQL;

# 查看被优化器优化后的SQL语句
show warnings;
explain
id:表的读取顺序 - 越大越优先入内存 - 相同则从下往上进行顺序读取
select_type:数据读取操作的操作类型
possible_keys:哪些索引可以将被SQL该使用
key、keylen:真正被使用到SQL运行的索引、使用到的索引列长度
ref:显示使用哪个表中的列或常数的值进行筛选数据行
rows:有多少行数据从该表查询到
table:输出行所引用的表
type:联接类型
extra:查询时的详细信息
filtered:返回结果的行占需要读到的行的百分比
2.4.1 id - 表的读取顺序 - 越大越优先读取 - 相同则从上至下读取

表连接
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GgrKCdRS-1587797807644)(en-resource://database/31370:1)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7ETup27b-1587797807647)(en-resource://database/31372:1)]

2.4.2 select_type - 查询类型
查询类型
simple:不使用子查询、union关键字
primary:主查询 - 即最外层的select
subquery:子查询 - select或者where中包含子查询
dependent subquery:子查询 - 结果取决于外层select - 尽量少使用
derived:from子句的子查询 - from子查询被标记为临时表
union:union关键字后面的select语句
dependent union:union关键字后面的select语句 - 结果取决于外层select
union Result:union合并后的结果

explain select *from food where id = 1
union
select *from food where id = 2;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ijs6mC31-1587797807650)(en-resource://database/31374:1)]

explain 
	select student.name, (select name from class where id = student.class_id) className 
	from student,food where student.food_id = food.id

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Dv121F5u-1587797807653)(en-resource://database/31378:1)]

2.4.3 type - 联接类型

1. 经常出现的type类型性能:system > const > eq_ref > ref > range > index > all

2. 保证每表查询至少达到range级别,最好能达到ref级别 - All级别尽量的消除



从最好到最坏查询性能由上至下排列

type
system:表仅有一行(=系统表) - const联接类型的一个特例
const:仅有一行数据 - 通过primary key 或者 unique key列
eq_ref:等值连接(使用索引列)- 必须使用前表的数据
ref:通过索引列使用=或<=>操作符筛选。主表筛选
ref_or_null:专门搜索包含NULL值的行。在解决子查询中经常使用该联接类型的优化
index_merge:key列包含了使用的索引的清单,key_len包含了使用的索引的最长的关键元素
unique_subquery: 可以替换in子查询
index_subquery:可以替换in子查询
range:只检索给定范围的行,使用索引来选择行 - 利用常量进行筛选
index:整个索引文件扫描一遍 - 该联接类型与ALL相同,除了只有索引树被扫描。这通常比ALL快,因为索引文件通常比数据文件小
ALL:整个表数据扫描一遍 - 进行完整的表扫描 - 极危险信号 - 看到必须想办法消除它
explain 
	select *from student where id = 1;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UZ1lXAQe-1587797807657)(en-resource://database/31380:1)]


# name字段有创建索引 - 如果name不是索引则不会是ref,而是全表检索All
explain select * 
	from student,food
	where student.food_id = food.id  and student.name = 'lrc';

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VVkXOfT0-1587797807661)(en-resource://database/31384:1)]


explain 
    select *from student where  id between 1 and 10;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cIwFDrPq-1587797807664)(en-resource://database/31386:1)]



这两种情况不知道怎么复现 - 复现不了

# unique_subquery
value IN (SELECT 主键/唯一键列 FROM single_table WHERE 筛选表达式)

# index_subquery
value IN (SELECT 索引列 FROM single_table WHERE some_expr)

2.4.4 ref - 筛选值取自哪个表的那列数据
explain select stu.name, (select id from food where food.id = stu.food_id)
	from student stu

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-boUEGL5N-1587797807668)(en-resource://database/31388:1)]

2.4.5 extra - 查询时的详细信息

想要查询快 - 尽量的解决掉 using filesort、using temporary 字符串出现

extra
Distinct:发现第1个匹配行后,停止为当前的行组合搜索更多的行
Not exists:能够对查询进行LEFT JOIN优化,发现1个匹配LEFT JOIN标准的行后,不再为前面的的行组合在该表内检查更多的行
range checked for each record (index map: #):检查是否可以使用range或index_merge访问方法来索取行
Using filesort:数据库排序 - 切记尽量防止该字符出现 - 没有使用到索引进行排序
Using index:只从索引树中获取列值,不需要访问真实数据库读取整条行记录
Using temporary:创建一个临时表来容纳结果 - 尽量少出现 - 常出现在order by排序、group by分组
Using where:使用到where关键字
Using sort_union(...), Using union(...), Using intersect(...):使用到集合关键字
Using index for group-by:用来查询GROUP BY或DISTINCT查询的所有列,而不要额外搜索硬盘访问实际的表
Using join buffer:表连接缓存 - 表连接多,配置文件就需要设高点缓存
2.4.5.1 Using index condition - 索引下推 - 子节点进行判断是否符合在进行IO查找
  1. 减少IO请求访问基表的次数,优势就是在找到索引以及准备访问数据库时在进行一次where筛选。
  2. 索引下堆的只是索引列字段哦,非索引列字段是不可以下推的
  3. 触发条件:①非聚集索引(主键、外键索引)


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w8lHatfx-1587797807671)(en-resource://database/31512:1)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6aooHKhV-1587797807676)(en-resource://database/31514:1)]

ICP的执行流程

1. 获取一行索引元组(索引列值、行数据在数据库地址)
2. 使用where部分条件测试元祖是否符合条件
索引元组通过where,则数据库获取整个行数据
索引元组没通过where,则读取下一个索引元祖
从数据库获取整个数据行
待从数据库获取到所有符合条件数据行,在进行一次部分where进行最后筛选
2.4.5.2 案例

not exists

explain SELECT * from student LEFT JOIN test ON student.food_id=test.id
  WHERE test.id is null;
  
/*
在这种情况下,MySQL使用t1.id的值扫描t1并查找t2中的行。如果MySQL在t2中发现一个匹配的行,它知道t2.id绝不会为NULL,并且不再扫描t2内有相同的id值的行。换句话说,对于t1的每个行,MySQL只需要在t2中查找一次,无论t2内实际有多少匹配的行。*/
  

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AkcRpMQl-1587797807679)(en-resource://database/31490:1)]

using index condition - 索引下堆的只是索引列字段哦,非索引列字段是不可以下推的

# 索引列只使用到name
explain select * from member where name = 'lrc' and nickname like '%f%';

# 索引列使用到name、nickname
explain select * from member where name = 'lrc' and nickname like 'f%';

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B1qtL8Wn-1587797807682)(en-resource://database/31516:1)]

2.4.6 key_len - 索引长度
字符集类型
1. utf8mb4 - 每字符4字节
2. utf8- 每字符3字节
3 gbk- 每字符2字节
4 latin- 每字符1字节
字符类型
1. 可变长度字符
可null:最大字符长度 * 每个字符占的字节 + 1 + 2
不可null:最大字符长度 * 每个字符占的字节 + 2
2. 固定长度字符
可null:最大字符长度 * 每个字符占的字节 + 1
不可null:最大字符长度 * 每个字符占的字节
数值类型
tinyint:1 + 1(可为null时加)
smallint:2 + 1(可为null时加)
int:4 + 1(可为null时加)
long:8 + 1(可为null时加)
日期类型
timestamp:4 + 1(可为null时加)
datetime:8 + 1(可为null时加)

2.4.7 explain案例
explain select id from student;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ShOKfzFU-1587797807685)(en-resource://database/31492:1)]


explain select * from student;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B9LDn6P0-1587797807689)(en-resource://database/31494:1)]


explain 
	select * from student 
		left join class on class_id = class.id 
		left join food on food_id = food.id 
	where student.id >=2;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kVoA1Gsm-1587797807692)(en-resource://database/31496:1)]


# 非索引列
explain select count(year) from student;

# 主键索引列
explain select count(id) from student;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-48ZgOkm5-1587797807696)(en-resource://database/31498:1)]


1. 如果没有where筛选语句,要使用到索引,则select的列必须是索引列,只要含有非索引列都会导致索引失效

# member有 主键索引id,普通复索引idx_name_nickname(name, nickname))
explain select * from member where name = 'lrc';

explain select * from member where name = 'lrc' and nickname = 'cc1';

explain select * from member where nickname = 'cc1';

explain select name,nickname from member;

explain select nickname from member;

explain select name,nickname,year from member;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J4NzuAxO-1587797807698)(en-resource://database/31500:1)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ex6pbbXQ-1587797807705)(en-resource://database/31502:1)]


2. 外键索引失效情况 - where仅是外键情况且select只能外键列(外键索引才起效)

explain select * from student where food_id >1;

explain select food_id from student where food_id >1;

explain select * from student where name like 'l%'

explain select food_id,name,nickname from student where food_id >1;

# name列有创索引,但依然不起作用
explain select food_id,name from student;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7LT7TpPt-1587797807708)(en-resource://database/31506:1)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qrUQEXLX-1587797807711)(en-resource://database/31508:1)]


3. MySQL根据情况是否使用索引进行完全加载表数据

# 背景Member表有100条数据,Class表有5条数据,food表5条数据
explain select * from member left join class on class_id = class.id;

explain select * from class left join member on class_id = class.id;

select * from 
	class left join member on member.class_id = class.id 
	left join food on member.food_id = food.id;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AktFGCgk-1587797807715)(en-resource://database/31518:1)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nLH8b4hI-1587797807719)(en-resource://database/31520:1)]


2.4.8 查询优化
优化策略
1. 小表驱动大表
2. order by尽量用索引排序,而不是文件排序
1. 增大排序缓冲区 sort_buffer_size
2. 增大需要排序的数据行记录大小 max_length_for_sort_data
3. group by
1. 实质是先排序后分组 - 遵守最佳左前缀原则
2. 无法使用索引时,调大max_length_for_sort_data以及sort_buffer_size字段
3. 能写在where的条件则不要写在having上

如果max_length_for_sort_data设得太高,导致数据行不能在sort_buffer_size一次性在运存中排好序,则会将排序数据拆分成多个临时文件。这对单路排序是很不好的,因为要频繁的读取临时文件。很大可能单路排序的临时文件多于双路排序的。因为单路排序是整条数据行记录读入内存,而双路排序只将排序列的值读入内存。双路排序这从根本上减少了临时文件的生成 。


2.4.8.1 双路排序、单路排序

如果需要输出的行记录数据大于max_length_for_sort_data,则使用双路进行排序输出

双路排序 - 排序内存中行记录地址、需要排序的列值

取出符合where筛选条件的行记录地址以及需要被排序的列值,在内存中进行排序。排好序,根据行记录地址在从数据库取出完成的行记录 - 使用运行内存少,但访问磁盘频繁 - 最少都要访问两次数据库表


单路排序 - 整行记录的列值,而不是需要排序的列值

取出符合where筛选条件的完整行记录,在内存中进行排序。排好序,直接读取在内存排好序的行记录即可 - 使用运行内存大,但访问磁盘次数少 - 运存充足访问一次数据库表即可


2.4.8.2 order by案例
explain select * from member  where year > 20 order by year;

# 需要强制使用索引进行排序才能生效
explain select * from member force index(idx_year_name_nickname)  where year > 20 order by year;

# 排序字段没有遵守最左前缀原则
explain select * from member force index(idx_year_name_nickname)  where year > 20 order by name;
explain select * from member force index(idx_year_name_nickname)  where year > 20 order by year,name;
explain select * from member force index(idx_year_name_nickname)  where year > 20 order by year,name,nickname;
explain select *from member force index(idx_year_name_nickname) order by year;
explain select *from member force index(idx_year_name_nickname) order by year desc, name desc;

# 无效,排序列的升、降序不一致,故会文件排序而不是索引排序
explain select *from member force index(idx_year_name_nickname) order by year desc, name asc;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zkSAnFCU-1587797807724)(en-resource://database/31776:1)]

2.4.8.3 group by案例
explain select class_id,max(year) from member group by class_id;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MuTjka0j-1587797807727)(en-resource://database/31782:1)]

2.4.8.4 in、exists案例
# 主查询的数据多于子查询的数据,则使用in
# 因为只要加载子表的记录入内存比较即可,字表记录数较少
select id from A where id in (select * from B)


# 子查询的数据多于主查询的数据,则使用exists - 只返回true\false而不是子表的记录数
# 因为子查询只要检索N次主查询的记录数
select id from A where exists (select 1 from B where B.id = A.id)
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值