校招面试准备——数据库

数据库范式:

第一范式:保证每列(每个字段)都是不可分解的

第二范式:保证表中的每一个非主属性都和主键的每一列(针对联合主键)相关(一个表只能说明一种信息)

  • 候选码中的每一个属性都是主属性,其他的是非主属性
  • 反例: 学号,姓名,年龄,课程名称,课程ID,成绩,学分
  • 这个表说明了两个信息:学生基本信息和学生课程信息;主键应该是学号和课程ID(这样才能映射到唯一一条数据),然而学生姓名和学号和课程ID没关系,课程名称也和学号没有关系。
  • 问题:数据冗余(同一个课的课程名和课程ID被存了好多次),删除异常(当把学生信息都删了以后,课程信息也没了)
  • 更新异常(当更新一门课程的名称时,需要更新很多行数据),插入异常(当一个学生没选课的时候,没有课程ID,主键不完整,就没法进入数据库)

第三范式:保证表中的每一列都和主键直接相关,而不是间接相关(非主键之间没有依赖)

  • 反例:学号,姓名,年龄,班级,班级所在教室
  • 主键是学号,然而班级所在教室和学号没有直接的关系,它和主键的关系是 学号->班级->班级所在教室
  • 问题:数据冗余(班级所在教室被存了好几次),更新异常,删除异常,没有插入异常了(因为有学号就能插入)

BCNF: 主属性对主键不存在部分依赖

  • 反例:仓库号,存储物品号,管理员号,物品数量 (一个管理员只在一个仓库工作,一个仓库只能有一个管理员)
  • 仓库号和存储物品号能决定物品数量,而存储物品和管理员号也能决定物品数量,也就是说这两组都是候选码,仓库号,存储物品号和管理员号都是主属性
  • 但是当以仓库号和存储物品号为主键是,主属性管理员号部分依赖主键(因为它只依赖仓库号),就不符合BCNF
  • 问题:数据冗余,删除异常(一个仓库不放东西,就丢失了管理员信息),插入异常(当一个仓库分配了管理员但是没有存物品,就无法存储管理员信息),更新异常(当给仓库换管理员时,要更新好多条数据)

 

事务的四大特性:

原子性:事务中的一系列操作,要么都做,要么都不做

一致性:事务结束后,数据库的一致性没有被破坏;比如银行转账,转账之后,银行的总钱数不变

隔离性:多个事务对同一个表进行操作时,互不干扰

持久性:一个事务一旦被提交,那么就一定会对数据库起到永久性的改变,即使数据库系统遇到故障也不会丢失提交事务的操作

 

事务的隔离级别,会遇到什么并发问题

刚刚提到事物具有隔离性,这个隔离性也是分级别的;首先看事务并发会带来哪些潜在问题:

  • 脏读:读到了别的事务还未提交的数据;别的事务还没提交呢,说明它有可能回滚,那另一个事务读到的数据就是错误的
  • 不可重复读:一个事务对同一条数据读好多次,但它某一次读到的数据和之后再读到的数据不一样了,因为在这个间隔中有其他的事务修改了数据
  • 幻读:一个事务对某一块数据读取或其他操作,都操作完了以后 发现怎么还有数据没操作呢?因为在它读的时候,有其他的事务加进来一些数据;或者说两次查询得到的数据量不同

那不同的隔离级别能避免这些问题吗:

  • 读未提交:很明显这个名字符合脏读中的条件,所以他不能避免脏读,其他两种情况就更不能避免了
  • 不可重复读:见名知意,这个隔离级别保证了事务在未提交时,别的事务读不到它的修改;但是不能保证在一个事务进行读操作时,别的事务不会对数据进行修改;还是会不可重复读以及幻读的
  • 可重复读:这个隔离级别保证了在进行读操作时,别的事务不会修改数据,但是别的事务可以插入数据;也就是说还是会幻读的
  • 串行化:排着队一个一个来,那就不会有什么并行问题

MySQL默认的隔离级别是“可重复读”;

 

MySQL常用存储引擎

存储引擎可以决定数据在内存中以何种格式存储,怎么查找(比如利用索引),以及有些存储引擎支持事务,还决定怎么处理并发。面试常见的两种引擎是InnoDB和MyISAM。

 

InnoDB

  • 支持事务,因此就可以提交、回滚
  • 支持外键
  • 进行存储时,InnodDB会将数据表分为两个文件存储(.frm和idb)且它有共享表空间存储和独占表空间存储两种方式;

 

MyISAM

  • 不支持事务和索引
  • 存储式分三个文件,frm-->存储表定义;myd-->存储数据;myi-->存储索引

  • 锁粒度:只支持表级锁
  • 索引:它首先不是聚簇索引,数据域放的是数据的物理地址,也不强求有主索引(辅助索引自己知道地址,不像InnoDB那样样需要去主索引里找),其次它还支持全文索引、压缩等
  • 行数:有一个变量表示了行数,因此查找总行数的时候直接返回

 

索引

如果没有索引,数据库中的数据就会想excle一样被存在磁盘里,这样的缺点是在查询的时候需要进行全表搜索;索引的作用就是利用数据结构和算法,能够更快得进行查询。索引的缺点是:1. 增加了存储空间   2. 在修改数据库(插入删除)时也要花费时间去修改索引。

 

索引的优点

  • 加快检索速度
  • 加速表与表之间的链接,对实现数据参考完整性也很有意义(给主键和外键加索引)
  • 在使用分组和排序子句时,可以减少时间(给分组用的属性和排序用的属性加索引)

 

哪些属性适合加索引,哪些不适合

适合的

  • 需要经常搜索的属性(直接搜索或者范围搜索)
  • 主键
  • 经常需要连接的列上,比如外键
  • 经常需要排序的属性
  • 经常用在where语句中的属性
  • 经常组合的属性

不适合的

  • 不经常用的(不经常搜索,连接,排序,组合)
  • 定义为text image bit类型的
  • 取值种类很少的(比如性别,一般也就两种,用索引的话,区分度太低)

 

索引类型(数据结构方面)

Hash: 只有heap和memory引擎才有Hash索引;优点是可以一次定位,缺点是不适用于范围查找

B+树索引(innodb默认用这个)

 

为什么说B+比B树更适合实际应用中操作系统的文件索引和数据库索引? https://www.cnblogs.com/wenxiaofei/p/9853682.html

1.B+的磁盘读写代价更低

B+的内部结点并没有指向关键字具体信息的指针。因此其内部结点相对B树更小。如果把所有同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的需要查找的关键字也就越多。相对来说IO读写次数也就降低了。

2.B+tree的查询效率更加稳定

由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。

 

为什么不用红黑树和AVL

https://blog.csdn.net/qq_21993785/article/details/80580679

https://blog.csdn.net/qq_21993785/article/details/80576642

 

索引分类,索引失效条件

索引类型概念
普通索引最基本的索引,没有任何限制
唯一索引与"普通索引"类似,不同的就是:索引列的值必须唯一,但允许有空值。
主键索引它是一种特殊的唯一索引,不允许有空值。
全文索引针对较大的数据,生成全文索引很耗时好空间。
组合索引为了更多的提高mysql效率可建立组合索引,遵循”最左前缀“原则

 

组合索引的最左匹配原则:

在最左匹配原则中,有如下说明:

  1. 最左前缀匹配原则,非常重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。
  2. =和in可以乱序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式

 

数据库的锁(按存储引擎来说)https://zhuanlan.zhihu.com/p/29150809

MyISAM只有表锁

在select之前,会自动给表加读锁;在执行更新操作(UPDATE,DELETE,INSERT)前会给表加写锁;在自动加锁前,它会一次性获得SQL语句所需要的全部锁,所以它不会出现死锁。

  • 表共享读锁 (Table Read Lock):不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求;
  • 表独占写锁 (Table Write Lock):会阻塞其他用户对同一表的读和写操作;

MyISAM 表的读操作与写操作之间,以及写操作之间是串行的。当一个线程获得对一个表的写锁后, 只有持有锁的线程可以对表进行更新操作。 其他线程的读、 写操作都会等待,直到锁被释放为止。

默认情况下,写锁比读锁具有更高的优先级:当一个锁释放时,这个锁会优先给写锁队列中等候的获取锁请求,然后再给读锁队列中等候的获取锁请求。这也正是 MyISAM 表不太适合于有大量更新操作和查询操作应用的原因,因为,大量的更新操作会造成查询操作很难获得读锁,从而可能永远阻塞。同时,一些需要长时间运行的查询操作,也会使写线程“饿死” ,应用中应尽量避免出现长时间运行的查询操作(在可能的情况下可以通过使用中间表等措施对SQL语句做一定的“分解” ,使每一步查询都能在较短时间完成,从而减少锁冲突。

 

InnoDB

InnoDB 实现了以下两种类型的行锁

  • 共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
  • 排他锁(X):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。

为了允许行锁和表锁共存,实现多粒度锁机制,InnoDB 还有两种内部使用的意向锁(Intention Locks),这两种意向锁都是表锁

  • 意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的 IS 锁。
  • 意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的 IX 锁。

对于UPDATE DELETE INSERT语句,会自动加排它锁;对于select语句,不会自动加任何锁

InnoDB 行锁实现方式:

  • InnoDB 行锁是通过给索引上的索引项加锁来实现的,这一点 MySQL 与 Oracle 不同,后者是通过在数据块中对相应数据行加锁来实现的。InnoDB 这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB 才使用行级锁,否则,InnoDB 将使用表锁!
  • 不论是使用主键索引、唯一索引或普通索引,InnoDB 都会使用行锁来对数据加锁。
  • 只有执行计划真正使用了索引,才能使用行锁:即便在条件中使用了索引字段,但是否使用索引来检索数据是由 MySQL 通过判断不同执行计划的代价来决定的,如果 MySQL 认为全表扫描效率更高,比如对一些很小的表,它就不会使用索引,这种情况下 InnoDB 将使用表锁,而不是行锁。
  • 由于 MySQL 的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然多个session是访问不同行的记录, 但是如果是使用相同的索引键, 是会出现锁冲突的(后使用这些索引的session需要等待先使用索引的session释放锁后,才能获取锁)。 

 

查询优化 Loading...

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值