【MySQL笔记】sql优化

SQL执行频率

SHOW GLOBAL STATUS LIKE 'Com_______'

结果如下:

Com_insert:插入sql执行次数
Com_delete:删除sql执行次数
Com_update:更新sql执行次数
Com_select:查询sql执行次数

insert优化

批量插入

插入多条记录,建议批量插入(不要超过1000条,大批量可以使用load指令)

insert into tb1 values(..),(..),(..)

原因分析:主要原因是多条insert合并后日志量减少了,降低了日志刷盘的数据量和频率从而提高效率;同时也能减少sql解析次数;减少了网络传输IO

手动提交事务

每条sql都会开启一个事务

begin;
insert into tb1 values(..),(..),(..)
insert into tb1 values(..),(..),(..)
commit;

主键顺序插入

如果乱序插入,可能发生页分裂

order by优化

排序字段应该创建索引
如果按多个字段排序,应该创建联合索引:create index ix_name_money on account(name,money)
如果多个字段排序,有升序、有降序,创建联合索引:create index ix_name_moneydesc on account(name asc,money desc)

group by 优化

分组字段应该创建索引

update优化

一定要根据索引字段进行更新,也就是where条件中的字段一定要加索引,否则会锁表,如下:

-- name字段没加索引,会锁表。如果name字段加了索引,只会锁一条记录
update account set money=1000 where name='fan'

InnoDB的行锁是针对索引加的锁,而不是针对记录加的锁,如果没有索引会升级成表锁

count优化

使用count(*),不要使用count(id)count(字段)count(1)
InnoDB对count(*)做了优化,不取值,服务层按行累加

limit优化

分页查询常规直接使用LIMIT,仅适用数据量少的情况。越往后速度越慢。
比如limit 1000000,10,MySQL需要对前100w记录进行排序,仅返回1000000-1000010十条记录,其他记录丢弃,查询排序的代价非常大。

Demo:测试了千万级数据,分页查询1000万以后的分页,用时十几秒

select * from order_shopcart order by id limit 10000000,10

利用BETWEEN..AND..

最快的方式,用时0.18秒!执行计划的typerange(部分索引)
缺点:查询字段的数据必须要连续的,如果数据不是连续的话,只能用上面的方式

select * from order_shopcart where id BETWEEN 10000000 AND 10000010 order by id;

利用覆盖索引

子查询只用到了索引列,没有取实际的数据,所以不涉及到磁盘IO,所以即使是比较大的 offset 查询速度也不会太差。
利用子查询的方式,把原来的基于order_shopcart的搜索转化为基于主键(id)的搜索,主查询因为已经获得了准确的索引值,所以查询过程也相对较快。
方式1:

select * from order_shopcart where id>(
select ID from order_shopcart order by id limit 10000000,1) limit 10

方式2:

SELECT *
FROM (SELECT `ID` AS `ID_1` FROM `order_shopcart`  ORDER BY ID LIMIT 10000000,10) AS `t`
JOIN `order_shopcart`   ON `t`.`ID_1`=`order_shopcart`.`ID`

用时3秒多,已经快了很多

posted @ 2022-02-19 22:38  .Neterr  阅读(36)  评论(0编辑  收藏  举报