Mysql
Posted miraclemaker
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mysql相关的知识,希望对你有一定的参考价值。
1.什么是ER图:
- 表示实体,属性和联系的图
- 实体:业务对象,矩形表示。
- 属性:实体的属性字段,椭圆形表示。
- 联系:实体与实体间的关系,能表示业务关系和数量关系,菱形表示。
2.数据库三范式:
- 1NF:属性不可再分。
- 2NF:1NF+非主键列不能对主键的子集产生依赖。
3NF:1NF+2NF+非主键列不能依赖其他非主键列。 - 如果不满足的话,可能数据会很杂乱,很多不应该在一起存放的数据存放在一起,删除的时候就会删多;更新的时候更新的多,考虑的多;
3.外键:
- 主键与外键:
。主键:一个表只能有一个主键,不能为NULL,不能重复。
。外键:一个表可以有多个外键,外键可以为NULL(尚不确定映射到其他标的哪一行),可以重复(可能映射到其他表的好几行,一个员工映射十个订单)。
- 为什么不推荐级联:级联是指更新数据后引发数据库的一连串更新
。存在外键增加了复杂性,编写代码的时候要时刻考虑外键约束;
。数据库为了维护外键,会触发一些检查,拖慢了响应速度;
。大数据下的分库分表无法使用外键。
4.DML跟DDL:
- DML:数据库操作语言,对数据表的增删改查。
- DDL:数据库定义语言,对数据库内部对象的增删改。
5.内连接左连接右连接的区别:
- 内连接:查询两张表的交集部分。
- 左连接:我们一般用左外连接,查询左表全部数据及两表交集(可以查出左表中链接字段为null的数据)
- 右连接:右连接可以化为左连接。
6.数据库设计分几步:
- 分析用户需求,抽取实体,实体属性,实体间的关联关系;
- 构建ER图,将ER图转化为数据表;
- 构建数据库,编程测试,试运行;
- 系统运行,日常维护。
7.sql执行顺序:
- sql执行顺序:SELECT * FROM * WHERE * GROUP BY * HAVING * ORDER BY * LIMIT * ;
- 各种函数的使用:distinct,聚合函数,日期函数,字符串函数等都放在select * from中。
8.char和varchar:
- char:创建的时候指定最大长度,创建后不管进来是多大,长度都固定(最大一个字节,255)
- varchar:创建的时候指定最大长度,但是会根据字符串长度存储(一到二个字节,最长存2^16),存的1-2^8(加一个额外长度),2^8-2^16(加两个额外长度),时间换空间。
9.sql和nosql:
- sql:有严格的标准,操作简单,文档丰富,支持事务ACID,可以进行多表复杂查询,分库分表。
- nosql:不支持事务,高性能高扩展性,更灵活,适合海量数据存储。
。类型分为文档型(MongDB),键值(Redis),图形(Neo4j),宽列(HBase)。
10.mysql的体系结构:
- 连接层:管理连接,权限认证;
- 服务层:完成大部分功能,如语法分析,sql优化,缓存查询,存储过程,函数的执行;
- 引擎层:真正负责数据的存储和读取,提供接口,不同的存储引擎有不同的功能;
- 存储层:存储数据,与引擎层交互。
11.存储引擎:
- 定义:决定数据CRUD如何实现,不同的表可以有不同的存储引擎,亦可以自己编写存储引擎。
- InnoDB和MyIsAm的区别:
。InnoDB(默认):支持事务,外键,行级锁,能解决幻读问题,聚集索引
。MyIsAm:大部分操作都是读和插入时适用,不支持事务,外键,行级锁,崩溃后无法恢复,采用非聚集索引,被MongDB代替。
13.索引:
- 定义:快速检索数据的数据结构,InnoDB使用优化后的B+树查找数据。
- 优缺点:提高查询速度,但同时创建和维护索引也降低了sql执行效率。
- 实现方式:
。Hash表:虽然快,但是不支持顺序和范围查询。
。Full-Text:对字符,text类型可以加这个全文索引,主要是用于模糊查询,原理是倒排索引,在辅助表中存储着词和文档位置的映射
。B树和B+树:
。B树所有节点既存放key也存放data,查询的时候查询到一半可能就结束了
。B+树只有叶子节点存放key和data,非叶子节点只存放key,并且叶子节点间存在引用链,所以B+树每次都是到叶子结点才能把数据查出来。范围查询不需要回溯。
。innodb优化b+树:叶子结点指针改为双向。
- 类型:
。主键索引和二级索引:主键索引是指key为主键;二级索引(唯一,普通,前缀)是指data为主键的索引。
。聚集索引和非聚集索引:聚集索引是指data存放的是数据,非聚集索引是指data存放的是数据的地址。
。覆盖索引和联合索引:覆盖索引是指索引包含需要查询的字段值,联合索引是指多个字段创建索引。
- 建议:选取频繁查询,排序的作为索引,尽量选择联合索引。不选取频繁更新,字段可为NULL的作为索引。
- 失效:
。能走覆盖索引的情况下使用了你你 SELECT * 进行查询;
。创建了组合索引,但查询条件未准守最左匹配原则;
。在索引列上进行计算、函数、类型转换等操作;
。以 % 开头的 LIKE 查询比如 like \'%abc\';
。索引字段上出现!=<> not in时会失效;in后面的数据如果超过30%就会走全表,不走索引。
。查询条件中使用 or,且 or 的前后条件中有一个列没有索引,涉及的索引都不会被使用到;
14.三大日志:
- mysql操作:mysql操作数据时会将那一数据也的内容都提取出来放到Buffer Pool,后续的操作都是先看Buffer Pool上有没有数据,没有再去磁盘中寻找。
- redo log:重做日志,物理上记录磁盘中对数据页的修改,先记录到 redo log buffer中,每隔1s,事务提交一次,redo log buffer内存占用超出一半时,刷盘到redo log日志中。
- binlog:二进制日志,逻辑上记录sql反向语句,先记录到binlog cache,事务提交后写入binlog中。
- undolog:回滚日志,逻辑上记录sql反向操作,先记录到undolog中,根据回滚指针形成undolog版本链,再进行实际的操作。先于数据库存储到磁盘上。
- redo log 保证持久性,使用 undo log 保证原子性,MVCC保证隔离性,一致性通过A,I,D实现的。
- redo log和binlog都保证数据库的一致性,但保护层面不同,记录内容,记录时间,执行效率都不同
15事务:
- ACID:
。原子性:操作要不都起作用,要不都不起作用;
。一致性:操作执行前后,数据从一个一致性状态转换到另一个一致性状态;
。隔离性:并发访问数据库时,事务之间不会互相干扰;
。持久性:事务提交后,对数据的改变是持久的。
- 隔离级别:读未提交,读已提交,可重复读,串行化。
。脏读:事务a读取到事务b修改的数据,但事务b回滚了,a读到了脏数据。
。不可重复读:事务a两次读同一数据的间隙,事务b修改了数据并提交了。
。幻读:事务a两次读同一数据的间隙,事务b新增了数据并提交。
。
- 并发事务的控制方式:锁(悲观)和MVCC(乐观)
- MVCC:为每个事务生成一个版本数据,保证事务的隔离性,利用隐藏字段,undolog,readview实现
。隐藏字段:每个表创建的时候都会有隐藏的DB_TRX_ID:最近事务的id,DB_ROLL_PTR:回滚指针,指向上一个版本数据,DB_ROW_ID:隐藏主键,没有主键时会自动生成。
。undolog:每次执行操作后都会形成一行记录之前版本的数据,包括DB_TRX_ID和DB_ROLL_PTR指向上上个版本的数据,最终形成一个undolog版本连记录在undolog日志中。
。readview:(不同隔离级别生成readview的时机不同)每次操作后会生成一个readview(四个字段分别记录当前活跃事务id集合,最小活跃事务id,与分配事务id,readview创建者的事务id)记录数据,DB_TRX_ID与这四个字段进行对比来判断具体应该将undolog版本链中的哪一条数据回滚。
16锁:
- 类别:表锁和行锁,这两种锁都包括共享锁和排它锁
- 表锁和行锁:
。表锁:资源消耗少,加锁快,锁冲突概率高,性能差。
。意向共享锁:加表锁的时候验证表内有无行锁,意向锁之间互相兼容,只有意向共享锁和表级共享
。意向排他锁:锁兼容,其余均互斥。
。行锁:资源消耗多,加锁慢,锁冲突概率低,性能好。
。记录锁:对记录加锁。
。间隙锁:对记录的间隙加锁,防止插入数据。
。临键锁:记录锁+间隙锁,能够解决幻读问题,mysqlc、查询数据加的都是临键锁,只有查询的字段只包含唯一索引且不是范围查询时,降级为记录锁。
- 共享锁和排它锁:
。共享锁:事务读取时获取共享锁,读读共享。
。排它锁:事务修改时获取排它锁,与任何都不共享。
17.为什么主键既不连续也不单调:
- 单调:每次插入数据后,Mysql会自动保存一个值作为下次插入的主键值,如果此时mysql重启了,保存的数据还没更新,就会导致主键还跟上次一致,现在采用了redolog日志解决了这个问题。
- 连续:插入数据时不会对主键设置事务锁,事务a插入数据主键+1,事务b插入数据主键又+1,若此时事务a回滚了,就会造成主键不连续。
18当前读和快照读:
- 当前读:读的是最新数据,读的时候加读锁,保证其他事务不会修改这条数据。(修改数据或for update时会发生当前读)
- 快照读:读的是当前记录的可见版本,多用于对一致性要求低,对性能要求高。
19.性能优化:
- 开启慢查询日志,或用explain查看sql执行计划,filesoft:排序的字段没加索引;temporary:排序或分组的字段来自其他表;
- 避免主键过长,避免使用UUID;
- 对于需要分组和排序的字段最好建立索引;
- 表中数据是否太大,是不是要分库分表;
- 写sql语句时做优化:
。select:尽量用select(字段),避免select(*),因为select(*)会多一步查询字段的操作,select(字段)效率稍高,能够明确表达业务需求。
。update:where条件要添加索引,否则会锁会从行锁升级为表锁。
。count:尽量使用count(*),避免count(字段)。
。insert:批量插入,开启事务,事务内部采用有序插入和一个insert插入多个value,这样可以避免sql多次重复解析,减少了日志量,避免事务的频繁创建。
。limit:分页查询时,如果偏移量太大,会使得性能很低。将where查询条件用order by分组后再limit;或者业务上商讨不做过多的分页。
20.sql执行计划:
- explain:在sql语句最前面加上explain关键字就可以显示这条语句的执行效率。
。
。type:
。key:用到的索引;key_len:用到的索引长度;
。rows:必须要执行查询的行数;
。extra:额外信息:
。Using filesort:在排序时字段没有建立索引。
。Using temporary:需要创建临时表(查询字段来自其他表),常见于 ORDER BY 和 GROUP BY。
。Using index:表明查询使用了覆盖索引,不用回表,查询效率非常高。
。Using index condition:表示查询优化器选择使用了索引条件下推这个特性。
。Using where:表明查询使用了 WHERE 子句进行条件过滤。一般在没有使用到索引的时候会出现。
。Using join buffer:连表查询的方式,表示当被驱动表的没有使用索引的时候
21.MVCC+临键锁防止幻读:
- 快照读:如果为快照读,那么读取的只是快照,不会出现幻读。
- 当前读:如果为当前读,那么在读取的时候为数据加上临键锁,防止插入,就不会造成幻读。
22.数据库崩溃恢复后:
- 已经commit的但还没来得及把数据写入磁盘的,执行前滚(redolog)。
- 还没commit的,执行回滚(undolog)。
23.count的几种方式:
24.最左前缀法则的生效条件:
- 根据创建联合索引的顺序,依次对你的where条件进行检测。遇到范围(<,>,between,like)当前算上之后就结束,如where a = 1 and b = 2 and c > 3 and d = 4,索引(a,b,c,d)中只能用到abc(a,b,d,c)全能用上。并且不管你联合索引的顺序,你写(a,b,c,d)就先看a在不在where后面并且不是范围,再看b;(b,a,c,d)就先看b在不在,再看a。
25.数据行和行溢出:
- 数据行:mysql底层有两种数据行,现在默认使用Compact,使得一个数据页能够保存更多的行数据;在存储一些大记录数据格式时,当数据本身超过768byte时就会将超出的数据放到另一个数据溢出页中。
- 行溢出:首先我们直到一个数据页是16kb,也就是16384byte,但是一个数据行最大可以保存65535byte 数据,当插入行大于数据页大小,或者大于页中剩余空间大小时就会发生行溢出,将溢出的数据写到溢出页中,设置一个偏移量指针将两者关联起来。
26.order by 和group by底层原理:
- order by:如果字段加了索引,就按照b+树进行排序;如果没加索引,如果数据行字段数比较少,就走单路排序(一次IO操作,一次性将所有需要排序的数据行都取出来在sort buffer中快速排序),反之走二路排序(两次IO操作,先取排序字段于sort buffer中,排序字段快速排好后,再根据排序字段取数据行),这两种排序中,如果sort buffer放不下数据了,都会创建临时文件触发归并排序。
- group by:只是在orde by的基础上做了分组,所以group by优化还是order by优化。
26.进阶:
- 主从复制:将主库中修改的数据自动同步到从库
- 原理:主库操作后将记录写入二进制文件,从库读取主库二进制日志写入自己的中继日志,从库读取并操作。
- 分库分表:
- 水平分库和水平分表:差不多,字段数不变,数据按照行分表存储。
- 垂直分库:一个库中的表拆分到几个库中。垂直分表:将表的字段分开,都包括主键就可以
- mycat:作为客户端和mysql间的中间件,客户端链接的时候将mysql换成mycqt即可。
。无论是垂直还是水平,都是要去修改配置文件schema.xml rule.xml service.xml
- 读写分离:
- 基于主从复制,主机写,从机读叫一主一从。两台主机写,两台从机读叫双主双从,同时两台主机间也互相复制,防止一台主机宕机后功能无法实现。都可以基于mycat实现。
以上是关于Mysql的主要内容,如果未能解决你的问题,请参考以下文章