Mysql-sql语句性能调优

勿以浮沙筑高台


Mysql性能调优
版本:Mysql_8

确定执行慢的sql

慢日志

在mysql中有一个慢日志,当查询的时间超过一定时间后会将执行慢的SQL语句记录到慢日志当中。

日志文件名为:slow_query_log
使用下面命令可以查询是否开启,默认是关闭的。

SHOW VARIABLES LIKE ‘%slow_query_log%’;

开启:

SET GLOBAL slow_query_log =1

设定查询超过多少时间的记录到慢日志

set global slow_launch_time=1 #最少为1秒

性能优化方案

子查询

因为关联的时候,如果内表有1000条,外表有10条,这个时候查询每条外表的数据会传递到内表进行查询,也就是1000*10=10000次。所以有很大的开销.

下面这条SQL语句就是全链接的方式

select name,id,age from student where id in (select id, from stu_score where score>=90)

优化:使用join,left join,right join 进行半链接优化。就是只用一半的表去链接,而不是双向的去链接数据。

select name,id,age from student stu join (select id from stu_score where score>=90) stusc on stu.id = stusc.id

select *

select *会破坏索引

派生子查询

和子查询一样。经历避免无用临时表的创建

select * from (select * from student where id >10) where id=21

优化后:

selec * from student where id=21 and id>10

IN查询

这里执行查询后,用explain查看类型会发现type为range。

Select * from student_score where (student_id,subject_id) in ((1,1), (1,2), (1,3), (1,4));

优化后:type=ref,因为括号里的结果要么是true要么是false因此更快

explain select * from student_score where (student_id=1 and subject_id=1) or (student_id=1 and subject_id=2) or (student_id=1 and subject_id=3)

UPDATE/DELETE IN子查询优化

子查询进行了相互匹配

delete from t1 where t1.id in(select id from t2 where id<5);

优化:

delete from t1 join (select id from t2 where id<5) tmp on t1.id=tmp.id;

Like "%xxxx%"优化

在MySQL中, like 'xxx%‘子句可以用到索引,但’%xxx%'不行。

select * from student where name like ‘%king%’;

优化后:

select * from student where name like ‘king%’;

其中name字段建立了主键(聚集索引), 从索引中能够取得name列,不必读取数据行。如果select后的字段正好是索引,那么就用到了覆盖索引。通过覆盖索引,可以减少I/O, 提高性能。 优化后的代码如下:

select * from student a join (select id from student where name like ‘%king%’) b on a.id=b.id.

Limit优化

当查询数量超过百分之20时的时候会进行全表扫描

select * from student limit 999 20;

优化:使用范围查询先将查询的部分排除掉,如果id是主见则加上order by使用主键

select * from student id >999 order by id limit 20

注意查询字段类型匹配

注意查询字段类型匹配,减少类型的转换,

select id from student where id =“1”;

优化:

select id from student where id = 1;

尽量使用union all不要使用union

union all不创建临时表,这在执行大的联合查询中会减少I/O开销,提升查询速度。但对union语句和在最外层使用order by的语句无效。 如下SQL不会产生临时表。

(Select id from t1 order by id) union (select id from sbtest where k=0 order by id);

如下查询会产生临时表

(Select id from t1 order by id) union all (select id from sbtest where k=0 order by id) order by id desc;

Or优化

Or查询会让索引走range扫描类型:

select id from student where id = 1 or id 2;

优化:使用union all

(select id from student id = 1) union all (select id from student id = 2)

Count(*)优化

我们直接使用count(*)是走的唯一索引,

select count(*) from student

优化:后面加个聚集索引的判断

select count(id) from student id>0

ON DUPLICATE KEY UPDATE优化

ON DUPLICATE KEY UPDATE一般执行插入的时候如果主键冲突了,mysql执行更新语句,如果没有冲突则执行插入语句。

INSERT INTO student(name, age, id) VALUES(‘zhangsan’,‘12’,1)
ON DUPLICATE KEY UPDATE age=1, name=“张三”

尽量避免使用having

having会全文检索到内存里再次进行筛选。

select name from student group by id having id >40 limit 3

优化后:

select name from student where id>40 group by id limit 3

不要在where当中使用函数

一旦在where中使用了函数,索引就会失效

Select create_time from aa where Date(create_time)>curdate()

优化后:

Select create_time from aa where create_time > DATE_FORMAT(curdate(), ‘%Y-%m-%d’)

注意查询的数据量

当数据量大于百分之20的时候,会进行全文检索,因此我们一般查询都会加个范围查找不要全部查询。

Select count(id) from t1 where datetime between '2018-03-15 00:00:00’and '2018-03-16 23:59:59’and state=0;

合理建立索引

当索引包含的是平均分布的数据集时,进行全表扫描比读取索引更快。比如数据表有个字段是性别,它有两个平均分布的值(男和女)。通过这两个值分别可以读取大约50%的记录,这种情况进行全表扫描更快,因此不适合在性别上建立索引。

order by 索引优化

当查询有条件的进行索引时,最好建立索引和order by的联合索引。

select id,name from student where id >123 order by age asc;

这个情况id 和 age最好建立联合索引,这样可以避免using firesort排序。 此外,order by子句后的字段顺序要一致,即要么全部升序,要么全部降序。

小表驱动大表

leftjon的时候使用小表去驱动大表进行查询

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值