SQL优化详解

目录

·插入数据

insert的优化(少量数据)

批量插入

手动事务提交

主键顺序插入

插入大量数据

·主键优化

数据组织方式:

页分裂:

主键顺序插入的方式:

主键乱序插入:

页合并:

主键设计原则:

·order by优化

·group by 优化

·limit优化

优化方式:

·count优化

count的用法:

几种用法的优劣:

count(主键)

count(字段)

count ( 1 )

count (* )

·update优化


·插入数据

插入多条数据的优化方案:(插入一条没啥优化的哈)

insert的优化(少量数据)

批量插入

像这种模式,一般建议数据量最多在500-1000条左右。

Insert into tb_test values(1,'To'),(2,'WO'),(3,'jee');

手动事务提交

因为每句insert的执行都会涉及事务的提交,执行的越多越占用时间,为此可以进行手动事务提交,

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;

主键顺序插入

一般而言主键顺序插入还是乱序插入都可以,建议主键顺序插入

乱序:2 5 22 86 34 8987 213

顺序:1 2 3 4 5 6 7 8 9

插入大量数据

一次性插入大量数据,insert的插入性能较低,可以使用MySQL提供的load指令进行插入:

注意,插入的数据需要具有一定的格式

#客户端连接服务端时,加上参数--local-infile

mysql --local-infile -u root -p

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

set global local_infile =1;

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

load data local infile '/root/sql1.log' into table `tb_user` fields terminated by ',' lines terminated by '\n';

插入1000000的数据需要16s,如果是使用insert大概需要十几分钟。

·主键优化

数据组织方式:

在InnoDB中,表数据都是根据主键顺序组织存放的,这种存储方式的表称为索引组织表。

为什么都是根据主键顺序存放的呢:

数据库的数据是根据表空间,段,区,页,行的形式存放的,行就是每一条数据,表是InnoDB管理的最小单位。数据的索引分为聚集索引和二级索引,聚集索引使用的是B+树,它的每个主键都会在树的最下面存放,而前面的向上分裂的部分作为查询数据的索引。所以表的数据都是根据主键顺序组织存放的。

页分裂:

页可以为空,也可以填充一半,也可以填充100%。每个页包含了2-N行数据(如果一行数据过大,会行溢出),根据主键排列。

主键顺序插入的方式:

就从前往后插数据,第一个页写满了,就写入第二个页,然后用一个双向指针维护两个页的关系。

主键乱序插入:

如果是这种情况,第一个页写满了,但是要插入一个id为50的数据,这个时候怎么办呢?

他会新建一个数据页,然后把第一个页分一半出来,把50插入到新的数据页中

然后把链表指针改变一下,把1号的下一个改为3号,3号的next改为2号。

所以:顺序插入的效率最高。

页合并:

当删除一行记录时,实际上记录并没有被物理删除,只是记录被标记(flaged)为删除并且它的空间变得允许被其他记录声明使用。

当页中删除的记录达到 MERGE_THRESHOLD(默认为页的50%),InnoDB会开始寻找最靠近的页(前或后)看看是否可以将两个页合并以优化空间使用。

主键设计原则:

1、满足业务需求的情况下,尽量降低主键的长度

因为二级索引的最下面存放都是主键,主键太长,就会占用大量的IO和磁盘。

2、插入数据时,尽量选择顺序插入,选择使用AUTO_INCREMENT自增主键。

3、尽量不要使用UUID做主键或者是其他自然主键,如身份证号。

两个原因:无序且过长

4、业务操作时,避免对主键的修改。

·order by优化

在mysql中有两种排序方式

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

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

所以优化的就需要让排序方式尽量变成Using index。

#没有创建索引时,根据age, phone进行排序
explain select id,age,phone from tb_user order by age , phone;
#创建索引
create index idx_user_age_phone_aa on tb_user(age,phgne);
#创建索引后,根据age, phone进行升序排序
explain select id,age,phone from tb_user order by age , phone;
#创建索引后,根据age, phone进行降序排序
explain select id,age,phone from tb_user order by age desc , phone desc ;

创建了联合

·group by 优化

分组操作的研究中,我们主要研究索引对分组操作的影响。

这是没有索引的查询效率:

下面

是创建索引后的性能:

建立适当的索引,满足最左前缀法则即可提高分组效率。

如果查询时是这样,pro在where,而age在group by也是满足最左前缀法则的。

·limit优化

什么时候要考虑limit进行优化呢:

select * from sb_tu limit 0,10;

第0条数据开始,查10个数据

select * from sb_tu limit 100000,10;

从第100000个数据开始查10个数据。

越往后查询的代价越大,他会把0到100000个数据全部排序,然后丢弃,只返回100000到100010这10个数据。

优化方式:

覆盖索引加子查询

1:先查出想要的id

select id from tb_sku order by id limit 100000,10;

2:表联查查数据

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

原方法耗时19s,优化后耗时11.47s。

·count优化

select count(*) from tb_sku;

MyISAM引擎把一个表的总行数存在了磁盘上,因此执行count(*)的时候会直接返回这个数,效率很高。如果有where条件就需要一行一行的读取了。

InnoDB引擎就麻烦了,它执行count(*)的时候,需要把数据一行一行地从引擎里面读出来,然后累积计数。

目前由于存储引擎的缘故,没有太好的优化count的方法,常用的就是使用像redis之类的数据库进行自我计数。

count的用法:

count(*),count(主键),count(字段),count(1);

count(主键)统计有多少个主键。一般为数据库表的总数。

count(字段)是查询该字段不为空的总数,如果为空则不计入。count(*)同理。

count(1)是给每个字段添加一个1的标识,然后统计1的数量。

几种用法的优劣:

count(主键)

InnoDB引擎会遍历整张表,把每一行的主键id值都取出来,返回给服务层。服务层拿到主键后,直接按行进行累加(主键不可能为null)。

count(字段)

没有not null约束: InnoDB引擎会遍历整张表把每一行的字段值都取出来,返回给服务层,服务层判断是否为null ,不为null,计数累加。有not null约束: InnoDB引擎会遍历整张表把每一行的字段值都取出来,返回给服务层,直接按行进行累加。

count ( 1 )

InnoDB引擎遍历整张表,但不取值。服务层对于返回的每一行,放一个数字“1”进去,直接按行进行累加。

count (* )

InnoDB引擎并不会把全部字段取出来,而是专门做了优化,不取值,服务层直接按行进行累加。

按照效率排序的话,count(字段)<count(主键id)<count(1) = count(*),所以尽量使用count(*)。

·update优化

我们在更新数据时一定要根据id进行更新,因为在事务中使用id索引进行update用的是行级锁,该行在事务未commit之前不会再被其他人修改。

如果使用字段进行字段进行查询则会被开启表级锁,整张表在该事务未提交之前不会再被修改,会影响其他人操作。

如果字段有建立索引表则不会被添加表级锁,而是行级锁。

  • 10
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

猿究院-Cu-Sn合金

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

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

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

打赏作者

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

抵扣说明:

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

余额充值