1、explain
explain能够查看sql语句的执行计划,查看是否使用了索引,有没有做全表扫描,这些信息对于我们sql的优化有着很大作用
示例
由上图可知对执行的sql添加explain会返回以下数据
id:选择标识符
select_type:标识查询的类型
table:输出结果集的表
paritions:匹配的分区
type:表示连接的类型
possible_keys:表示查询的时候,可能使用到的索引
key:表示实际使用到的索引
key_len:索引字段的长度
ref:列与索引的比较
rows:扫描出的行数
filtered:按照表条件过滤的行百分比
extra:执行情况的描述和说明
1.1 id
select标识符,即sql执行的查询序列号
1、id相同时,执行顺序从上向下
2、如果是子查询,id的序号会递增。id值越大,越先被执行
1.2 select_type
表示查询中每个select子句的类型
(1) SIMPLE(简单SELECT,不使用UNION或子查询等)
(2) PRIMARY(子查询中最外层查询,查询中若包含任何复杂的子部分,最外层的select被标记为PRIMARY)
(3) UNION(UNION中的第二个或后面的SELECT语句)
(4) DEPENDENT UNION(UNION中的第二个或后面的SELECT语句,取决于外面的查询)
(5) UNION RESULT(UNION的结果,union语句中第二个select开始后面所有select)
(6) SUBQUERY(子查询中的第一个SELECT,结果不依赖于外部查询)
(7) DEPENDENT SUBQUERY(子查询中的第一个SELECT,依赖于外部查询)
(8) DERIVED(派生表的SELECT, FROM子句的子查询)
(9) UNCACHEABLE SUBQUERY(一个子查询的结果不能被缓存,必须重新评估外链接的第一行)
![]()
1.3 table
显示这一步所访问的数据库中表名称
1.4 type
查找数据的访问方式
常用的类型有:
ALL、index、range、 ref、eq_ref、const、system、
NULL(从左到右,性能从差到好)
ALL:将全表扫描,找到所需要的行
index:只遍历索引数
range:只检索给定范围的行
ref:表示上述表的连接匹配条件
1.5 possible_keys
表示查询涉及到的字段上若存在索引,则改索引被列出,但不一定真实的使用这个索引
1.6 key
表示实际使用的索引,这个索引必然包含在possible_keys中
1.7 key_length
表示索引中使用的字节数
1.8 ref
列与索引的比较,表示上述表的连接匹配条件,即哪些列或常量用于查找索引列的值
1.9 rows
估算出的结果集行数
1.10 Extra
包含mysql解决查询的详细信息
2、从哪几个维度优化数据库性能的问题
1、数据库配置,客户端连接服务端,并发的情况下,数据库的连接不够
- 服务端设置最大的连接数 show variables like ‘max_connections’ ,修改连接数的命令:set GLOBAL max_connections=100; 或者直接修改配置文件
- 客户端使用连接池,应用池化技术不需要新建一个连接,MyBatis自带一个连接池,或者阿里的druid.这里注意并不是连接池的连接数越大越好,相反连接数越大会影响性能,因为这根cpu的性能有关系,当维护的线程数越多,CPU处理不过来
2、架构层面的优化
- 引入一个独立运行的缓存中间件,分担数据库的压力;
- 主从分离进行读写分离
- 水平分库分表
3、存储引擎的选择与表结构设计
- MyISAM
不支持事务:对事务要求的业务场景不能使用
表级锁定 :锁机制是表级索引,降低了其并发的性能
读写互相阻塞:不仅会在写入的时候阻塞读取,读取的时候也会阻塞写入,但读本身并不会阻塞另外的读
使用场景:
- 不需要事务支持的业务
- 并发相对较低
- 数据修改相对较少,以读为主
- 数据一致性要求不是非常高
- InnoDB
具有事务支持:支持4个事务的隔离级别
行级锁定,全表扫描仍然是表锁
读写阻塞与事务的隔离级别有关
使用场景:
- 需要事务支持
- 数据更新较为频繁的场景
- 数据一致性要求较高
- 表结构设计:选择合理的存储引擎,字段设计考虑大小
4、SQL,索引优化
a、返回数据避免*,需要啥字段,返回啥字段
b、SQL语句中IN包含的值不应太多,对于连续查询的能用between就不要用in
c、当只需要一条数据的时候,使用limit
d、如果排序字段没有用到索引,就尽量少排序
e、如果限制条件中其他字段没有用到索引,少用or
f、不建议使用like’%name’ 或者 like ‘%name%’,这样查询会导致索引失效从而进行全表扫描,如果想要的如此查询的话,建立全文索引
创建全文索引:alter table 表名 add fulltext index ‘索引名’ (字段1,字段2)
使用全文索引:select id ,fnum,ddst from 表 where match(user_name) against(‘name’ in boolean mode);
g:范围查询或者一些函数计算都会导致索引失效
h:关联查询尽量使用inner join,避免left join,因为前者会自动选择数据小的表作为驱动表,利用小表驱动大表
i:合理的使用创建索引
5、业务层次的优化
- 充值送奖金的业务,银行卡支付性能会低于充值的支付
- 限流,MQ