文章目录
一. 配置文件
1.查询日志
- log-bin :二进制日志,主要用于主从复制,二进制日志文件
- log-err :
默认是关闭的
,用来记录严重的警告和错误提示,每次启动和关闭的详细信息等 - log: 查询日记。比如记录一下,查询时间超过
5s
的记录
windows 下的配置文件叫做
my.int
文件,linux 下的配置文件是/etc/my.cnf文件
。
2.数据文件
- 两系统
- frm 文件: 存的是表结构
- myd 文件: 存放的是表数据
- myi 文件: 存放的是表索引
myd
和 myi
连个就像是指针。两个互相指
二.Mysql 的逻辑架构
mysql本身就是一个分层的,可拔插的程序结构。
插件式的存储引擎架构将查询处理和其他的系统任务以及数据的存储提取相分离。这种架构可以根据业务的需求和时间需要合理的选择合适的存储引擎。
2.1 连接层
最上面,是一些客户端和连接服务,包含本地的sock
通信和大多数的 服务器和客户端额链接,类似于TCP/IP
协议,主要用于类似一些安全处理,还有授权认证等相关的方案,该层还引入了 线程池的 概念,为通过授权认证的客户端提供线程,同样在该层上可以实现基于 SSL
的安全链接。服务器也会为安全接入的每个客户端,验证它所具有的操作权限。
2.3服务层
服务层,第二层的框架完成大多数的服务功能,如SQL
接口,必须完成缓存的查询,SQL
的分析和优化,以及部分内置函数的执行,所有跨存储引擎的功能也在这一层实现,如 过程
,函数
等,在该层中,服务器会解析查询,并创建相应的内部解析树,并对其完成相应的优化,如确定查询表的顺序,是否利用索引,最后生成相应的执行操作。如果是 select
语句,服务器会查询内部的缓存,如果缓存空间足够大,这样在解决大量读操作的时候,就能很好提升系统的性能。
2.4 引擎层
储存引擎层,引擎层真正的负责了 MySQL
中数据的存储和提取,服务器通过API
和存储引擎进行通信,不同的存储引擎具有的功能不同,这样我们能根据自己的实际需求进行选取,后面介绍mylsam
和 innoDB
,
2.5 存储层
真正的进行文件存储的地方。主要是将数据存储在运行于裸设备的文件系统之上,并完成与存储引擎的交互。
三.存储引擎
3.1查看存储引擎
SHOW ENGINES
对比项 | MyISAM | InnoDB |
---|---|---|
主外键 | 不支持 | 支持 |
事务 | 不支持 | 支持 |
行表锁 | 表锁,即使操作一条数据,也会锁住整个表,不适合高并发操作 | 行锁,操作时候只能锁定某一行,不对其它行有影响,适合高并发的操作 |
缓存 | 只缓存索引,不缓存真实数据 | 不仅缓存索引还要缓存真实数据,对内存要求比较高,而且内存的大小对性能有决定性的影响 |
表空间 | 小 | 大 |
关注点 | 性能 (偏读) | 事务 |
默认安装 | Y | Y |
3.2 索引优化分析
1.性能下降 SQL 慢,执行时间长,等待时间长
- 查询语句写的烂,没有建立索引或者索引失效。
- 索引失败,单值- - -复合
- 关联查询太多
join
(设计缺陷或不得已的需求) - 服务器调优及各个参数设置(缓冲,线程数)
3.3 建立索引
- 单值索引
- 复合索引
CREATE TABLE; #建表
CREATE INDEX; #建索引
单值索引
比如我们要查student
表的 name
字段,可以用如下命令建立索引。默认的索引名就是 idx_表名_字段名
。
CREATE INDEX `idx_student_name` on studentes(name);
复合索引
一般比如在淘宝买东西的时候,会有按照多个条件进行查询,这种情况下,如果使用 sql
语句,就相当于用 AND
关键字进行连接。
SELECT * FROM `studentes` WHERE `name`='小王' AND `classid`='2';
CREATE INDEX idx_students_nameClassid on studentes(`name`,`classid`);
查看索引表
show INDEX from `student`
mysql 的书写顺序和执行顺序
书写顺序
select
<要返回的数据列>
from
<表名>
<join, left join, right join...> join
<join表>
on
<join条件>
where
<where条件>
group by
<分组条件>
having
<分组后的筛选条件>
order by
<排序条件>
limit
<行数限制>
执行顺序
机读的时候,电脑会先从 from
开始执行,而不是从 select
开始执行,因为电脑更在乎的是在哪个表里查找。
from
<表名> # 笛卡尔积
on
<筛选条件> #对笛卡尔积的虚表进行筛选
<join, left join, right join...> join
<join表> #指定join,用于添加数据到on之后的虚表中,例如left join会将左表的剩余数据添加到虚表中
where
<where条件> #对上述虚表进行筛选
group by
<分组条件> #分组
<sum()等聚合函数> #用于having子句进行判断,在书写上这类聚合函数是写在having判断里面的
having
<分组筛选> #对分组后的结果进行聚合筛选
select
<返回数据列表> #返回的单列必须在group by子句中,聚合函数除外
distinct
order by
<排序条件> #排序
limit
<行数限制>
四.索引
索引是帮助 MySQL
高效获取数据的数据结构,可以得到索引的本质,索引是数据结构。
索引是一种数据结构
索引的目的在于提高查询效率,可以类比字典
索引就是排好序的快速查找数据结构
数本身之外,数据库还维护着一个满足特定查找算法的数据结构,这些数据结构,以某种方式指向数据,这样可以在这些数据结构的基础上,实现高级查找算法,这种数据结构就是索引。也就是 B
树索引。
索引简单点来理解,就是排好序的快速查找数据结构。
- 索引对查找和排序都会有明显的影响
4.1为什么增删慢,查找快
- 查找就是直接查
- 而增删其实就是要建立索引树,所以频繁增删的数据不适合做索引
4.2 索引的结构
- BTree 索引
- Hash 索引
- full-text 全文索引
- R-Tress 索引
真实的情况是,3层的 B+ 树可以表示上百万的数据,如果上百万的数据,查找只需要 三次IO ,性能的提升将会是巨大的,如果没有索引,每个数据项都要发生一次IO,那么总共几百次的
IO
,显然成本非常的高。
如果我们平时所说的索引,如果没有特殊指名,指的都是 B 树索引(多路搜索树,并不一定是二叉的)结构组织索引,除了 B
树索引以外,还是 hash
索引。
三百万以上的数据,就需要做数据优化了。
索引的劣势
- 索引实际上也是一张表,他也要占空间
- 虽然索引大大提高了查询的速度,但是也降低了更新表的速度
- 更新表的时候,不仅要更新数据,还要更新索引
- mysql 目前一个表里最多只能建立
16个索引
- 但如果你在一个大表上创建了多种组合索引,索引文件的会膨胀很快
单值索引
- 即一个索引只包含一个列,一个表可以有多个单例索引
唯一索引
- 索引列的值必须是唯一的,但是允许为空值,比如,银行卡号
复合索引
- 即一个索引包含了多个列, 比如在银行系统中,可以根据名字和地址做索引。
查找的过程:
这样相当于只做三次 IO
就可以了。
什么时候应该建立索引
- 主键自动建立唯一索引
- 频繁作为查询条件的字段应该创建索引
- 外键应该建立索引
- 频繁更新的字段不适合建立索引
where
用不到的数据不适合建立索引- 单键索引和组合索引在一起的时候,我们应该建立
组合索引
- 查询中的排序字段,若排序字段通过索引去访问,将大大的提高排序速度
- 分组时候要用到索引
什么时候不建议使用索引
- 表的记录低于
300w
条的时候 - 经常增删的表
- 数据重复且平均的表,建立索引的意义不大。(比如,一个表中有2000条数据,有 1980条不同,那么索引的选择性就是1980/2000=0.99),一个索引的选择性越接近于1,这个索引的效率就越高。
性能分析
- mysql query optimizer,自带的优化器
- mysql 常见的瓶颈。
-
CPU:cpu 饱和,一般发生在,数据装入内存,或者从磁盘中读取数据的时候,
-
磁盘IO 一般发生在装入的数据,远大于内存容量的时候,
-
服务器硬件瓶颈
- Explain:
Explain 关键字
explain 是干什么的?
使用explanin
关键字,可以模拟优化器执行SQL
查询语句,从而知道MySQL
是如何处理你的 SQL
语句的,分析你的查询语句或者是表结构的性能瓶颈。
直接在SQL
语句的前边加上 EXPLAIN
即可。
EXPLAIN SELECT * FROM class;
explan主要能干的几件事
- 表的读取顺序
- 数据读取操作的操作类型
- 哪些索引可以被使用
- 哪些索引被实际使用
- 表之间的引用
- 每个表有多少行被优化器查询
explain关键字 - id
select 查询的序列号,包含一组数字,表示查询中执行 select
子句或者操作表的顺序。
- id 相同,执行顺序,有上至下。
比如下边的表,id
都相同,那么执行顺序就应该由 table
至上到下执行。
- 如果是子查询,
id
的序号,会递增,id
越大优先级别越高,越先被执行。
所以由上表也可以看出来,SQL的执行顺序和你写的顺序,不一定相同。
explain-select_type
- simple :简单的select 查询,查询中不包含子查询或者 union
- primary:查询中若包含任何复杂的子查询,最外层查询则被标记为
- subquery:在
select1
或者where
列表中包含子查询 - derived:在
from
表中包含的子查询被标记为derived(衍生)
,mysql
会递归执行这些子查询,把结果放在临时表里。 - union:若第二个 select 出现在 union之后,这被标记为 union:若union包含在
from
子表的查询中,外层的select
,就会被标记为derived
。
explain-type
从最好到最差,依次如下
- system
- const
- eq_ref
- ref
- range
- index
- ALL
一般来说,至少得保证达到 range 级别,最好达到 ref
explain-possible_keys- keys
- possible_keys :可能用到的索引。
- key:实际用到的索引。
- key_len: 计算查询中使用的索引的长度,在不损失精度的情况下,长度越短越好,
key_len
显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len
是根据表的定义计算出来的,而不是通过表内检索出来的。
若使用了覆盖索引,那么所以索引只出现在 key
列表中,这种情况的出现,就是因为,你要查询的索引,正好和我建立的索引一模一样。
比如下面的情况,你的查询条件越细,查询就越准确,相对应的,key_len 也就越长。
explain - ref
显示索引的哪一列被引用,如果可以的话,是个常数,哪些列或常量被用于查找索引列上的值
比如下面,就是看到的哪个索引字段被充分引用了。
其实可以看到哪些索引可以使用,哪些索引被实际使用。
explain-rows
根据表统计信息以及索引选用情况,大致估算出找到所需要读取的行数。
row这个东西当然是用的越少越好
explain-extra
该选项包含不适合在其他列显示,但是十分重要的额外信息。
using filesort
说明mysql 会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取。mysql中无法利用索引完成的排序操作,称为文件排序using temporary
使用了临时表保存了中间结果,mysql
对查询结果排序时使用了临时表。常见排序order by
和 分组查询group by
。using index
覆盖索引,要建立的索引和你要查的正好重合了。比如你建的是name
和age
两个字段,你查的也是name
和age
两个字段。
热身小例子
Join 关系
内连接
select <select_list>
From TableA A
inner join TableB B
ON A.key=B.key
左连接
select <select_list>
from tableA A
left Join TableB B
on A.key=B.key
右连接
select <select_list>
from TableA A
right join TableB B
on A.key=B.key
A的独有
select <select_list>
from Table A A
left join Table B B
On A.key=B.key
Where B.ke IS NULL
B独有
B独占
select <select_list>
from TableA A
right join TableB B
On A.key=B.key
Where A.key IS NULL
select <select_list>
from TableA A
fullouter JOIN Table B B
ON A.key = B.key
select <select_list>
from TableA A
fullouter JOIN TableB B
ON A.key=B.key
Where A.key is null
or B.key is null
四.索引
索引是帮助 MySQL
高效获取数据的数据结构,可以得到索引的本质,索引是数据结构。
索引的目的在于提高查询效率,可以类比字典
索引就是排好序的快速查找数据结构
数本身之外,数据库还维护着一个满足特定查找算法的数据结构,这些数据结构,以某种方式指向数据,这样可以在这些数据结构的基础上,实现高级查找算法,这种数据结构就是索引。也就是 B
树索引。
4.1为什么增删慢,查找快
- 查找就是直接查
- 而增删其实就是要建立索引树
4.2 索引的结构
- BTree 索引
- Hash 索引
- full-text 全文索引
- R-Tress 索引
真实的情况是,3层的 B+ 树可以表示上百万的数据,如果上百万的数据,查找只需要 三次IO ,性能的提升将会是巨大的,如果没有索引,每个数据项都要发生一次IO,那么总共几百次的
IO
,显然成本非常的高。
三百万以上的数据,就需要做数据优化了。
参考文献
https://www.bilibili.com/video/BV12b411K7Zu?p=188&share_source=copy_web