Mysql进阶(sql优化和explain关键字)

一、为什么要对SQL进行优化?

由于业务数据量的增多,SQL的执行效率对程序的运行效率影响增大,此时就需要对SQL进行优化。

二、SQL优化的方法

1.查询sql尽量不要使用select * ,而是具体字段。

节省资源,减少开销。

2.避免在where子句中使用or来连接条件。

反例:

SELECT * FROM user WHERE id=1 OR salary=5000

正例:使用union all把两个sql结果合并。

SELECT * FROM user WHERE id=1

union all

SELECT * FROM user WHERE salary=5000

使用or可能会使索引失效,从而全表扫描。

对于or没有索引的salary这种情况,假设它走了id的索引,但是走到salary查询条件时,它还得全表扫描。

3.尽量使用数值替代字符串类型

正例:

主键(id):primary key优先使用数值类型int

性别(gender):0代表女,1代表男;数据库没有布尔类型,mysql推荐使用tinyint

因为引擎在处理查询和连接时会逐个比较字符串中的每一个字符,而对于数值型而言只需要比较一次就够了,字符会降低查询和连接的性能,并会增加存储开销。

4.使用varchar代替char

varchar是变长字段,按数据内容实际长度存储,可以节省存储空间;

char按声明大小存储,不足时补空格;

其次对于查询来说,在一个相对较小的字段内搜索,varchar效率更高

5.对查询进行优化,应尽量避免全表扫描,首先考虑在where及order by,group by涉及的列上建立索引。

6.应尽量避免索引失效

6.1 应尽量避免在where子句中使用or来连接条件,否则将导致引擎放弃使用索引而进行全表扫描。如:select id from t where num=10 or num=20

6.2 in和not in也要慎用,否则会导致全表扫描。

如:select id from t where num in (1,2,3),对于连续的数值,能用between就不要用in,即改写为:

select id from t where num between 1 and 3;

6.3 模糊查询也将导致全表扫描

select id from t where name like '%abc%'

6.4 应尽量避免在where子句种对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。如:select id from t where substring(name,1,3)='abc'

7.提高group by语句效率

反例:先分组,再过滤。

正例:先过滤,再分组

8.清空表时优先使用truncate

truncate table 比delete速度快,且使用的系统和事务日志资源少。

delete语句每次删除一行,并在事务日志中为所删除的每行记录一项。truncate table通过释放存储表数据所用的数据页来删除数据。

9.表连接不宜太多,索引不宜太多,一般5个以内。

联的表个数越多,编译的时间和开销也就越大。

每次关联内存中都生成一个临时表。

应该把连接表拆成几个较小的几个执行,可读性更高。

10.深度分页问题

反例:select id,name from account limit 100000,10;

正例:select id,name from account where id > 100000 order by limit 10;

详细请看下文链接:

https://blog.csdn.net/qq_43631716/article/details/117172605

11.使用explain分析SQL执行计划

三、执行计划

explain:

使用explain关键字可以模拟优化器执行SQL查询语句,从而知道MYSQL是如何处理自己的SQL语句的。分析自己的查询语句或是表结构的性能瓶颈。

explain作用:

1.表的读取顺序

2.数据读取操作的操作类型

3.哪些索引可以被使用

4.哪些索引可以被实际使用

5.表之间的引用

explain使用:

在select语句之前增加explain关键字,执行查询会返回执行计划的信息,而不是执行SQL

EXPLAIN SELECT * FROM users WHERE id>3

explain出来的信息有12列,分别是:

id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra

概要描述:

1.id:选择标识符

2.select_type:表示查询的类型

3.table:输出结果集的表

4.type:表示表的连接类型

5.possible_keys:表示查询时,可能使用的索引

6.key:表示实际使用的索引

7.key_len:索引字段的长度

8.rows:扫描出的行数(估算的行数)

9.Extra列:附加信息

id:

select识别符,这是select的查询编号

id如果相同,可以认为是一组,从上往下顺序执行,在所有组中,id值越大,优先级越高,越先执行。

 SELECT * FROM users u,test t WHERE u.id = t.id

 SELECT * FROM users u WHERE u.id = (SELECT id FROM test t WHERE id =1)

select_type:

表示查询中每个select子句的类型

1)SIMPLE(简单SELECT,不使用UNION或子查询等)

2)PRIMARY(子查询中最外层查询,查询中若包含任何复杂的子部分,最外层的select被标记为PRIMARY)

3)SUBQUERY(子查询中的第一个SELECT,结果不依赖于外部查询)

4)DERIVED(派生表的SELECT,FROM子句的子查询)

5)UNION(UNION中的第二个或后面的SELECT语句)

type:

对表的访问形式,表示MySQL在表中找到所需行的方式,又称“访问类型”。

常用的类型有:system>const>eq_ref>ref>range>index>ALL(从左到右,性能从好到差)

system

表只有一行记录(等于系统表),平时不会出现,可忽略不计。

const

表示通过索引一次就找到了,const用于比较primary key或者unique索引。

eq_ref

唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见于主键或唯一索引扫描。

ref

非唯一性索引扫描,返回匹配某个单独值的所有行。本质上也是一种索引访问,它返回所有匹配某个单独值的行,然而,它可能会找到多个符合条件的行,所以它应该属于查找和扫描的混合体。

range

值检索给定范围的行,使用一个索引来选择行。key列显示使用了哪个索引,一般就是你在where语句中出现了between、<、>、in等查询,这种范围扫描索引比全表扫描要好,因为它只需要开始于索引的某一点,而结束于另一点,不用扫描全部索引。

index

Full Index Scan,index与ALL区别为index类型只遍历索引树。这通常比ALL快,因为索引文件通常比数据文件小。也就是说,虽然ALL和Index都是读全表,但Index是从索引中读取的,而ALL是从硬盘中读取的。

ALL

Full Table Scan,将遍历全表以找到匹配的行。

一般来说:得至少保证查询达到range级别,最好能达到ref

possible_keys

显示可能应用在这张表中的索引,一个或多个。

查询涉及到的字段上,若存在索引,则该索引将被列出,但不一定被查询实际使用。

key

实际使用的索引。如果为NULL,则没有索引,或者索引失效。

key_len

表中索引中使用的字节数,可通过该列计算查询中使用的索引长度。在不损失精确度的情况下,长度越短越好。

博主认为以下这篇文章能更好的帮助大家了解认识explain关键字,大家可以看看哟

【最全最详细explain讲解】explain | 索引优化的这把绝世好剑,你真的会用吗?_检查索引的使用情况 expian-CSDN博客

 

  • 17
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值