mysql数据库简介
mysql是一个关系型数据库,同时mysql也是一个开源的数据库,通俗的来讲就是插件式引擎数据库,下面可以看下mysql的架构。
关于数据引擎之前写过一篇公众号,mysql数据库引擎,内容都是从网易出的《Mysql技术内幕》里总结的,关于数据库引擎这里就强调下innoDB存储引擎和MyISAM存储引擎。
- innoDB存储引擎:innoDB存储引擎是mysql5.5.8默认的存储引擎,innoDB的设计主要是面向OLTP的应用,其特点是支持事物、行锁设计、支持外键。
- MyISAM存储引擎:不支持事物、表锁设计、支持全文索引,主要面向一些OLAP数据库的应用,在MySQL5.5.8版本之前是默认的存储引擎。
Mysql查询
其实对于开发人员来说,我们最常写的sql就是查询,那么对于查询来说一个很大的课题就是如何避免慢sql,我这边大概有两个思路去规避慢sql,第一就是了解sql执行前要做的事情,第二就是关注sql执行过程中做的事情,而想要明白这两个点,就要首先明白逻辑查询和物理查询。
逻辑查询
sql语言和大多数语言是不同的,比如说我们的java语言,他是一行一行的执行的(不考虑指令重排序),但是sql语言的执行并不是顺序执行的,而是有他的逻辑顺序,可以简单的理解为一条sql的执行计划。下面看下一条sql的逻辑顺序:
可以看到一条sql的执行分为11步,第一步是from语句,最后一步是limit语句,至于每一步的详细介绍就不粘贴了,放一张我之前画的图吧:
顺便提一句这个图非常重要,其中有两个问题可以思考:
- 过滤条件有了where关键字为什么还要有having?
答:where语句的执行顺序在分组前,分组聚合后不能使用where语句进行过滤了,所以才有了having - 大数据limit分页为什么慢?
答:limit的语句在sql执行计划的最后一步,所以当存在limit 1000000,20的情况下,是先查出了100万零20条数据最后剔除100万数据,也就是说本身我们只想要20条数据但是我们要查出100多万的数据,所以当数据量大的时候不能使用limit分页,具体解决方案可以参考:大数据量分页
物理查询
物理查询是获取数据真正的查询,物理查询的结果和我们编写的sql的逻辑查询结果一样,那么既然这样为什么还有物理查询?答案是优化,mysql的架构不是有解析器和优化器组件吗?逻辑查询经过解析器的解析,再经过优化器的优化后选择一条Mysql认为最优的解来查询出结果。
所以可以理解为物理查询是数据库帮我们的一次优化,但是!!!数据库并不能保证优化的100%最优。因为mysql的优化器是基于采点预估的方式选择最佳路径的,为什么不全表扫描?如果优化要采取全表扫描的方案,那还不如不优化了,直接怼算了,当然mysql的采点肯定不是我们想象的那么简单,不过保险起见,最好还是EXPLAIN下.
EXPLAIN
- id: MySQL Query Optimizer 选定的执行计划中查询的序列号。表示查询中执行 select
子句或操作表的顺序,id值越大优先级越高,越先被执行。id 相同,执行顺序由上至下。 - select_type:查询类型,SIMPLE、PRIMARY、UNION、DEPENDENT UNION等。
- table:显示这一行的数据是关于哪张表的
- type:这是重要的列,显示连接使用了何种类型。从最好到最差的连接类型为const、eq_reg、ref、range、indexhe和all
- possible_keys:显示可能应用在这张表中的索引。如果为空,没有可能的索引。可以为相关的域从where语句中选择一个合适的语句
- key:实际使用的索引。如果为null,则没有使用索引。很少的情况下,mysql会选择优化不足的索引。这种情况下,可以在select语句中使用use index(indexname)来强制使用一个索引或者用ignore index(indexname)来强制mysql忽略索引
- key_len:使用的索引的长度。在不损失精确性的情况下,长度越短越好
- ref:显示索引的哪一列被使用了,如果可能的话,是一个常数
- rows:mysql认为必须检查的用来返回请求数据的行数
- extra:关于mysql如何解析查询的额外信息。
简单总结下,这里我比较关注的是key和rows,key是实际走的索引,rows是扫描行,如果你发现实际走的索引不是最优的,这时你可以强制使用你认为最优的索引,这就是Mysql优化器没能最优的一个例子。
索引
索引这里其实没有什么可说的了,就随便说点吧,索引不要滥建,真的会影响写的性能,比如说B+树索引,每次插入和删除都可能导致树的左旋或者右旋;还有索引长度不要太长,索引的维护本来就是额外的开销,所以越短越好;最后尽量使用BTHREE索引,因为大于和小于也可以使用到索引。
踩过的一些坑
- 第一个坑是上线发现索引忘了建了,慢sql卡的我想抽死自己,这里还是要提醒一定要评估是否需要建索引。
- 不要随便修改线上表结构,我一个同事在高峰期修改一个接近亿级数据的表的字段信息差点导致我们宕机,尽量交给专业的人去做,如果没有,操作前还是要做好功课。
- 代码层面通过id分页拉取数据,拉取重复,最后分析sql不是很规范,分页sql双闭合了,业务代码就复杂了,还是尽量左开右闭。
总结
这篇文章是面向开发的,不深不浅,我个人觉得还是很有帮助的,欢迎大家一起学习探讨。