MySQL基础(面试)

一、数据库的三大范式

第一范式: 每个列不可以再拆分;
第二范式: 在第一范式的基础上,非主键列完全依赖于主键,而不是主键的一部分(主要针对于联合主键而言);
第三范式: 在第二范式的基础上,非主键列完全只依赖于主键,不依赖于其他非主键(也就是消除了传递依赖关系)。
如:C 实际上是直接依赖于B,传递依赖于A 的,也就是说,通过A,可以唯一确定B,然后通过B来确定的C,这样就叫做不满足第三范式。

参考文章

二、数据类型

  1. 整数类型: 包括TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,分别是1、2、3、4、8 个字节。注意:如INT(11),这个11 只是显示长度,没有任何意义。
  2. 实数类型: 包括FLOAT、DOUBLE、DECIMAL。DECIMAL 的存储比BIGINT 还要大,能存储精确的小数,但效率会稍微差些,可以理解成用字符串进行处理。
  3. 字符串类型: 包括CHAR、VARCHAR、TEXT、BLOB。VARCHAR 存储可变长字符串,会使用额外的1或2个字节存储字符串长度。VARCHAR 和CHAR 存储的内容超出长度时都会被截断。CHAR 适合存储很短的字符串,或者所有的值都接近同一个长度。
  4. 日期和时间类型: timestamp 的效率会高于datetime。
  5. 枚举类型(ENUM): 把不重复的数据存储为一个预定义的集合

三、存储引擎

1. 常用的存储引擎

InnoDB 引擎: 提供数据库的ACID 事务支持,且还提供行级锁和外键的约束。
MyISAM 引擎: 不提供事务支持,也不支持行级锁和外键。
MEMORY 引擎: 所有的数据存储在内存中,数据处理速度快,但安全性不高。

四、索引

1. 索引的优缺点

优点:

  1. 可以加快数据的检索速度;
  2. 通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。

缺点:

  1. 创建索引和维护索引都需要耗费时间,当对表中的数据进行增、删、改时,索引也需要动态的维护,会降低增、删、改的执行效率。
  2. 索引需要占用物理空间。

2. 索引的创建原则

  1. 最左匹配原则,这是组合索引非常重要的原则,MySQL会一直向右匹配知道遇到范围查询(>、<、between、like)就停止匹配;(=和in可以乱序,查询优化器会帮你优化成索引可以识别的形式)
  2. 较为频繁作为查询条件的字段才去创建索引;
  3. 更新频繁的字段不适合创建索引;
  4. 若是不能有效区分数据的列不适合做索引列(如性别:男、女、未知)。
  5. 尽量在以前的索引上扩展索引,不要新建索引;
  6. 对于查询中很少涉及到的列,重复值比较多的列不要建立索引;
  7. 定义有外键的数据列一定要建索引;
  8. 对于定义为text、image和bit 的数据类型列不要建立索引。

3. 索引的创建方式

  1. 新建表的时候创建;
  2. ALTER TABLE table_name ADD INDEX index_name(colum_name);
  3. CREATE INDEX index_name ON table_name(colum_name);

4. 创建索引需要注意事项

  1. 非空字段:应该指定列为NOT NULL,除非你想存储NULL。mysql中,含有空值的列很难进行查询优化。
  2. 取值离散大的字段:用COUNT() 来统计,返回值越大说明离散程度高;
  3. 索引字段越小越好:数据库的数据存储以页为单位,一页存储的数据越多一次IO 操作获取的数据越大,效率越高。

5. B树 和B+ 树的区别

  1. B树可以将键和值放在内部节点和叶子节点;B+ 树中,内部节点是键,没有值,叶子节点同时存放键和值。
  2. B+ 树的叶子节点有一条链相连,B 树的叶子节点各自独立。
    B 树 && B+ 树

6. 数据库为什么使用B+ 树而不是B 树

  1. B 树只适合随机检索,而B+ 树支持随机检索和顺序检索;
  2. B+ 树的查询效率更加稳定;
  3. B 树在提高了磁盘IO 性能的同时并没有解决元素遍历的效率低下的问题;
  4. B+ 树增删文件(节点)时,效率更高。

7. 聚簇索引与非聚簇索引

  1. 聚簇索引:将数据存储与索引放在一块,找到索引也找到了数据;
  2. 非聚簇索引:将数据存储与索引分隔开,索引结构的叶子节点指向了数据的对应行。

8. 非聚簇索引一定会回表查询吗

不一定,这涉及到查询语句所要求的字段是否全部命中了索引,如果全部命中了索引,那就不再进行回表查询。

9. 为什么需要注意联合索引中的顺序

联合索引:MySQL 可以使用多个字段同时建立一个索引,叫做联合索引。在联合索引中如果想要命中索引则需要按照建立索引的字段顺序挨个使用,否则无法命中索引。

五、锁


共享锁 & 排他锁

数据库的增、删、改操作默认都会加排他锁,而查询不会加任何锁。

排他锁: 对某一资源进行加排它锁,自身可以进行增、删、改、查,其他人无法进行任何操作。
eg:select * from student where id = 1 for update;

MySQL 中,行级锁并非直接锁记录,而是锁索引。如果操作的是主键索引,则MySQL 就会锁定这条主键索引;如果操作的是非主键索引,MySQL 会先锁住非主键索引再锁定相关的主键索引。所以如示例的例子如果id 没有加索引则会变为加表锁。

共享锁: 多个事务对同一数据可以共享一把锁,都能访问数据,但是只能读不能修改。
eg:select * from student where id = 1 lock in share mode;

死锁发生:

T1:begin tran
     select * from table lock in share mode
     update table set column1='hello'

T2:begin tran
     select * from table lock in share mode
     update table set column1='world'

当 T1 准备执行 update 时,根据锁机制,T1 的共享锁需要升级到排他锁才能执行接下来的 update。在升级排他锁前,必须等 table 上的其它共享锁(T2)释放,同理,T2 也在等 T1 的共享锁释放。于是死锁产生了。


乐观锁 & 悲观锁

说明:乐观锁 & 悲观锁 是针对查询(select)语句。 比如例子:减库存出现负数。

排它锁(for update)是悲观锁的一种实现方式,这里不再说明。
乐观锁需要靠表设计和代码来实现:

  1. 一般在该商品表中添加version 版本字段或者timestamp 时间戳字段
  2. 查询后执行的更新操作变成如下(多了版本号条件):
    update table set name = “zhangsan” where id = 1 and version = 22;
    如果更新操作失败,表示更新操作之前程序已经更新过,可以尝试重试来保证更新成功。为了尽可能更新失败,可以合理调整重试次数(阿里巴巴手册规定重试次数不低于三次)。

查询情况较多的情况下建议使用乐观锁,如果写入居多且对吞吐要求不高可使用悲观锁。

“加锁的查询操作”:加过排他锁的数据行在其他事务中是不能修改的,也不能通过for update或lock in share mode的加锁方式查询,但可以直接通过select …from…查询数据,因为普通查询没有任何锁机制。

六、存储过程

存储过程是预编译SQL 语句,只需要创建一次,以后该程序中就可以调用多次。

优点:

  1. 存储过程是预编译的,执行效率高;
  2. 存储过程的代码直接放在数据库当中,通过存储过程名直接调用,减少网络通讯;
  3. 存储过程可以重复执行,减少数据库开发人员的工作量;
  4. 安全性高,执行存储过程需要有一定权限的用户

缺点:

  1. 如果程序中有大量的存储过程,在项目交付的时候随着用户需求的增加会导致数据结构发生变化,后期维护系统会比较困难。
  2. 开发调试复杂,存储过程的调试要比一般程序困难;
  3. 不支持集群,数据库服务器无法水平扩展。

随着众多ORM 的出现,存储过程很多优势已经不明显了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值