数据库
- 建表三范式
- 第一范式:每一列不可再拆分。(实体属性的原子性)
- 第二范式:必须有主键,并且每一列必须完全依赖于主键。
- 第三范式:不允许存在传递依赖,有类似需求时,使用外键等来满足。
- 索引
- 数据结构
- 常用数据结构:B+Tree、Hash
- B+Tree索引与Hash的区别
- hash索引等值查询比较快
- B+Tree能够提供比较稳定的查询速度,因为Hash存在冲突,假设使用拉链法来解决hash冲突的话,在数组上时O(1),但是进入链表,时间复杂度就变成了O(n)
- Hash索引不支持范围查询(或者说非等值查询)
- Hash索引无法支撑排序(不支持group by、order by等操作)
- Hash索引无法支持模糊查询
- Hash索引无法支持最左有限匹配原则
- B+Tree以及B-Tree的特点
- B-Tree
- 假设是n阶树
- 根节点的子树个数为2~n
- 除根节点和子树节点之外,其他节点的子树个数为n/2向上取整 ~ n
- 每个节点里面存储的元素内容为:p1,k1,p2,k2 … pn,元素有序,p为指向子树的指针。
- 在B-Tree中,每一个元素只出现一次
- 在B-Tree中,叶子节点不存储具体的数据内容,所有的数据都存储在非叶子节点上。
- B+Tree
- 假设是n阶树
- 根节点的子树个数为2~n
- 除根节点和子树节点之外,其他节点的子树个数为n/2向上取整 ~ n
- 每个节点中存储的元素内容为: p1, k1, p2, k2 … pn,kn,元素有序,p为指向子树的指针(p和k的个数相等)
- 父节点的内容会在其子节点中存储
- 所有具体的数据信息都存储在了叶子节点上
- 其他
- AVL:平衡二叉树,左右子树高度不超过一
- 完全二叉树:除最底层全满,最底层子节点全部靠左
- 二叉查找树:BST,中序遍历为从小到大有序
- 红黑树:一种自平衡二叉查找树
- 节点是红色或者黑色
- 根节点是黑色
- 叶子结点是黑色
- 每个红色节点的子节点必须是黑色
- 从每个节点到其下面的任何叶子节点拥有相同的黑色节点个数
- B-Tree
- 为什么选用B+Tree
- 查询效率比较高并且稳定,为O(logdn),以d为底n的对数。
- 比较契合操作系统的磁盘预读原理
- 每个节点存储的数据量比较大,所以逻辑上相邻的数据在物理上也很有可能相邻(与二叉树、红黑树做比较)
- 实际上对B+Tree还做了改进,每个叶子结点会有一个指向最相邻的下一个叶子结点的指针,这样的话,范围查询,可以直接顺着指针查下去。
- 因为以上两点,并且在B+Tree中每个节点存储的k要比B-Tree多,所以B+Tree更适合做索引。
- B+Tree索引与Hash的区别
- 使用注意点
- 最左匹配原则
- 每次只能用到一个索引
- %放最前面无法用到索引
- 多个范围查询的话,即使是联合索引,后面的范围查询字段也是用不到索引的
- 列参与运算用不到索引
- null不计入索引
- or的两个部分都有索引,并且是不同字段,如果MySQL判断扫全表需要更长时间的话,会同时用到这两个索引(这是唯一一个可能违反每次只用一个索引的地方)
- explain
- 字段
- select type
- type
- system
- const
- eq_ref
- ref
- ref_or_null
- range
- index
- all
- possible_keys
- key
- rows
- 字段
- 其他
- 索引创建的注意点
- 一张表不能有太多索引
- 会影响插入效率
- 创建索引的时候一般需要考虑索引的区分度
- 用distinct/总量,0.95以上基本没问题
- 在InnoDB中,推荐使用自增的int来做主键索引,这样一来可以提高效率,二来防止往中间页频繁插入,导致裂项,进而导致空间浪费。
- 但是如果没有主动设置主键索引时,会默认设置一个自增的int做主键索引
- 存在null时,是可以给这一列创建唯一索引的, 但是唯一索引会把两个null认为重复。
- 一张表不能有太多索引
- 索引创建的注意点
- 常用数据结构:B+Tree、Hash
- 存储引擎
- MyISAM和InnoDB的区别
- MyISAM的文件分三份:表定义、数据文件、索引文件,InnoDB只有数据文件和日志文件。
- 所以MyISAM的数据迁移特别方便。
- 还有,MyISAM删全表数据(delete)也特别方便,直接删掉数据文件和索引文件即可。但是InnoDB只能一行一行去删。不过,一旦delete存在where子句,那么两个一样。
- MyISAM支持表锁,而InnoDB支持到行锁。
- MyISAM不支持事务,InnoDB支持事务。如果强行在MyISAM上使用事务,那么在多条操作中间某一条失败时,前面的所有操作都不会被回滚。
- MyISAM会记录当前表的总条数,所以count(1)的时候,能够直接读取,但是InnoDB只能一次次去查。(猜测,如果存在where子句,两个还是一样的操作)
- 注意MyISAM和InnoDB的索引文件是有差别的。InnoDB的主键索引才会存储所有的数据。
- 对于auto_increment的列,InnoDB要求必须给单独建索引,但是MyISAM没这要求,让它与其他列建联合索引就行。
- MyISAM的文件分三份:表定义、数据文件、索引文件,InnoDB只有数据文件和日志文件。
- MyISAM和InnoDB的区别
- 事务隔离级别
- 未提交读
- 一个事务还没有提交,另一个事务就能读到此次修改的内容
- 会出现脏读、幻读、不可重复读的情况
- 读已提交
- 只要事务提交了数据,就能被另一个事务读到
- 会出现幻读、不可重复读的情况
- 幻读主要是指插入
- 不可重复读主要是指更新
- 可重复读
- 一个事务多次读的结果是一样的
- 理论上是无法解决幻读的问题的,但是InnoDB做了优化,可以解决幻读的情况
- 可重复读比读已提交,是多了对当前修改行的行锁
- InnoDB的优化,是在行锁之外,加了间隙锁,导致对当前行做修改时,第一不能再次修改当前行,第二不能在临近行新增数据
- 串行化读
- 读加读锁(表级锁),写加写锁
- 效率会大受影响
- 未提交读
- redo/undo/binlog
- redo日志
- 记录的是当前的操作(或者说是修改后的数据结果)
- 在事务开始之后就开始记录,不停地进行落盘
- 事务提交,数据落盘之后,redo日志就已经失效了
- 主要是为了保证持久性,部分为了保证原子性(因为undo动作也会在redo日志里面有记录)
- undo日志
- 记录的是被修改数据的原始内容
- 事务开始时进行记录
- 事务提交,数据落盘,如果没有其他事务还在使用当前undo日志里面的版本,则事务失效
- 主要是为了保证原子性
- binlog
- 数据库操作的日志记录
- 数据格式
- 低版本的支持二进制流和文本文件两种格式,高版本的只支持二进制流
- 记录方式
- row模式:记录每一行的变更。但是高版本的话,对于ddl,也是直接记录语句
- statement模式:记录语句
- mix模式:mysql自己决定按哪种形式记录
- 记录时间:事务提交时,所以一旦开启,有可能对事务速度造成影响
- 失效时间:定时失效,可以调整定时的时间
- redo日志
- 死锁
- 出现原因:
- 两个事务分别持有对方所需的资源,并且在等待对方释放所有的资源
- 示例:
- update table set a = A where a = B, update table set b = B where b = A ;
- update table set a = A where b = A, update table set b = B where a = B ;
- 检查方式:
- 检查业务日志
- 确定mysql事务隔离级别(因为RR里面的间隙锁也有可能导致死锁)
- 检查数据库日志
- 避免方法:
- 大事务拆小
- 最好能够一次性获取到所有的资源
- 加索引(能够避免尝试锁全表)
- 出现原因:
- 其他
- 语句
- join
- left join
- right join
- inner join
- full join
- inner join里面驱动表的选择:小表驱动大表
- outer join 里面,无匹配的行,其会填充null
- union、union all
- join
- 数据类型
- int(4)与int(11)的区别
- varchar与char的区别
- text与varchar的区别
- datetime和timestamp的区别
- timestamp会自动替换成utc时间进行存储,然后取出的时候替换成当前时区
- datetime存是什么样的,取的时候就是什么样的
- timestamp的时间区间是1970 ~ 2138年
- datetime的时间区间是0000 ~ 9999年
- 语句
- 数据结构