数据库面试高频问题汇总

一、MySQL

1、索引

概念:

索引是一种数据结构。数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。索引的实现通常使用B树及其变种B+树。更通俗的说,索引就相当于目录。为了方便查找书中的内容,通过对内容建立索引形成目录。而且索引是一个文件,它是要占据物理空间的。

索引的优点

可以大大加快数据的检索速度,这也是创建索引的最主要的原因。树的高度就是IO次数。

通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。

索引的缺点

时间方面:创建索引和维护索引要耗费时间,具体地,当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,会降低增/改/删的执行效率;

空间方面:索引需要占物理空间。

索引的存储:hash表的模式或者B+树的模式(B树)

B树的数据结构:

相比于搜索二叉树,B树相当是一个m路搜索树。

B+树的数据结构:

1)多路非二叉

(2)只有叶子节点保存数据

(3)搜索时相当于二分查找

(4)增加了相邻接点的指向指针。

从上面我们可以看出最核心的区别主要有俩,

一个是数据的保存位置:B树保存在所有的节点中,B+树保存在叶子节点

一个是相邻节点的指向:B树叶子节点之间没有指针,B+树有。

2B+树相比B树的优势:

总结如下三点:

a、单一节点存储更多的元素,使得查询的IO次数更少;

b、所有查询都要查找到叶子节点,查询性能稳定;

c、所有叶子节点形成有序链表,便于范围查询。

3MySQL的索引为什么用B+树?

B+树由B树和索引顺序访问方法演化而来,它是为磁盘或其他直接存取辅助设备设计的一种平衡查找树,在B+树中,所有记录节点都是按键值的大小顺序存放在同一层的叶子节点,各叶子节点通过指针进行链接。如下图:

 

B+树索引在数据库中的一个特点就是高扇出性,例如在InnoDB存储引擎中,每个页的大小为16KB。在数据库中,B+树的高度一般都在2~4层,这意味着查找某一键值最多只需要2到4次IO操作,这还不错。因为现在一般的磁盘每秒至少可以做100次IO操作,2~4次的IO操作意味着查询时间只需0.02~0.04秒。

聚簇索引与非聚簇索引

聚集索引是一种索引,该索引中键值的逻辑顺序决定了表中相应行的物理顺序。

聚集索引确定表中数据的物理顺序。聚集索引类似于电话簿,按姓氏排列数据。由于聚集索引规定数据在表中的物理存储顺序,因此一个表只能包含一个聚集索引。但该索引可以包含多个列(组合索引),就像电话簿按姓氏和名字进行组织一样。

Myisam 非聚集索引, mysql 5.5之前使用   采用b+树,叶子节点存放地址

Innodb 聚集索引,mysql 5.5之后使用  采用b+树,因为InnoDB的数据文件本身要按主键聚集,所以InnoDB要求表必须有主键,叶子节点直接是数据。InnoDB的所有辅助索引都引用主键作为data域,所以其辅助索引需要两次查询,首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录。项目中使用的

非根结点至少有Math.ceil(m/2)-1个关键字

插入都是在叶子节点,并且进行向上溢出

删除进行向下溢出

4MySQL怎么判断要不要加索引?

建议按照如下的原则来创建索引:a当唯一性是某种数据本身的特征时,指定唯一索引。使用唯一索引需能确保定义的列的数据完整性,以提高查询速度。b在频繁进行排序或分组(即进行group by或order by操作)的列上建立索引,如果待排序的列有多个,可以在这些列上建立组合索引。

5数据库索引失效了怎么办?

可以采用以下几种方式,来避免索引失效:使用组合索引时,需要遵循“最左前缀”原则;

不在索引列上做任何操作,例如计算、函数、类型转换,会导致索引失效而转向全表扫描;

尽量使用覆盖索引(之访问索引列的查询),减少 select * 覆盖索引能减少回表次数;

MySQL在使用不等于(!=或者<>)的时候无法使用索引会导致全表扫描;

LIKE以通配符开头(%abc)MySQL索引会失效变成全表扫描的操作;

字符串不加单引号会导致索引失效(可能发生了索引列的隐式转换);

少用or,用它来连接时会索引失效。

explain:使用此关键字查询可以返回有多少索引并且本次是否使用了索引。

analyze:可以查看索引的结构判断是否需要重构。

6mysql分页优化

如果limit的偏移量过大会导致查询许多无用的信息,造成时间浪费。

方法:推荐使用"延迟关联"的方法来优化排序操做,何谓"延迟关联" :经过使用覆盖索引查询返回须要的主键,再根据主键关联原表得到须要的数据。

7内连接

内连接通过INNER JOIN来实现,它将返回两张表中满足连接条件的数据,不满足条件的数据不会查询出来。

外连接:

外连接通过OUTER JOIN来实现,它会返回两张表中满足连接条件的数据,同时返回不满足连接条件的数据。外连接有两种形式:左外连接(LEFT OUTER JOIN)、右外连接(RIGHT OUTER JOIN)。

左外连接:可以简称为左连接(LEFT JOIN),它会返回左表中的所有记录和右表中满足连接条件的记录。

右外连接:可以简称为右连接(RIGHT JOIN),它会返回右表中的所有记录和左表中满足连接条件的记录。

8sql注入的几种常见方式

     1、恶意拼接:比如

     SELECT * FROM users WHERE user_id = 1234; DELETE FROM users

     2、利用注释进行注入:比如

     SELECT * FROM user_table WHERE username='’or 1 = 1 -- and password='’

如何应对:1、对sql语句进行过滤比如过滤or

                      2、参数化(占位符),预编译sql语句

9、 表中包含几千万条数据该怎么办?

建议按照如下顺序进行优化:

优化SQL和索引;

增加缓存,如memcached、redis;

读写分离,可以采用主从复制,也可以采用主主复制;

使用MySQL自带的分区表,这对应用是透明的,无需改代码,但SQL语句是要针对分区表做优化的;

做垂直拆分,即根据模块的耦合度,将一个大的系统分为多个小的系统;

做水平拆分,要选择一个合理的sharding key,为了有好的查询效率,表结构也要改动,做一定的冗余,应用也要改,sql中尽量带sharding key,将数据定位到限定的表上去查,而不是扫描全部的表。

10、MySQL的慢查询优化有了解吗?

a、开启慢查询日志

b、分析慢查询日志

c、常见的慢查询优化        未使用索引         优化LIMIT分页      分解关联查询     优化数据库结构

11、当前读与快照读

当前读指的是读取最新已经提交的数据

快照读指的是读取当前事务开始前最新的版本的数据

二、事务

1、概念

事务可由一条非常简单的SQL语句组成,也可以由一组复杂的SQL语句组成。在事务中的操作,要么都执行修改,要么都不执行,这就是事务的目的,也是事务模型区别于文件系统的重要特征之一。

四个特性:

原子性:事物的原子性是指事物中包含的所有操作,要么全做,要么全不做。

一致性:在事务开始以前,数据库处于一致性的状态,事务结束后,数据库也必须处于一致性状态。

隔离性:事务隔离性要求系统必须保证事务不受其他并发执行的事务的影响,也即要达到这样一种效果

持久性:一个事务一旦成功完成,它对数据库的改变必须是永久的,即便是在系统遇到故障的情况下也不会丢失。数据的重要性决定了事 务持久性的重要性。

2、脏读、不可重复读、幻读的概念

脏读:读取到了未提交的数据。

不可重复读:同一事务中两次相同的操作结果不一致,主要指修改操作。

幻读:是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。主要指删除、插入操作。参考一下博客:

脏读、幻读和不可重复读_song854601134的博客-CSDN博客_幻读脏读不可重复读https://blog.csdn.net/song854601134/article/details/125147625

3 谈谈MySQL的事务隔离级别

SQL 标准定义了四种隔离级别,这四种隔离级别分别是:

读未提交(READ UNCOMMITTED);

读提交 (READ COMMITTED);

可重复读 (REPEATABLE READ);

串行化 (SERIALIZABLE)。

事务隔离是为了解决脏读、不可重复读、幻读问题,下表展示了 4 种隔离级别对这三个问题的解决程度:

隔离级别

脏读

不可重复读

幻读

READ UNCOMMITTED

可能

可能

可能

READ COMMITTED

不可能

可能

可能

REPEATABLE READ

不可能

不可能

可能

SERIALIZABLE

不可能

不可能

不可能

上述4种隔离级别MySQL都支持,并且InnoDB存储引擎默认的支持隔离级别是REPEATABLE READ,但是与标准SQL不同的是,InnoDB存储引擎在REPEATABLE READ事务隔离级别下,使用Next-Key Lock的锁算法,因此避免了幻读的产生。所以,InnoDB存储引擎在默认的事务隔离级别下已经能完全保证事务的隔离性要求,即达到SQL标准的SERIALIZABLE隔离级别。

三、锁

概念

锁是数据库系统区别于文件系统的一个关键特性,锁机制用于管理对共享资源的并发访问。下面我们以MySQL数据库的InnoDB引擎为例,来说明锁的一些特点。

锁的类型:

InnoDB存储引擎实现了如下两种标准的行级锁:

共享锁(S Lock),允许事务读一行数据。

排他锁(X Lock),允许事务删除或更新一行数据。

1、介绍一下间隙锁

InnoDB存储引擎有3种行锁的算法,间隙锁(Gap Lock)是其中之一。间隙锁用于锁定一个范围,但不包含记录本身。它的作用是为了阻止多个事务将记录插入到同一范围内,而这会导致幻读问题的产生。

2、InnoDB中行级锁是怎么实现的

InnoDB行级锁是通过给索引上的索引项加锁来实现的。只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁。

当表中锁定其中的某几行时,不同的事务可以使用不同的索引锁定不同的行。另外,不论使用主键索引、唯一索引还是普通索引,InnoDB都会使用行锁来对数据加锁。

Mybaits

概念

MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。

aMybatis是一个半ORM(对象关系映射)框架,底层封装了JDBC,是程序员在开发时只需要关注SQL语句本身,不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。使得程序员可以花更多的精力放到业务开发中。另外,程序员直接编写原生态sql,严格控制sql执行性能,灵活度高。

bMyBatis 可以使用简单的 XML文件 或注解方式来配置和映射原生信息,将 POJO映射成数据库中的记录,避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。

c、通过xml 文件或注解的方式将要执行的各种 statement 配置起来,并通过java对象和 statementsql的动态参数进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射为java对象并返回。(从执行sql到返回result的过程)。

一级缓存:在一个sqlsession

二级缓存:多个session中一个namespace

1MyBatis中的$和#有什么区别?

使用#设置参数时,MyBatis会创建预编译的SQL语句,然后在执行SQL时MyBatis会为预编译SQL中的占位符(?)赋值。预编译的SQL语句执行效率高,并且可以防止注入攻击。

使用$设置参数时,MyBatis只是创建普通的SQL语句,然后在执行SQL语句时MyBatis将参数直接拼入到SQL里。这种方式在效率、安全性上均不如前者,但是可以解决一些特殊情况下的问题。例如,在一些动态表格(根据不同的条件产生不同的动态列)中,我们要传递SQL的列名,根据某些列进行排序,或者传递列名给SQL都是比较常见的场景,这就无法使用预编译的方式了。

四、Redis

Redis本质上是一个Key-Value类型的非关系型的内存数据库,很像Memcached,整个数据库加载在内存当中操作,定期通过异步操作把数据库中的数据flush到硬盘上进行保存。

 

1 Redis有哪些数据类型?

Redis支持5种核心的数据类型,分别是字符串、哈希、列表、集合、有序集合;

Redis还提供了BitmapHyperLogLogGeo类型,但这些类型都是基于上述核心数据类型实现的;

Redis5.0新增加了Streams数据类型,它是一个功能强大的、支持多播的、可持久化的消息队列。

2、缓存穿透、缓存击穿、缓存雪崩以及解决方案

缓存穿透:是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。

解决方案:

接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;

从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,这样可以防止攻击用户反复用同一个id暴力攻击

 

缓存击穿:是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。指的是同一个数据。

解决方案:a、热点数据永不过期    b、分布式锁,只容许一个线程去数据库查询并重建缓存,其他线程等待。

 

缓存雪崩:是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。

解决方案:a、过期时间设置不一样   b、多级缓存   c、加锁、限流等

3你要如何设计Redis的过期时间?

热点数据不设置过期时间,使其达到“物理”上的永不过期,可以避免缓存击穿问题;

在设置过期时间时,可以附加一个随机数,避免大量的key同时过期,导致缓存雪崩。

4redis持久化机制

为了能够重用Redis数据,或者防止系统故障,我们需要将Redis中的数据写入到磁盘空间中,即持久化。

Redis提供了两种不同的持久化方法可以将数据存储在磁盘中,一种叫快照RDB,另一种叫只追加文件AOF

5. 为什么要用 Redis 而不用 map/guava 做缓存?

 

缓存分为本地缓存和分布式缓存。以java为例,使用自带的map或者guava实现的是本地缓存,最主要的特点是轻量以及快速,生命周期随着jvm的销毁而结束,并且在多实例的情况下,每个实例都需要各自保存一份缓存,缓存不具有一致性。

使用Redismemcached之类的称为分布式缓存,在多实例的情况下,各实例共用一份缓存数据,缓存具有一致性。缺点是需要保持Redismemcached服务的高可用,整个程序架构上较为复杂。

对比:

Redis 可以用几十 G 内存来做缓存,Map 不行,一般 JVM 也就分几个 G 数据就够大了;

Redis 的缓存可以持久化,Map 是内存对象,程序一重启数据就没了;

Redis 可以实现分布式的缓存,Map 只能存在创建它的程序里;

Redis 可以处理每秒百万级的并发,是专业的缓存服务,Map 只是一个普通的对象;

Redis 缓存有过期机制,Map 本身无此功能;Redis 有丰富的 APIMap 就简单太多了;

Redis可单独部署,多个项目之间可以共享,本地内存无法共享;

Redis有专门的管理工具可以查看缓存数据。

6redis的过期键删除策略

定期删除:Redis会周期性的随机测试一批设置了过期时间的key并进行处理。测试到的已过期的key将被删除。

惰性删除:惰性删除不会去主动删除数据,而是在访问数据的时候,判断是否过期,过期就删除。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值