🔥 主要思路:
🚀 增加数据时,尽量顺序插入
🚀 删除、修改、查询数据时,尽量走索引操作
🐈⬛ 主键优化
⭐ 满足业务需求的情况下,尽量降低主键的长度,减少磁盘 IO
⭐ 插入数据尽量选择顺序插入,选择使用 auto_increment 自增主键
⭐ 尽量不要使用 UUID 或其他自然主键(如身份证号) 作为主键
⭐ 业务操作避免对主键的修改
在 InnoDB 存储引擎中,表数据是根据主键顺序组织存放的。这种存储方式为索引组织表(index organized table IOT)。
数据行是记录在逻辑结构 page 页中的,而每一个页的大小是固定的,默认 16K。也就意味着,一个页中所存储的行也是有限的,如果插入的数据行在该页存储不下,将会存储到下一个页中,页与页之间会通过指针连接。
🦮 insert 优化
一次性往数据库中插入多条数据,可从以下三方面优化:
- 批量插入数据
|
|
- 手动控制事务
|
|
- 主键顺序插入
数据在 B+ 树的叶子节点有序存放,顺序插入保障每次插入都是在后面添加一条记录(顺序磁盘 IO),不需要调整叶子节点中的内容。
|
|
🦛 update 优化
🫧 防止索引失效
🫧 防止升级为表锁
InnoDB的行锁是针对索引加的锁,不是针对记录加的锁,并且该索引不能失效,否则会从行锁升级为表锁。
开启多个事务,在执行 SQL 时,防止行锁升级为表锁。
🦒 order by 优化
🍀 根据排序字段建立合适的索引
🍀 多字段排序时,尽量遵循最左前缀法则
🍀 尽量使用索引 / 覆盖索引
🐎 limit 优化
在数据量比较大时,如果进行 limit 分页查询,在查询时,越往后,分页查询效率越低。
当在进行分页查询时,如果执行 limit 2000000,10
,此时 MySQL 会排序前 2000010 条的记录,
仅仅返回 2000000 - 2000010 的记录,其他记录会被丢弃,查询排序的代价非常大。
优化思路:
🎈 在业余允许的情况下,可以限制页数。通常用户也不会向后面翻很多页。
例如在淘宝双十一时不能查询历史购物记录。
🎈 可以通过先定位数据,先偏移,再 limit
1 2 3
select * from user where id > 2000000 limit 10;
🎈 通过覆盖索引 + 子查询形式进行优化
1 2 3 4 5 6 7 8 9 10
select * from user u where id >= (select id from user order by id limit 2000000 1) limit 10; -- or select * from user u, (select id from tb_sku order by id limit 2000000, 10) a where u.id=a.id;
🦬 count 优化
count(*) == count(数字) > count(主键) > count(字段)
⭐ count(主键)
- InnoDB 引擎会遍历整张表,把每一行的 主键id 值都取出来,返回给服务层。服务层拿到主键后,按行进行累加(主键不可能为null)。
⭐ count(字段)(注意 null 约束)
- 没有 not null 约束: InnoDB 引擎会遍历整张表把每一行的字段值都取出来,返回给服务层,服务层判断是否为 null,不为 null,就计数累加。
- 有 not null 约束:InnoDB 引擎会遍历整张表把每一行的字段值都取出来,返回给服务层,直接按行进行累加。
⭐ count(数字)
- InnoDB 引擎遍历整张表,但不取值。服务层对于返回的每一行,放一个数字 “1” 进去,直接按行进行累加。
⭐ count(*)
- InnoDB引擎并不会把全部字段取出来,而是专门做了优化,不取值,服务层直接按行进行累加。