MySql语句优化

1、Mysql提供了一个EXPLAIN命令,它可以对SELECT语句进行分析,并输出SELECT执行的详细信息,以供开发人员针对性优化。EXPLAIN命令用法十分简单,在SELECT语句前加Explain就可以了,例如:EXPLAIN SELECT * from user_info WHERE id < 300;

2、Explain命令的输出格式如下:

     id:SELECT查询的标识符。每个SELECT都会自动分配一个唯一的标识符

     select_type:SELECT查询的类型

     table:查询的是哪个表

     partitions:匹配的分区

     type:join类型

      possible_keys:此次查询中可能选用的索引

      key:此次查询中确切使用到的索引

      key_len:此次查询中确切使用到的索引长度

      ref:哪个字段或常数与key一起被使用

      rows:显示此次查询一共扫描了多少行。这个是一个估计值

      filterd:表示此查询条件所过滤的数据的百分比

      extra:额外的信息

    注意加粗的五项是开发人员需要重点关注的

3、对type的所有可能的类型进行进一步的剖析

    通过这个值可以判断是全表扫描还是索引扫描

     1)表中只有一条数据的时候,这个值是const;

     2)eq_ref通常出现在多表的join查询,表示对于前表的每一个结果都只能匹配到后表的一行结果。并且查询的比较操作通   

          常是=,查询效率较高。

     3)  ref:此类型通常出现在多表的join查询,针对于非唯一或者非主键索引,或者是使用了最左前缀规则索引的查询。

     4)range:表示使用索引范围查询,通过索引字段范围获取表中部分数据记录。这个类型通常出现在=,<>,>,>=,<,<=,IS NULL,<=>,BETWEEN, IN操作中。当type是range时,那么EXPLAIN输出的ref字段为NULL,并且key_len字段是此次查询中使用到的索引的最长的那个。

     5)index:表示全索引扫描,和ALL类型类似,只不过ALL类型是全表扫描,而index类型则仅仅扫描所有的索引,而不扫描数据。index类型通常出现在:所要查询的数据直接在索引树中就可以获取到,而不是需要扫描数据。当是这种情况时,Extra字段会显示Using index。

     6)ALL:表示全表扫描,这个类型是查询是性能最差的查询之一。通常来说,我们的查询不应该出现ALL类型的查询,因为这样的查询在数据量大的情况下,读数据库的性能是巨大的灾难。如果一个查询是ALL类型的查询,那么一般来说可以对响应的字段添加索引来避免。

4、如果排序字段没有用到索引,就 尽量少排序

5、如果限制条件中其他字段没有索引,尽量少用or

     or两边的字段中,如果有一个不是索引字段,而其他条件也不是索引字段,会造成该查询不走索引的情况。很多时候使用 union all 或者是union(必要的时候)的方式来代替“or”会得到更好的效果

6、区分in和exists, not in和not exists

select * from 表A where id in (select id from 表B)

上面sql语句相当于

select * from 表A where exists(select * from 表B where 表B.id=表A.id)

区分in和exists主要是造成了驱动顺序的改变(这是性能变化的关键),如果是exists,那么以外层表为驱动表,先被访问,如果是IN,那么先执行子查询。所以IN适合于外表大而内表小的情况;EXISTS适合于外表小而内表大的情况。
关于not in和not exists,推荐使用not exists,不仅仅是效率问题,not in可能存在逻辑问题。如何高效的写出一个替代not exists的sql语句?

原sql语句

select colname …  from A表 where a.id not in (select b.id from B表)

高效的sql语句

select colname …  from A表 Left join B表 on where a.id = b.id where b.id is null

7、避免在 where 子句中对字段进行 null 值判断

对于null的判断会导致引擎放弃使用索引而进行全表扫描

8、避免在where子句中对字段进行表达式操作

比如

select user_id,user_project from user_base where age*2=36;

中对字段就行了算术运算,这会造成引擎放弃使用索引,建议改成

select user_id,user_project from user_base where age=36/2;

9、对于联合索引来说,要遵守最左前缀法则

举列来说索引含有字段id,name,school,可以直接用id字段,也可以id,name这样的顺序,但是name;school都无法使用这个索引。所以在创建联合索引的时候一定要注意索引字段顺序,常用的查询字段放在最前面

10、关于JOIN优化

 

  • LEFT JOIN A表为驱动表
  • INNER JOIN MySQL会自动找出那个数据少的表作用驱动表
  • RIGHT JOIN B表为驱动表

注意:MySQL中没有full join,可以用以下方式来解决

select * from A left join B on B.name = A.name 
where B.name is null
 union all
select * from B;

尽量使用inner join,避免left join

参与联合查询的表至少为2张表,一般都存在大小之分。如果连接方式是inner join,在没有其他过滤条件的情况下MySQL会自动选择小表作为驱动表,但是left join在驱动表的选择上遵循的是左边驱动右边的原则,即left join左边的表名为驱动表。

合理利用索引

被驱动表的索引字段作为on的限制字段。

利用小表去驱动大表

从原理图能够直观的看出如果能够减少驱动表的话,减少嵌套循环中的循环次数,以减少 IO总量及CPU运算的次数。

巧用STRAIGHT_JOIN

inner join是由mysql选择驱动表,但是有些特殊情况需要选择另个表作为驱动表,比如有group by、order by等「Using filesort」、「Using temporary」时。STRAIGHT_JOIN来强制连接顺序,在STRAIGHT_JOIN左边的表名就是驱动表,右边则是被驱动表。在使用STRAIGHT_JOIN有个前提条件是该查询是内连接,也就是inner join。其他链接不推荐使用STRAIGHT_JOIN,否则可能造成查询结果不准确。

这个方式有时可能减少3倍的时间。

这里只列举了上述优化方案,当然还有其他的优化方式,大家可以去摸索尝试,感谢关注。。

   typ。e: jo

MySQL MySQL

MySQL 提供了一个 EXPLAIN 命令, 它可以对 SELECT 语句进行分析, 并输出 SELECT 执行的详细信息, 以供开发人员针对性优化.

EXPLAIN 命令用法十分简单, SELECT 语句前加上 Explain 就可以了, 例如:

 

EXPLAIN SELECT * from user_info WHERE  id < 300;

MySQL 提供了一个 EXPLAIN 命令, 它可以对 SELECT 语句进行分析, 并输出 SELECT 执行的详细信息, 以供开发人员针对性优化.

EXPLAIN 命令用法十分简单, SELECT 语句前加上 Explain 就可以了, 例如:

 

EXPLAIN SELECT * from user_info WHERE  id < 300;

对于MySQL语句优化,以下是一些建议: 1. 确保正确的索引:创建适当的索引可以显著提高查询性能。根据查询的特点和表的结构,选择合适的索引列和索引类型。 2. 优化查询语句:使用正确的查询语句可以减少数据库的负担。避免使用SELECT *,只选择需要的列。合理使用JOIN,避免多次嵌套子查询。 3. 避免全表扫描:全表扫描会导致性能下降。通过合理使用索引、优化查询语句和分页等方式,尽量避免全表扫描。 4. 使用EXPLAIN分析查询计划:通过使用EXPLAIN命令分析查询计划,可以了解MySQL是如何执行查询的,从而找到潜在的性能问题。 5. 合理配置服务器参数:根据服务器的硬件资源和实际负载情况,合理配置MySQL的参数,如缓冲区大小、连接数等。 6. 避免过度使用触发器和存储过程:触发器和存储过程会增加数据库的负担,应谨慎使用,并定期检查其性能影响。 7. 定期优化表结构:根据实际需求和数据变化情况,定期检查和优化表结构,包括字段类型、表关系等。 8. 合理使用缓存:使用缓存可以减少数据库访问次数,提高性能。根据业务需求,合理选择缓存策略和工具。 9. 定期维护和优化数据库:定期进行数据库维护工作,如备份、索引重建、碎片整理等,保持数据库的健康状态。 请注意,以上建议仅供参考,具体优化策略需要根据实际情况进行分析和调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值