【数据库面试题】常见数据库基础面试题
关系型与非关系型区别?
NoSQL
:键值对, 反范式,需要添加字段直接增加即可。查询不需要经过 SQL 解析(所以性能还是很高的)。同样的水平扩展的能力也很好。CAP(一致性,可用性,分区行之间做选择)
SQL
: 关系型类以表格形式存在,遵循范式,体现表与表,之间的关系。查询语句需要经过 SQL 解析。 事务支持较好。
什么是 CAP?
CAP 原则又称 CAP 定理,指的是在一个分布式系统中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性)这三个基本需求,最多只能同时满足其中的 2 个。
① 一致性:对于客户端的每次读操作,要么读到的是最新的数据,要么读取失败。换句话说,一致性是站在分布式系统的角度,对访问本系统的客户端的一种承诺:要么我给您返回一个错误,要么我给你返回绝对一致的最新数据,不难看出,其强调的是数据正确。
② 可用性:任何客户端的请求都能得到响应数据,不会出现响应错误。换句话说,可用性是站在分布式系统的角度,对访问本系统的客户的另一种承诺:我一定会给您返回数据,不会给你返回错误,但不保证数据最新,强调的是不出错。
③ 分区容忍性:由于分布式系统通过网络进行通信,网络是不可靠的。当任意数量的消息丢失或延迟到达时,系统仍会继续提供服务,不会挂掉。换句话说,分区容忍性是站在分布式系统的角度,对访问本系统的客户端的再一种承诺:我会一直运行,不管我的内部出现何种数据同步问题,强调的是不挂掉。
事务四大特性 ACID
A:Atomicity. 包含事务的操作,要么全做,要么全不做。
C:Consistency。一致性性. 事务执行前后的数据是一致的。
I:Isolation.隔离性,事务之间不会相互影响。 解决脏读,不可重复读,幻读。
D:Durability. 持久性.事务一旦提交,发生的改变是永久的。
事务:事务是一组操作,组成这组操作的各个单元,要不全都成功要不全都失败,这个特性就是事务
脏读:A 读了 B 事务尚未提交的数据,但是 B 没有提交,然后 B 回滚了。
不可重复读:A 多次读取某个数据过程中,被 B 更改并提交,导致 A 事务前后的数据不一致。
幻读:前后多次读取,数据总量不一致。A 批量更新数据,B 插入一条数据,正好符合 A 更新条件。但是 A 没更新到。
不可重复读(update)和幻读(insert, delete)到底有什么区别呢?
- 不可重复读是读取了其他事务更改的数据,针对 update 操作
- 幻读是读取了其他事务新增的数据,针对 insert 和 delete 操作
SQL 的隔离级别
SQL 的隔离级别有四种,它们分别是读未提交(read uncommitted)、读已提交(read committed)、可重复读(repetable read) 和 串行化(serializable)。下面分别来解释一下。
读未提交:读未提交指的是 一个事务在提交之前,它所做的修改就能够被其他事务所看到。
读已提交:读已提交指的是 一个事务在提交之后,它所做的变更才能够让其他事务看到。
可重复读:可重复读指的是 一个事务在执行的过程中,看到的数据是和启动时看到的数据是一致的。未提交的变更对其他事务不可见。
串行化:顾名思义是对于同一行记录,写会加写锁,读会加读锁。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。
mysql
的隔离级别为: 可重复读: 不允许脏读,不允许不可重复读,允许幻读。
Mongodb
隔离级别为:读已提交
存储引擎
InnoDB 支持事务, 支持外键, 行级锁,有两个文件(.frm,.ibd B+树,数据和主键索引在一块存叶子节点),有安全日志,有大量增删用它。
MyIsAm: 不支持事务,不支持外键,表锁, 有三个文件(.frm,.MYD,MYI),在查询性能高。 表容易坏
索引的类型: 一句话:聚集索引与非聚集索引的区别是:叶节点是否存放一整行记录
InnoDB: 主键是聚簇索引, 非主键是非聚促索引, 文件存在主键索引的叶子节点上。 因此 innodb 必须有索引。
MyIsAm: 非聚簇索引,索引保存的是数据文件的指针。
Innodb:不保存数据的行数。 MyIsAm:保存了数据的行数,因此 select count()是很快的。 count() 和 count(1)的效果是一致的。
基础架构
1.客户端 2.服务层(解析 SQL,优化 SQL,查询缓存,执行 SQL) 3.数据层
Mysql 中索引
- 普通索引 可有 null,可重复
- 主键索引 不可以有 null,不可以重复
- 唯一索引 不可以重复,但是可以有 null
- 组合索引 多字段作为索引
- fulltext 哈希索引,Btree,Rtree。
char 与 varchar 的区别
char(M)是定长, 字段永远都是这么长,后边补空格。
vachar(M)是非定长, 实际长度+1 的长度。
这个 M 是字符并非字节。 255 个字符.如果该列是 utf8 编码,则该列所占用的字节数=字符数*3.
- char 是固定长度的,如果长度不足,采用右补空格的方式来填充字符串至规定的长度,而 varchar 不是,有多长存多长。
- 对于检索效率来说,char 的效率要高于 varchar 的
可以看出,select 后的值:char 类型的字段,左右空格全部被去除! 而 varchar 类型的字段,左边空格去除,右边空格保留!
left join,right join,inner join
LEFT JOIN:返回左表中所有记录,以及右表中满足条件的集合。 可能有多个。结果>= A 的数量。
LEFT JOIN 关键字会从左表 (table_name1) 那里返回所有的行,即使在右表 (table_name2) 中没有匹配的行。
inner:两个表的交集。
Inner Join 和 Join 是相同的。 对两个表求交集。
FULL OUTER JOIN 关键字只要左表(table1)和右表(table2)其中一个表中存在匹配,则返回行.
交叉查询。SELECT \* FROM t_Class a ,t_Student b WHERE a.classid=b.classid
//这种写法是 INNER JOIN 的简写模式。
Crose Join
。 笛卡尔积的结果中找数据。
举出几个 你做过的分库分表的实例。
先垂直 后 水平分表
垂直分表: 按业务(商分/拉新)
水平分表: 将大表 hash 分到不同表中。 1. 使用 ID Range 2. Hash 3.地理 4.日期 date;
你通常是如何优化 mysql 的查询?
- 查询之前使用 explain
- 查看使用的索引,加索引。
- 能少字段就少选。
- 逻辑上是不是存在锁表
快手面试题
-
数据库 MySQL
-
mysql 的索引有哪几种? 聚集索引与非聚集索引的区别? 什么是全文索引?B+ Tree 索引和 Hash 索引区别?
普通,唯一,主键,组合索引,全文索引。 叶子结点是否保存所有的数据。 全文索引: 对 text 类型分词搜索。 -
B+树索引和哈希索引的明显区别是:
- 如果是等值查询,那么哈希索引明显有绝对优势,因为只需要经过一次算法即可找到相应的键值;当然了,这个前提是,键值都是唯一的。如果键值不是唯一的,就需要先找到该键所在位置,然后再根据链表往后扫描,直到找到相应的数据;
- 从示意图中也能看到,如果是范围查询检索,这时候哈希索引就毫无用武之地了,因为原先是有序的键值,经过哈希算法后,有可能变成不连续的了,就没办法再利用索引完成范围查询检索;
- 同理,哈希索引也没办法利用索引完成排序,以及 like ‘xxx%’ 这样的部分模糊查询(这种部分模糊查询,其实本质上也是范围查询);
- 哈希索引也不支持多列联合索引的最左匹配规则;
- B+树索引的关键字检索效率比较平均,不像 B 树那样波动幅度大,在有大量重复键值情况下,哈希索引的效率也是极低的,因为存在所谓的哈希碰撞问题。
-
a b c 3 个字段的联合索引什么用到哪个?最左原则
-
什么是覆盖索引,覆盖索引可以的优势是什么?避免回表
-
你是怎么理解索引的,mysql 索引的数据结构?为什么选则 b+树?
-
mysql 的存储引擎有哪些? 区别?
myisam, innoDB. 事务支持,是否支持外键,存储结构,锁的力度,文件存储类别。 -
数据库隔离级别有哪几个,mysql 的默认的是哪个?每个隔离级别解决的是什么问题? 如何解决幻读?幻读与不可重复读的区别?
脏读 不可重复读 幻读
读未提交
读已提交
可重复读
串行
可重复读: 默认级别,解决脏读、不可重复读的问题,存在幻读的问题。使用 MMVC 机制 实现可重复读 -
mvcc 的做用,如何实现的?
MVCC 最大的优势:读不加锁,读写不冲突。在读多写少的 OLTP 应用中,读写不冲突是非常重要的,极大的增加了系统的并发性能
MVCC 是通过在每行记录后面保存两个隐藏的列来实现的。这两个列,一个保存了行的创建时间,一个保存行的过期时间(或删除时间)。当然存储的并不是实际的时间值,而是系统版本号(system version number)。每开始一个新的事务,系统版本号都会自动递增。事务开始时刻的系统版本号会作为事务的版本号,用来和查询到的每行记录的版本号进行比较。 -
mysql 的锁有哪些?行锁、表锁、悲观锁、乐观锁、间隙锁,悲观锁和乐观锁的区别?
悲观锁,每次去拿数据都认为别人会修改数据,所以每次都加锁,
乐观锁,每次拿数据时认为不会修改数据,所以不会上锁,但提交时会判断在此期间是否有其它人修改了数据,通常用 version 实现
间隙锁,解决幻读的问题, (给某段数据加锁)
BEGIN;
/_ 查询 id 在 7 - 11 范围的数据并加记录锁 _/
SELECT _ FROM `test` WHERE `id` BETWEEN 5 AND 7 FOR UPDATE;
/_ 延迟 30 秒执行,防止锁释放 \*/
SELECT SLEEP(30);
/_ 提交事务 1,释放事务 1 的锁 _/
COMMIT;
-
手写一个死锁的代码?
-
mysql 的主从数据同步的方式,如何保证数据的一致性?
通过 binlog 的方式。 -
mysql 的事物特性有几个?ACID ,隔离级别有哪几个?
-
undo 、redo、 binlog 日志都是干什么的,有什么作用?
redo 和 undo 日志
- redo 日志:数据修改之后记录的值,可以用来恢复未写入 datafile 的已成功事务更新的数据
- undo 日志:记录某数据被修改前的值,可以用来在事务失败时进行 rollback;
- binlog: 写入成功后,会讲操作步骤写入文件,作为日志记录。
-
如何进行分库分表,常用中间件?mycat 、sharding-jdbc 等
-
你们创建的那么多索引,到底有没有生效,或者说你们的 SQL 语句有没有使用索引查询你们有统计过吗?如何看索引是否生效?mysql 的执行计划
那什么情况下会发生明明创建了索引,但是执行的时候并没有通过索引呢?查询优化器放弃使用索引,sql 中有放弃索引的语句,比如 like %""%等 -
mysql 主键设计原则? 数字,有序 ,为什么要是数字和有序,基于什么考虑的?
使用非自增的主键,为什么要比自增主健耗时,耗时在哪里?要将新的索引插入到已有索引位置,需要进行数据的移动,频繁的数据移动增加磁盘 io 次数,主要耗时在这里
https://blog.csdn.net/itworld123/article/details/103004407
https://juejin.im/post/5e9d73ef51882573b86fa491 -
如果并发情况下有两条一样的数据插入数据库如何处理? 用数据库的联合主键
-
select \* from table where a = 10 and b>20
如何建立索引?建立 a,b 的联合索引 ,https://zhuanlan.zhihu.com/p/48981451 所有关于建立索引的方式 (原则是谁先缩小返回的多,谁在前) -
如何做 sql 优化?
加索引、去掉无用字段的返回,避免全面扫码,使用覆盖索引 -
了解 mysql 的回表吗?如何避免回表?
查询时都是查询的主键的索引,然后在根据主键索引查询,这样就操作就是回表,在要查询的数据上建立了索引,这样就不需要进行回表查询了,
例如:select name from table where name = zhangsan
,在 name 上建立索引 -
MySQL 千万级数据量表 update 操作如何处理?
使用脚本更新,update and sleep ,选择在低峰期更新 -
MySQL 中 where 1=1 会影响性能么,为什么?https://blog.csdn.net/shouchenchuan5253/article/details/104021767