复习数据库的时候延伸了很多问题,真有种递归学习的感觉。
数据库真的是一门深不可测的学科啊……
范式
范式本质是什么?
范式本质上就和汽车各种排放标准一样,是一种关系模式的设计准则。
人们规定各个级别的范式主要用于解决在数据库使用中产生的各种插入、删除、修改异常。
而这些数据异常的主要解决手段就是对关系模式进行分解,使之成为更高级别的范式。
然而,分解可能会造成新的问题,而其中最大的代价就是破坏原有关系模式的依赖等价甚至是数据等价。
1NF、2NF、3NF、BCNF
- 1NF:列不可再分
- 2NF:1NF且消除非主属性对候选键的部分依赖
- 3NF:2NF且消除非主属性对候选键的传递依赖
- BCNF:3NF且消除主属性对候选键的传递依赖
为什么没有一个范式消除主属性对候选键的部分依赖?
因为主属性不可能对候选键有部分依赖。
设主属性为X,候选键为XABC,若有X对候选键的部分AB有依赖;
则有AB=>X,那么ABC就能决定所有属性;
故XABC为超键,与其实候选键矛盾。
更高的范式一定更好吗?
更高的范式不一定就更好:
- 更高的范式不一定保持数据等价和依赖等价(如3NF分解为BCNF不一定能保持FD)
- 分解成更高的范式意味着表的增加,势必增加了查询时级联操作的次数,可能会降低查询效率
那具体什么时候用什么范式呢?
所有关系模式都能够分解成3NF;如果条件可以,甚至可以分解成BCNF。
什么时候使用什么范式是需要根据查询需求和实际需求具体分析的。有些时候根据实际用途,数据异常可能先天不存在或无意义,此时没有必要用更高级别的范式。
最高范式是什么?
解决函数依赖问题的最高范式是BCNF。
4NF和5NF分别用于解决多值依赖和联接依赖。
事实上还有6NF。
索引
数据库底层为什么使用B+树?
- 不使用二叉搜索树的原因:容易不平衡,复杂度退化。
- 不使用AVL、红黑树等平衡二叉树的原因:常数大,对磁盘IO不友好
- 不使用B树的原因:全表查询方便,查询时间更稳定(可能是好处?)
为什么B+树节点中数值少于一半进行合并?
也可以设置成其他阀值,但性能可能因此降低。
数据库底层其他实现的方法有哪些?
数据库底层实现和优劣比较:
B+树索引:主要考虑到磁盘IO效率和遍历效率。
哈希索引:等值查询快,不等值查询只能走全表查询。
空间索引:太难了,没学会。
数据库索引是怎么建立的,索引越多越好吗?
数据库的索引本质就是建B+树。如果一张表有多条索引,则建立多颗相互独立的B+树。
优点:查询速度增益
缺点:额外存储空间,更新数据同时要更新索引
因此,对频繁修改的属性不宜建立索引,对值域小的属性建立索引效果不大
什么样的查询用不到索引?
想想底层就行了:
- 联合索引非最左前缀用不到
不等于查询用不到
字符串非最左模糊搜索用不到
覆盖索引、回表、最左前缀原则、索引下推、聚集索引
- 聚集索引:对主键建B+树,叶子直接存记录,即包含全部数据
- 辅助索引:又称非聚集索引,非主键索引,叶子不包含全部数据,但包含书签(即主键id)
- 回表:使用辅助索引查询非索引数据,需要拿到书签后回聚集索引再次查表。主键或覆盖索引不需要回表
- 覆盖索引:查询字段值恰好在辅助索引中有(比如sum(辅助索引字段)),就不需要回表了
- 联合索引:多个关键字按一二三关键字建同一索引,需要最左前缀原则
- 最左前缀原则:联合索引只走最左侧连续的若干关键字做索引
- 索引下推:对于联合索引的多关键字查询,对于不符合最左前缀的部分依然做排除判断
非关系数据库有什么用?
选用NoSQL的主要原因有:表变更、字段灵活不固定、大量数据写入
ACID
事物ACID是什么,底层具体是怎么实现的?
A原子性:回滚,由undo日志实现
C一致性:由应用程序员保证
I隔离性:DBMS并发调度子系统控制,使用锁机制保证可串行化调度
D持久性:DBMS故障恢复子系统控制,redo日志和检查点机制
脏读、幻读和不可重复读
脏读:读到别人未提交的数据;
不可重复读:读两遍结果不一样;
幻读:做两次查询结果不一样