数据库 面试复习

前言

自从大三学完数据库后,这门课就没再看过。最近要找实习了,发现面试总避免不了要问数据库相关的问题,回过头去找课本,才发现书都已经被我扔了。。。只能根据网上的数据库面试题来复习了。

数据库事务的四个特征

ACID,分别对应Atomicity、Correspondence、Isolation、Durability

  • 原子性:事务的所有操作,要么全部完成,要么全部不完成,不能停滞在中间环节。事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务没有执行过一样。其保证了一致性,避免了事务执行当中(此时是不一致的)对外可见。
  • 一致性:在事务的开始前和执行后,数据库的完整性约束没有被破坏。指事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。
    • 实际上数据库的一致性是人为定义的,该由编写该事务的程序员来确保。
    • 完整性检查:
      • 单个关系的完整性约束:not null、unique、check(谓词)等
      • 参照完整性,对应的操作有delete cascade、update cascade等
      • 断言:表示数据库任何时候都应该满足的一个条件
  • 隔离性:多个事务并发执行时,一个事务的执行不应影响其他事务的执行。虽然同一时间可能有多个事务会并发执行,但是系统保证,对于任意一事务来说,都感觉不到别的事务在并发执行,而是在它之前或者之后执行。
    • 脏读:A修改了数据,还未提交,B读取了这个修改的数据,最后A提交失败,那B读到的就是脏数据。(read uncommitted隔离会看到)
    • 不可重复读:一个事务多次读取同一数据,结果却不一样。第一次与第二次读取之间,数据被别的事务修改了。强调的是数据被修改了(read committed隔离会看到)
    • 幻读:和可重复读类似,但是另一个事务对数据的影响不是修改,而是新增或者删除,读取的记录数量前后不一致(repeated read隔离会看到,innodb默认的隔离级别为repeated read
    • 常见的解决办法是串行执行,但是效率低。所以会有并发控制系统,来使事务并发执行,同时保证隔离性。(当我们将当前会话的隔离级别设置为serializable的时候,其他会话对该表的写操作将被挂起。可以看到,这是隔离级别中最严格的,但是这样做势必对性能造成影响。所以在实际的选用上,我们要根据当前具体的情况选用合适的。)
  • 持久性:事务提交后,对系统的影响是永久的,即使出现系统故障。

主键、超键、候选键、外键

  • 主键:元组中能够唯一区分出元组的属性值。其不可以为空,元组中也只能有一个主键。
  • 超键:在关系中能唯一标识元组的属性集称为关系模式的超键。一个属性可以作为一个超键,多个属性组合在一起也可以
  • 候选键:最小的超键,即没有冗余元素的超键。
  • 外键:在一个表中存在另一个表的主键,称此表的外键。

视图

  • 视图可以简化复杂查询。视图的定义是基于一个查询声明,这个查询声明可能关联了许多底层的表。
  • 视图可以限制特定用户的数据访问权。
  • 视图可以使用可计算的列。
  • 视图可以帮助我们兼容旧的系统。
  • 视图的增删改也会影响表,但视图并不总是能增删改的。视图的数据与表的数据一一对应时可以修改。对于视图的insert还应该注意,视图必须包含表中没有默认值的列

drop、delete和truncate的区别

drop直接删除表
delete删除数据,搭配where
truncate重构表,原始数据清空,表结构还在,id从1开始。

  • delete删除是每次删除一行,并且同时将删除的操作作为事务存在日志中,方便回滚。truncate则是直接一次性清空表,并不把删除操作记录入日志,不能恢复。并且在删除的过程中不会激活与表有关的删除触发器,执行速度快。(truncate时有级联的话会有外键约束的问题)
  • delete语句为DML语句,操作会放到rollback segment中,事务提交后才会生效。如果有相应的trigger,执行的时候会被触发。
  • truncate、drop是DDL,操作立即生效,原数据不放到rollback segment中,不能回滚。

索引

索引就是对数据库表中一列或者多列进行排序的结构,是帮助数据库高效检索的数据结构。

索引一般分为:聚集索引,非聚集索引,普通索引,唯一索引,主键索引,全文索引

  • 索引可以加快数据库检索速度,避免全表扫描
  • 索引需要占用额外的存储空间
  • 会使数据库更新数据能力降低,因为要维护索引表

聚集索引:聚集索引与表数据存储顺序一致,叶节点存储了真实表数据
非聚集索引:索引顺序与表数据存储顺序不一致,叶节点存储了索引字段值以及指向数据页数据行的逻辑指针。

B-Tree

  • 一颗m阶B树,非叶子结点最多有m个子节点,最少有m/2个
  • 关键字最多有m - 1个,最少有m / 2向上取整 - 1个
  • 根节点最少两个子节点,除非整个树只有一个节点
  • 所有叶子节点在同一层,且不带任何信息
  • k个关键字则有k + 1个孩子节点
  • 关键字从小到大排列,父节点关键字不出现在孩子节点中,且关键字的值比关键字指向的孩子节点中的值都要大

连接

a

id name
1 a1
2 a2

b

id name
1 b1
2 b2

笛卡尔乘积:select id.* , name.* from a,b;结果是

a.id a.name b.id b.name
1 a1 1 b1
2 a2 1 b1
1 a1 2 b2
2 a2 2 b2

左外连接

只保留出现在左外连接运算之前左边的关系中的元组

右外连接

只保留出现在右外连接运算之前右边的关系中的元组

全外连接

保留出现在两个关系中的元组

不保留未匹配元组的连接运算被成为内链接

范式

https://www.zhihu.com/question/24696366

  • 范式一:符合1NF的关系中的每个属性都不可再分
  • 范式二:2NF在1NF的基础之上,消除了非主属性对于码的部分函数依赖
  • 范式三:3NF在2NF的基础之上,消除了非主属性对于码的传递函数依赖
  • BCNF:在 3NF 的基础上消除主属性对于码的部分与传递函数依赖

SQL

  • 去重 select distinct xx form table_name;
  • 自然连接:只考虑连接在两个关系模式中都出现的属性上取值相同的元组对。
    • 多个属性相等时,自然连接需要多个属性值同时相等 select xx from r1 natural join r2
    • 为了避免多个不必要的属性值相等,可以使用select xx form (a natural join b) join c using(xx_id), join r using(A)
  • 更名运算 as:select name as xx_name from …; select xx form r as R where R.x = x;
  • SQL使用单引号来标识字符串,如果字符串中有单引号,则用两个单引号来表示,如'it''s me'
  • %匹配任意子串,_匹配任意字符where xx like ‘%abc%’; like ‘ab \% cd%’ escape ‘\’声明转义字符为\;
  • order by用来对查询结果排序,默认为升序 select xx form xx where xx order by name desc, salary asc;可以同时对多个属性排序;
  • between等同于 where salary between a and 3; where salary <= 3 and salary >= 1;
  • where (a1, a2) <= (b1, b2)在a1 <= a2同时b1 <= b2时为真。
  • union、intersect、except为并、交、差运算
    • (select a from a) union (select b from b),自动去重;union all可以保留所有重复
    • (select a from a) intersect (select b from b),自动去重;intersect all可以保留所有重复,但数目为重复的最小个数。比如一个表里有2个,另一个表里有6个,则最后结果为2个。
    • (select a from a) except (select b from b),执行前会先自动去重。前表减后表,两表相同的元组;except all可以保留所有重复。如果a有2个,b有6个,则结果不显示;若a有6个,b有2个,则结果有4个。
  • true and unknown = unknown; false and unknown = false; unknown and unknown = unknown
  • true or unknown = true; false or unknown = unknown; unknown or unknown = unknown
  • not unknown = unknown
  • where name is null;不能说where name = null这样返回unknown;或者where null = null;返回unknown
  • 聚集函数avg、min、max、count、sum。avg和sum必须用在数字型上
  • group by用来分组,在group by子句中的所有属性上取值相同的元组将被分在一个组中。select中的属性不在聚集函数中就要在group by中 select name, id ,avg(salary) from table group by name;这是错误的
  • having用于对分组进行限定。与select相似,任何出现在having子句中,但没有被聚集的属性必须出现在group by子句中,否则错误。
  • 嵌套查询关键字 in
  • some,all用于集合比较
  • exists用于空关系测试,exists结构在作为参数的子查询非空时返回true值
  • unique用于重复性测试,子查询中没有重复元组返回true
  • from子查询,from子查询不需要having语句,因为可以移到外层查询的where中。select a from (select b, avg(c) from R group by b as sub_from(b, avg_c)) where avg_c > xxx 注意要as更名from子查询结果
  • with子句,用于提供定义临时关系的方法 with max_budget(value) as (select max(a) from B) select budget form max_budget where max_budget.value = xxx

存储过程

存储过程是数据库预编译的一些sql语句,它的优缺点有:

  • 因为预编译了,所以执行起来更快,不需要再去编译,直接执行即可
  • 减少网络传输,因为一个存储过程可以代替大量的sql语句,所以节省许多网络传输。但是这点意义不大
  • 可以进行权限管理

缺点

  • 更改起来比较麻烦
  • 开发调试复杂
  • 没法运用缓存

你可能感兴趣的:(数据库 面试复习)