0
点赞
收藏
分享

微信扫一扫

快收藏-2021最新阿里精选面试题(数据库篇)

Alex富贵 2022-11-06 阅读 186

快到一年一度的10月份大企校招的时间了,这里给广大在校生和部分已经工作的老司机们整理一些阿里巴巴的面试题,希望给大家能在面试前做一些引导,查缺补漏。

1. 使用 mysql 索引都有哪些原则?索引什么数据结构?


1、 对于查询频率高的字段创建索引;

2、 对排序、分组、联合查询频率高的字段创建索引;

3、 索引的数目不宜太多

原因:  a、每创建一个索引都会占用相应的物理控件;

          b、过多的索引会导致 insert、update、delete 语句的执行效率降低;

4、若在实际中,需要将多个列设置索引时,可以采用多列索引

如:某个表(假设表名为 Student),存在多个字段(StudentNo, StudentName, Sex, Address, Phone,BirthDate),其中需要对 StudentNo,StudentName 字段进行查询,对Sex 字段进行分组,对 BirthDate 字段进行排序,此时可以创建多列索引 index,index_name (StudentNo, StudentName, Sex, BirthDate);#index_name 为索引名

在上面的语句中只创建了一个索引,但是对 4 个字段都赋予了索引的功能。

创建多列索引,需要遵循 BTree 类型,即第一列使用时,才启用索引。

在上面的创建语句中,只有 mysql 语句在使用到 StudentNo 字段时,索引才会被启用。

如: select * from Student where StudentNo = 1000; #使用到了 StudentNo字段,索引被启用。

以使用 explain 检测索引是否被启用如:explain select * from Student where StudentNo = 1000;

5、选择唯一性索引

唯一性索引的值是唯一的,可以更快速的通过该索引来确定某条记录。例如,学生表中学号是具有唯 一性的字段。为该字段建立唯一性索引可以很快的确定某个学生的信息。如果使用姓名的话,可能存 在同名现象,从而降低查询速度。

6、尽量使用数据量少的索引

如果索引的值很长,那么查询的速度会受到影响。例如,对一个 CHAR(100)类型的字段进行全文检索 需要的时间肯定要比对 CHAR(10)类型的字段需要的时间要多。

7、尽量使用前缀来索引

如果索引字段的值很长,最好使用值的前缀来索引。例如,TEXT 和 BLOG 类型的字段,进行全文检 索会很浪费时间。如果只检索字段的前面的若干个字符,这样可以提高检索速度。

8、删除不再使用或者很少使用的索引.

表中的数据被大量更新,或者数据的使用方式被改变后,原有的一些索引可能不再需要。数据库管理 员应当定期找出这些索引,将它们删除,从而减少索引对更新操作的影响 B+ tree 树索引, B tree,散列

2. Mysql 有哪些存储引擎?请详细列举其区别?

InnoDB: 事务型存储引擎, 并且有较高的并发读取频率

MEMORY:存储引擎,存放在内存中,数据量小, 速度快

Merge:

ARCHIVE:归档, 有很好的压缩机制

3. 设计高并发系统数据库层面该如何设计?数据库锁有哪些类型?如何实现?

1. 分库分表:同样量的数据平均存储在不同数据库相同表(或不同表)中,减轻单表

压力,如果还是很大,就可以每个库在分多张表,根据 hash 取值或者其他逻辑判断将

数据存储在哪张表中

2. 读写分离:数据库原本就有主从数据库之分,查询在从服务器,增删改在主服务器,

3. 归档和操作表区分:建一张归档表,将历史数据放入,需要操作的表数据单独存储

4. 索引啊之类的创建,对于数据量很大,百万级别以上的单表,如果增删改操作不频繁的话, 可以创建 bitMap 索引,速度要快得多

1. 共享锁:要等第一个人操作完,释放锁,才能操作

2. 更新锁:解决死锁,别人可以读,但不能操作

3. 排他锁:读写都被禁用

4. 意向锁(xlock):对表中部分数据加锁,查询时,可以跳过

5. 计划锁:操作时,别的表连接不了这张表,

4. 数据库事务有哪些

原子性:所有操作要么全部成功,要么全部失败

一致性:例如转账,一个事务执行前和执行后必须一致

隔离性:防止脏读, 重复读问题

持久性:永久性提交数据库

 5. Oracle 常用函数有哪些?

Concat: 字符串拼接, 或者 ||

MConcat: 字符串拼接, 或者 ||

Instr: 指定字符串位置

Length: 长度

Trim: 去空格

Lower: 小写

Upper:大写

Nvl: 判断空

Replace: 替换

Substr: 截取

Floor: 向下取整

To_number:

To_char:

To_date:

Decode: 判断函数等等

6 Sql 中哪些情况可能不会走索引?

1. 查询谓词没有使用索引的主要边界,换句话说就是 select *,可能会导致不走索引

2. 单键值的 b 树索引列上存在 null 值,导致 COUNT(*)不能走索引。索引列存在空值

3. 索引列上有函数运算,导致不走索引

4. 隐式类型转换导致不走索引。

5. 表的数据库小或者需要选择大部分数据,不走索引

6. !=或者<>(不等于),可能导致不走索引

7. 表字段的属性导致不走索引,字符型的索引列会导致优化器认为需要扫描索引大

部分数据且聚簇因子很大,最终导致弃用索引扫描而改用全表扫描方式,

8. 使用 like, in 等, 可能导致不走索引

7. 讲讲分布式唯一 ID ?

确定 ID 存储用 64 位,1 个 64 位二进制 1 是这样的 00000000.....1100......0101,切割 64 位,某段二进制表示成 1 个约束条件,前 41 位为毫秒时间,后紧接 9 位为 IP,IP 之后为自增的二进制,记录当前面位数相同情况下是第几个 id,如现在有 10 台机器,这个 id 生成器生成 id 极限是同台机器 1ms 内生成 2 的 14 次方个 ID。

分布式唯一 ID = 时间戳 << 41 位, int 类型服务器编号 << 10,序列自增 sequence。

每个时间戳内只能生成固定数量如(10 万)个自增号,达到最大值则同步等待下个时间戳,自增从 0 开始。将毫秒数放在最高位,保证生成的 ID 是趋势递增的,每个业务线、每个机房、每个机器生成的 ID 都是不同的。如 39bit 毫秒数|4bit 业务线|2bit机房|预留|7bit 序列号。高位取 2016 年 1 月 1 日 1 到现在的毫秒数,系统运行 10 年,至少需要 10 年 x365 天 x24 小时 x3600 秒 x1000 毫秒=320x10~9,差不多 39bit 给毫秒数,每秒单机高峰并发小于 100,差不多 7bit 给每毫秒的自增号,5 年内机房小于 100台机器,预留 2bit 给机房,每个机房小于 100 台机器,预留 7bit 给每个机房,业务线

小于 10 个,预留 4bit 给业务线标识。

64bit 分布式 ID(42bit 毫秒+5bit 机器 ID+12 位自增)等

生成分布式 ID 的方式:A,2 个自增表,步长相互隔开 B,时间的毫秒或者纳秒 C,UUID,64 位约束条件(如上)

8. NIO 和 和 IO 的区别?

第一点,NIO 少了 1 次从内核空间到用户空间的拷贝。

ByteBuffer.allocateDirect()分配的内存使用的是本机内存而不是 Java 堆上的内存,和网络或者磁盘交互都在操作系统的内核空间中发生。allocateDirect()的区别在于这块内存不由 java 堆管理, 但仍然在同一用户进程内。

第二点,NIO 以块处理数据,IO 以流处理数据

第三点,非阻塞,NIO1 个线程可以管理多个输入输出通道

9 Redis 内存数据上升到一定大小会执行数据淘汰策略,Redis 提供了哪 6  种数据淘汰策略? 

LRU:从已设置过期时间的数据集合中挑选最近最少使用的数据淘汰

random:从已设置过期时间的数据中挑选任意数据淘汰

ttl:从已设置过期时间的数据集合中挑选将要过期的数据淘汰。

notenvision:禁止驱逐数据

如 mysql 中有 2 千万数据,redis 只存储 20 万的热门数据。LRU 或者 TTL 都满足热点数

据读取较多,不太可能超时特点。

redis 特点:速度块,O(1),丰富的数据类型,支持事物原子性,可用于缓存,比 memecache

速度块,可以持久化数据。

常见问题和解决:Master 最好不做持久化如 RDB 快照和 AOF 日志文件;如果数据比较重要,某分 slave 开启 AOF 备份数据,策略为每秒 1 次,为了主从复制速度及稳定,MS主从在同一局域网内;主从复制不要用图状结构,用单向链表更为稳定 M-S-S-S-S

redis 过期采用懒汉+定期,懒汉即 get/set 时候检查 key 是否过期,过期则删除 key,定期遍历每个 DB,检查制定个数个 key;结合服务器性能调节并发情况。

过期淘汰,数据写入 redis 会附带 1 个有效时间,这个有效时间内该数据被认为是正确的并不关心真实情况,例如对支付等业务采用版本号实现,redis 中每一份数据都维持1 个版本号,DB 中也维持 1 份,只有当 redis 的与 DB 中的版本一致时,才会认为 redis为有效的,不过仍然每次都要访问 DB,只需要查询 version 版本字段即可。

10. 请描述 MyISM 和 和 InnoDB?

MyISM 采用表级锁,对 Myism 表读不会阻塞读,会阻塞同表写,对 Myism 写则会阻塞读和写,即一个线程获得 1 个表的写锁后,只有持有锁的线程可以对表更新操作,其他线程的读和写都会等待。


InnoDB,采用行级锁,支持事务,例如只对 a 列加索引,如果 update ...where a=1 and b=2 其实也会锁整个表, select 使用共享锁,update insert delete 采用排它锁,commit 会把锁取消,当然 select by id for update 也可以制定排它锁。

11. 请描述实时队列? 

实时队列采用双队列模式,生产者将行为记录写入 Queue1,worker 服务从 Queue1 消费新鲜数据,如果异常则写入 Queue2(主要保存异常数据),RetryWorker 会监听 Queue2,消费异常数据,如果还未处理成功按照一定的策略等待或者将异常数据再写入 Queue2,如果数据发生积压可以调整 worker 的消费游标,从最新数据重新开始消费,保证了最新 data 得到处理,中间未处理的一段则可以启动 backupWorker 指定起止游标在消费完

指定区间的数据后,backupWorker 会自动停止。

DB 降级开关后,可直接写入 redis(storm),同时将数据写入一份到 Retry 队列,在开启 DB 降级开关后消费 Retry 队列中的数据,从而把数据写入到 mysql 中,达到最终一致性。MYSQL 切分为分片为 2 的 N 次方,例如原来分为两个库 d0 和 d1 均放在 s0 服务器上,s0 同时有备机 s1,扩容只要几步骤:确保 s0 到 s1 服务器同步顺利,没有明显延迟;s0 暂时关闭读写权限;确保 s1 已经完全同步到 s0 更新;s1 开放读写权限;

d1 的 dns 由 s0 切换到 s1;s0 开放读写权限。

12.DB 的特性和隔离级别?

4 大特性:原子性,一致性,分离性,持久性

隔离级别:

读提交:写事务禁止读

读未提交:写事务允许读

可重复读:写事务禁止读事务,读禁止写

序列化:全部禁止

详细说明:读提交 1 个事务开始写则全部禁止其他事务访问该行。读未提交 1 个事务开

始写则不允许其他事务同时写,但可以读。可重复读 读事务会禁止写事务,写事物则

禁止其他任何事务。序列化性能最低,全部禁止,串行执行。MYSQL 默认的是可重复

读。


13. mysql 数据库锁表怎么解决?

查询锁表信息

当前运行的所有事务

select * from information_schema.innodb_trx

当前出现的锁

select * from information_schema.innodb_locks

锁等待的对应关系

select * from information_schema.innodb_lock_waits

通过 select * from information_schema.innodb_trx 查询 trx_mysql_thread_id 然

后执行 kill 线程 ID

KILL 8807;//后面的数字即时进程的 ID


举报

相关推荐

0 条评论