mysql之SQL优化

1、插入数据

insert:

一般我们使用insert都是一条语句一条语句插入,但是如果数据量比较大的情况下,需要使用一定的优化手段进行插入。

(1)优化方案一

Insert into tb_test values(1,'Tom'),(2,'Cat'),(3,'Jerry');

(2)优化方案二:手动事务插入

 start transaction;

insert into tb_test values(1,'Tom'),(2,'Cat'),(3,'Jerry');

insert into tb_test values(4,'Tom'),(5,'Cat'),(6,'Jerry');

insert into tb_test values(7,'Tom'),(8,'Cat'),(9,'Jerry');

commit;

 (3)优化方案三:主键顺序插入大于乱序插入

在连接客户端时 使用loal-infile

mysql --local-infile -u root -p 

设置一个全局参数local_infile为1,开启从本地加载文件导入数据的开关

set global local_infile=1

执行load指令将准备好的数据,加载到表结构中

load data local infile ‘D:\\cc.sql’ into table tb_user fields terminated by ',' lines terminated by '\n';

2、主键优化

主键顺序插入的性能比乱序插入的性能高

(1)索引的数据结构是B+数,主键的叶子节点中保存的是行数据,而行数据保存在以下逻辑结构图中的页中,如下所示。每一页固定是16K的数据,如果行的数据超过了此页的存储大小,就会放到下一页中,页与页之间用指针链接。

 

索引叶子节点,当插入数据时,如果第一页插入空间不够的情况下,会下放到第二页中,第二页中的数据如下:

 那当下一个数字时5怎么办呢?因为叶子节点是顺序插入的,所以肯定要插到3的后面。mysql是怎么规划的呢?这里涉及到一个概念:页分裂。

(2)页分裂

此时第一页由于空间原因5插入不进去了,所以需要重新开辟新的页3,将第一页一半的数据移动到页3,然后5插入到页3中。

此时页之间值不是顺序的,所以需要重新对指针进行设置。

 

 (3)页合并

数据被删除之后,mysql又怎么规划其存储结构呢?这里就涉及到页合并了。下图中将10删除,此存储空间并不会被删除,只是将此空间设置为删除标记并且它的空间允许其他记录声明使用。

 当删除达到此空间的MERGE_THRESHOLD(默认是50%),则会触发空间删除,并且将空间进行合并,将第3页中的数据移动到第2页中。

 (4)主键的设计原则:

1、满足业务需求,降低主键长度

2、保证主键是顺序插入,减少页分裂的操作

3、尽量不要使用uuid做主键,或者身份证号  此主键无法保证顺序性

4、避免对主键进行修改

 3、order by优化

MySQL的排序,有两种方式:

Using filesort : 通过表的索引或全表扫描,读取满足条件的数据行,然后在排序缓冲区sort buffer中完成排序操作,所有不是通过索引直接返回排序结果的排序都叫 FileSort 排序。

Using index : 通过有序索引顺序扫描直接返回有序数据,这种情况即为 using index,不需要 额外排序,操作效率高。

图中username被设置索引,name无索引,通过排序查询相同的值,可以知道在100w条数据中,order by username查询花费0s,order by name查询花费0.29s。说明order by尽量覆盖索引排序。

 以下图中当oder by多个字段排序时,字段肯定遵循最左前缀法则,如果可以,可以创建联合索引,提高查询效率。

 由上述的测试,我们得出order by优化原则:

A. 根据排序字段建立合适的索引,多字段排序时,也遵循最左前缀法则。

B. 尽量使用覆盖索引。

C. 如果不可避免的出现filesort,大数据量排序时,可以适当增大排序缓冲区大小 sort_buffer_size(默认256k)。

 4、group by优化

分组操作,我们主要来看看索引对于分组操作的影响。图中name,birthday是联合索引,当使用birthday分组时,出现using temporary,原因是因为对于分组操作, 在联合索引中,也是符合最左前缀法则的。

 所以,在分组操作中,我们需要通过以下两点进行优化,以提升性能:

A. 在分组操作时,可以通过索引来提高效率。

B. 分组操作时,索引的使用也是满足最左前缀法则的。

5、limit优化

在100w的数据中,limit越往后,查询效率越低。

 那怎么优化上述查询呢,通过索引+子查询的方式:

6、count优化

下面图中四个用法都可以计算表的总个数,但是其效率上是有差别的,我们可以发现count(name)是最差的需要遍历全表,count(*), count(1),count(id)都会走索引,count(*)和count(1)实际上效率查不到,查询的时候不会将值返回服务层,而是直接计算按行进行计算。count(id)的区别是会将值返回给服务层,然后由服务层按行进行计算。

 

 效率上:count(name)< count(id)<count(1)~count(*),所以尽量使用count(*)。

7、update优化

InnoDB的行锁是针对索引加的锁,不是针对记录加的锁 ,并且该索引不能失效,否则会从行锁 升级为表锁 。

  • 15
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值