Mysql索引优化2

本文讨论了SQL查询的优化方法,包括使用索引提升分页查询性能,小表驱动大表原则,以及in和exists的选择,还提到了count(*)的特殊优化。此外,还涉及MySQL数据类型的选择和维护计数表的技巧。
摘要由CSDN通过智能技术生成

分页查询优化

原sql

select * from employee limit 9000,5;

优化1:前提是主键是连续且自增

select * from employee where id >9000 limit 5;

原sql

select * from employee order by name limit 90000,5;

优化2:根据非主键字段排序

select * from employee a inner join (select id from employee order by name limit 90000,5) ed on e.id=ed.id;

​

Join关联查询优化

嵌套循环连接 NLJ算法

T2表  100 条数据

T1表 10000条数据

A字段是索引

select * from t1 inner join t2 on t1.a=t2.a;

此时sql的大致流程是

1、把t2的读取一行数据

2、从第一步的数据中,取出关联字段a,到表t1中查找

3、取出表t1中满足条件的行,跟t2中获取到的结果合并,作为结果返回给客户端

4、重复上面三步

基于块的嵌套循环连接  BNL算法,在没有索引的时候采用BNL算法比较快

B字段不是索引

select * from t1 inner join t2 on t1.b=t2.b;

此时sql的大致流程是

1、把t2的所有数据放到join_buffer中

2、把表t1中每一行取出来,跟join_buffer中的数据做对比

3、返回满足join条件的数据

整个过程对表t1和t2都做了全表扫描,并且join_buffer中数据是无序的,所以t1对比数据的时候是需要在内存当中判断100*10000次

如果join_buffer中存放不下所有的t2表中的数据

join_buffer的默认大小是256k,如果放不下表t2的所有数据的话就会分段存放t2的数据去和join_buffer中的数据比较

关联字段没有索引为什么要选择BNL而不是选择NLJ算法呢?

NLJ算法的话是需要做100万次的磁盘扫描

而BNL的话磁盘扫描次数会少很多,主要是在内存中做100万次判断,因此BLJ算法性能更高

对于关联sql的优化

关联字段加索引

小表驱动大表也就是说小表先执行(小表:参与数据的关联集)

straight_join

straight_join 可以指定哪张表先执行,不过这个方法只适用于inner join 方法

Select * from t2 straight_join t1 on t2.a=t1.a; 这样表示t2这张表先执行

in和exists的优化

原则:小表驱动大表,即小的数据集驱动大的数据集

当B表的数据集小于A表的数据集时,in优于exists

Select * from A where id in(select id from B)

等价于:

For (Select  id from B ){

select * from A where A.id = B.id

}

当A表的数据集小于B表的数据集时,exists优于in

Select * from A where exists(select 1 from B where A.id=B.id)

注意: exists也可以用join来替代

count(*)查询优化

Select count(1) from A

Select count(id) from A

Select count(name) from A

Select count(*) from A

哪一条sql执行计划一样,这四个sql执行效率都差不多

count(*) = count(1) > count(字段) > count(主键id)  字段有索引,二级索引存储数据比主键索引少,所以count(字段) > count(主键id)

count(*)是例外,mysql不会把全部字段取出来,而是专门做了优化,不取值,按行累加,效率很高

常见优化方法

1、将总数维护到redis中,不一定缓存和数据库值一致

2、增加数据库计数表

Mysql数据类型选择

1、确定合适的大类型:数字、字符串、时间

2、确定具体的类型:有无符号,取值范围、变长定长

整型

Tinyint 1字节   有符号-128-127     无符号  0 -255

smallint 2字节

mediumint 3字节

int或integer  4字节

bigint 8字节

int(11) 长度

显示宽度,加一个填充0

’id’ int(5) unsigned zerofill 就有用了  00005

时间

小公司用timestamp 4个字节,占用的空间小,到了2038年就不能用了

大公司用datetime  8 个字节

字符串

Char 定长字符串,char(n)当插入的字符串实际长度不足n时,会插入空格进行补充保存

varchar:变长字符串,varchar(n) 的n代表最大列长度

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

—熙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值