mysiam和innoDB区别<br>
mysiam不支持事务,行锁,外键,崩溃后无法安全恢复<br>
innoDB对比mysiam写的效率差一些,并且占用更多的磁盘空间保存数据和索引,mysiam只缓存索引<br>
针对数据统计有额外的数据存储 故而针对count(*)效率更高<br>
mysql二阶段提交<br>
开始事务更新数据写入redolog(prepare阶段)提交事务写入binlog和设置redoglog为commit标志<br>
如果在写入redolog(prepare)时崩溃 此时是满足数据一致性的此时拿着事务id去binlog中去找没有找到则回滚,如果在binlog中找到则设置redolog为commit提交数据
当事务提交时先把 redolog写到操作系统的缓存区,并不会对redolog持久化,这种情况如果数据挂了,操作系统并没有挂,那么事务的持久新还是可以保证的
mysql的执行流程
1.客户端与服务端进行连接
2 查询缓存,查询到数据则返回记录(mysql 8.0已经删除)<br>
3查询不到则解析器进行词法分析和语法分析生成语法树<br>
4 预处理器进行校验表名和字段名<br>
5,优化器来计算执行sql语句的成本,选择执行成本最低的
6 执行器则调用api来到存储引擎来检索相应的数据
什么是bufferpool
如何判断一个页是否在bufferpool缓存中 ,mysql 中有一个哈希表的数据结构,,使用表空间号和数据页作为key,缓冲页对应的控制快(新加载的数据页)作为value,如果查询不到则从free 链表中选取一个空闲的缓冲页,,然后把磁盘数据加载到对应的缓冲页<br>
LRU链表
mysql改进了算法升级版的lru列表,将链表分为new和old两部分,加入元素时并不是从表头插入,而是从中间midpoint插入(就是从磁盘中新读出的数据会放在冷数据区的头部,如果数据很快被访问到)那么page 则会向new列表的头部移动,如果没有被访问则向old区尾部移动,等待淘汰<br>
flush链表
对于有修改的加到脏页加到flush链表中mysql需要持久化就从flush链表中找到持久化到磁盘
联表查询的优化点
注意关联字段使用索引
查询字段使用索引 不要select * 不然内存装不下
小表驱动大表
where ,on和having的使用场景区别<br>
where子句在group by分组和聚合函数之前对数据进行过滤<br>
having子句在 group by分组和聚合函数之后进行数据过滤<br>
对于内连接 where子句和on 后面and条件查询一致<br>
对于外连接 where是对连接后过滤 而on后面and条件还是返回全部左表 只对右表限制没有置为null<br>
mysql数据如何在磁盘存储
mysql中数据存放在磁盘中是以数据页存储的一页默认大小为16kb<br>
数据之间是通过双向链表进行连接,页之间页是通过链表进行链接的<br>
mysql中索引的分类<br>
聚簇索引
主键索引(就算没有主键id也会生成隐藏的字段)维护索引树,叶子节点挂着所有数据<br>
普通索引
联合索引<br>
唯一索引
索引中的值唯一的,可以允许为空值<br>
索引原理与sql优化<br>
什么是索引覆盖
查询的列在一颗索引树上就可以获取 无须进行回表操作<br>
什么是回表<br>
当使用非主键索引进行查询时,我们查询的列不在索引树上时,,根据索引树上查询到的主键值去主键索引树上获取完整的数据<br>
什么是索引下推
mysql5.6 引入了索引下推,可以在索引遍历过程中,对索引中包含的字段先做判断,过滤掉不符合条件的记录,减少回表次数,,在引擎层面可以解决的不交给server层,,尽量减少回表io<br>
什么是索引跳跃<br>
mysql8.0引入的优化,某种程度上可以无视最左前缀原则,,不过限制条件如下<br>
select选择字段不能包含非索引字段<br>
sql中不能带group by 和distinct语法<br>
仅仅支持单表查询不支持多表查询<br>
索引失效的场景
使用like关键字时以%开头会导致索引失效
数据类型转换失效
索引字段使用函数转换索引失效
索引列使用加减乘除
不符合最左前缀原则
如果数据库觉的全表扫描比使用索引更快也不会使用索引
or关键字使用必须都是索引列,否则有一个不是索引就会失效
慢sql优化
架构层面<br>
单库有瓶颈则分库分表
主从读写分离<br>
利用缓存<br>
表调优
建立索引,联合索引满足最左前缀原则
能使用覆盖索引的时候尽量使用覆盖索引
根据explain执行计划查看是否使用索引<br>
严格约束字段长度
对于多插入使用批量插入
长的字段建立索引可以使用前缀索引
小表驱动大表
大量数据查询时可以使用分页查询
开启慢查询日志 show variables like 'slow_query_log' 查看是否开启; 开启慢查询<br>set GLOBAL slow_query_log = on; 设置慢查询时间set long_query_time=0;<br>
explain关键字使用
type列
System<br>
constant
利用主键和唯一键查看一行数据时
eq_ref<br>
基于主键或唯一索引链接两个表,对于索引键值只有一条匹配,被驱动表的类型为 eq_ref<br>
ref
关联查询时使用非唯一索引匹配,,简单查询时使用二级索引匹配返回所有匹配某个单行值<br>
range
当使用范围扫描> between 时<br>
index
扫描二级索引 如果 extra有using index表示使用的覆盖索引<br>
id列
如果id序号相同,从上往下执行<br>
如果id序号不同,序号大的先执行<br>
如果两种都存在,先执行序号大的,然后再同级往下执行<br>
如果为null,最后执行,表示结果集,,并且不需要使用它来查询<br>
extra列
using index<br>
使用非主键索引树就可以查询到所需要的数据,一般是覆盖索引,,不需要回表查询<br>
using where
不通过索引查询所需要的数据<br>
using index condition<br>
表示查询列不被索引覆盖,where条件中是一个索引范围查找,过滤完需要回表找到所有符合的数据<br>
using temporary<br>
表示需要使用临时表来查询数据<br>
using filesort<br>
当查询中包含order by 操作而且无法利用索引完成排序操作<br>
MVCC(多版本并发控制)
读已提交每次执行sql查询时都会生成新的readview<br>
可重复读执行第一条查询 sql时生成的readview并且事务结束前都不会发生变化<br>
undolog版本链是指一行数据被多个事务依次修改后,在每个事务修改完成后,mysql 都会保留修改前的数据到undolog中,并且利用事务id和回滚指针两个隐藏字段把这些undolog进行串联起来形成一个历史版本链<br>
readview的机制4个标志位<br>
m_id 当前活跃事务id
如果行数据的最新undolog在当前活跃事务列表中那么一定读不到,因为活跃事务id都时readview生成时还没提交的事务id<br>
min_trx_id m_id 里面的最小值<br>
如果行数据的最新undolog事务id比当前活跃的最小的还要小表明该事务肯定提交了,一定读<br>
max_trx_id 最大值 是创建readview时当前事务的最大id+1<br>
如果行数据的最新undolog事务id比最大的事务id大说明这条事务在生成readview时还没开启肯定不读<br>
creator_trx_id 当前事务id 每开启一个事务都会生成一个<br>
如果行数据的最新undolog的事务id和当前事务id相等,说明时当前事务修改的肯定读<br>
如果最终判断最新的undolog事务id读取不到数据,那么就根据版本链往上找,,然后对比过滤直到找到符合的数据<br>