🥝FANMR.CN热爱,追求
SQL优化

insert优化

  • 对于多数据插入,尽量一条语句完成,减少与MySQL的连接、减少网络传输
  • 对于事务建议手动提交,自动提交会频繁的开启事务和提交事务
  • 对于主键建议顺序插入,乱序插入会发生页分裂现象

页分裂:在InnoDB存储引擎中,表数据都是根据主键顺序组织存放的,这种存储方式的表称为索引组织表(IOT)

图

其中对于页而言,如果顺序插入,一页满了就会创建下一页,但是对于乱序插入,会创建一个新的页,将应插入位置页的数据分一半到新页进行放置,然后加入需要加入的数据,最后改变链接(双向链表)

图

图

图

而与之相反的有个现象叫页合并

图

对于一次性大批量数据插入,insert性能较低,此时可以使用load指令

--连接服务端时,加上参数 --local-infile
mysql --local-infile -u root -p
--设置全局参数local-infile为1,开启从本地加载文件导入数据的开关
set global local-infile = 1
--执行load指令将准备好的数据加载到数据库
load data local infile '/etc/xxx.log' into table 'table_name' fields terminated by ',' lines terminated by '\n'

主键优化

  • 满足业务的情况下,尽量降低主键的长度
    • 解释:二级索引的叶子节点会记录主键数据,主键过长会占用空间,降低磁盘IO的效率
  • 插入数据时,尽量顺序插入
    • 解释:防止页分裂现象
  • 尽量不要使用UUID做主键或者其他自然主键,如身份证
    • 解释:防止页分裂现象
  • 业务操作时,避免对主键的修改

order by优化

Using filesort:通过表的索引或全表扫描,读取满足条件的数据行,然后在排序缓冲区sort buffer中完成排序操作,这种不是通过索引直接排序的方式叫FileSort排序
Using index:通过有序索引顺序扫描直接返回有序数据,不需要额外排序,效率高

该优化方式为给相关order by的字段加索引

--创建指定排序的索引
create index idx_user_age_pho_ad on table_user(age asc, phone desc)
  • 根据排序字段建立合适的索引,多字段排序时,也遵循最左前缀法则
  • 尽量使用覆盖索引(即防止产生回表查询拿数据)
  • 多字段排序,一个升序一个降序,需要注意联合索引在创建时的规则(ASC/DESC)
  • 如果不可避免的出现filesort,大量数据排序时,可以适当增大排序缓冲区大小sort_buffer_size(默认256k)
    • 解释:数据过大导致缓冲区满了后会在磁盘中进行排序,效率低

group by优化

  • 在分组操作时,可以通过创建索引来提高查询效率
  • 分组操作时,索引的使用也要满足最左前缀法则

limit优化

对于limit分页,数据越大时越靠后的数据查询越慢
官方建议:覆盖查询加子查询,减少了回表查询的操作时间

select t.* from tb_user t, (select id from tb_user order by id limit 100000, 10) a where t.id = a.id;

count优化

count慢是由InnoDB引擎造成的,需要一行一行的读,然后计数,优化策略为借助于Redis这样的技术进行统计

图

update优化

update后的条件尽量要走索引,因为InnoDB的行锁是针对索引加的锁,不是针对记录加的锁,否则行锁会升级为表锁,降低高并发的能力