mysql

MyISAM与InnoDB区别

myisam
只支持表级锁
数据与索引分开存储,有三个文件,每个文件名以表名开头,扩展名指出文件类型。
.frm 用于存储表的定义,.MYD 用于存放数据,.MYI 用于存放表索引
不支持聚簇索引

Innodb
支持事务和行级锁
行锁模式有以下几种:共享锁(读锁),排他锁(写锁),意向共享锁(表锁),意向排他锁(表锁),间隙锁。
数据与索引存储在同一个文件(一个表对应一个文件)
.frm 用于存储表的定义,.ibd 用于存储数据和索引

主从复制

主从复制有两种方式:基于日志(binlog)、基于GTID(全局事务标示符)。

复制类型
1.按row复制
2.按带修改操作的binlog(默认)
3.混合类型的复制

前提:主库得开启binlog
涉及3个线程:
从库IO线程发起连接到主库;主库IO线程发送binlog
从库IO线程保存binlog内容到本地中继日志
从库的SQL线程读取中继日志的内容并解析成sql执行

复制中断重连是否需要重新复制?
会记录每次复制的位置,不需要,但如果隔太久可以考虑重新建立从库。
当从库没有收到主库数据slave-net-timeout秒后,会重新建立连接并获取数据,默认为3600秒

间隙锁

当出现范围内修改的时候,比如update a ***where id>2 and id <6;
会锁定这个范围的数据,如果id=4的数据不存在,出现了间隙,这个时候想插入一条id=4的数据也是会被阻塞的。

聚簇索引和非聚簇索引

每个Mysql的表只能有一个聚簇索引。一般情况下就是该表的主键
聚集索引的索引顺序跟数据的顺序基本一致,这样范围查找的时候,数据就可以一次性取出,而不用从多个数据块提取,减少了io操作。因为这个优点,所以主键一般选用有序的比较好。
而非聚集索引,比如以name属性做的索引,实际存储的数据物理地址可能跟索引的相差很远。

索引采用什么数据结构

因为可能比较大,不适合放在内存,所以选择适合外部存储数据结构。

B-树:
多路自平衡的搜索树 ,类似普通的平衡二叉树,但是B-树允许每个节点有更多的子节点
数据分布在整颗树中
搜索有可能在非叶子结点结束

B+树:
数据都在叶子节点中,查询效率稳定
叶子节点之间形成单向链表,范围内查询更高效
是B-树的变体,也是一种多路搜索树

为什么大多选B+:
因为内节点无数据,所以每个节点能索引的范围更大,更精确,所以单次IO的得到的信息量大于B-树,IO效率更高
B+树,增加了链z指针,能更好的范围区间内查询,而B-数据和索引在一起,没法区间查找

局部性原理与磁盘预读

由于局部性原理:
1.当一个数据被用到时,其附近的数据也通常会马上被使用
2.程序运行期间所需要的数据通常比较集中
所以磁盘读取数据时,为了减少io,一般会顺序向后读一定长度,读取的数据一般为页的整数倍。MySQL每页大小默认为16K(这个值可以修改)

mysql事务隔离级别

默认可以重复读,是因为mysql5.0版本以前,binlog只支持STATEMENT这种格式,这种格式读已提交在主从复制时有bug。5.1版本binlog支持row格式,即按行复制,可以解决。
新版可以同oracle一样设置读已提交。因为可重复读存在间隙锁,而且条件列未命中索引会锁表。

EXPLAIN

查看执行计划注意点:
explain select * from live_recommend_list where create_time >'2019-01-01 00:00:00'

执行计划示例

select_type:查询中每个select子句的类型,SIMPLE(简单SELECT,不使用UNION或子查询等)
type:访问类型。
常用的类型有: ALL, index,  range, ref, eq_ref, const, system, NULL(从左到右,性能从差到好,range:只检索给定范围的行。一个好的sql语句至少要达到range级别。杜绝出现all级别
possible_keys:指出MySQL能使用哪个索引在表中找到记录,查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询使用
key:使用到的索引名。如果没有选择索引,值是NULL。可以采取强制索引方式
key_len:索引长度
rows:扫描行数。该值是个预估值
extra:详细说明。注意常见的不太友好的值有:Using filesort, Using temporary

大表优化顺序

1.优化sql和索引
2.加缓存
3.主从复制,读写分离
4.用mysql自带的分区表,sql条件中要带上分区条件的列,从而使查询定位到少量的分区上。
5.垂直拆分,将一个大的系统分为多个小的系统,也就是分布式系统
6.水平切分,这个就可以参考我之前的文章,怎么不停服迁移数据

sql优化

1.联合索引顺序问题,查询能筛选出更少数据的在前,比如时间+用户id, 如果查询根据用户id和较长时间范围,显然用户id放前面好些。
2.并不是表记录状态不多的都不需要建立索引,比如大量status=0,少量status=1,查询根据status=1也可以建。
3.避免 SELECT *
4.尽可能的使用 NOT NULL
5.bit类型,用索引时,查询可能会没有数据,where status ='0';
6.sql 中in包含的值不应该过多,比如oracel限制了1000,千万不要用多了in拼接去打破这个限制,要想下别人这么限制的原因,不能有超长sql
7.当只需要一条数据的时候,使用limit 1
8.如果排序字段没有用到索引,就尽量少排序
9.看情况合理分页,select id,name from table_name limit 866613, 20 改为select id,name from table_name where id> 866612 limit 20
10.利用小表去驱动大表
11.DATETIME 类型,默认是保存到秒,这个时候用时间戳查询,如startTime>1555603201000,  就会出现不正确的情况, 最好先转成Date类型再来查。

你可能感兴趣的:(mysql)