Java面试-MySQL

Posted 程序员编程

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java面试-MySQL相关的知识,希望对你有一定的参考价值。

来源:segmentfault.com/u/jack3021

mysql

1.MySQL中myisam与innodb的区别,至少5点

(1)、问5点不同;

  • 1>.InnoDB支持事物,而MyISAM不支持事物

  • 2>.InnoDB支持行级锁,而MyISAM支持表级锁

  • 3>.InnoDB支持MVCC, 而MyISAM不支持

  • 4>.InnoDB支持外键,而MyISAM不支持

  • 5>.InnoDB不支持全文索引,而MyISAM支持。

(2)、innodb引擎的4大特性

插入缓冲(insert buffer)、二次写(double write)、自适应哈希索引(ahi)、预读(read ahead)。

(3)、2者select count(*)哪个更快,为什么

myisam更快,因为myisam内部维护了一个计数器,可以直接调取。

2.innodb的日志的实现有哪些?

错误日志:记录出错信息,也记录一些警告信息或者正确的信息。

查询日志:记录所有对数据库请求的信息,不论这些请求是否得到了正确的执行。

慢查询日志:设置一个阈值,将运行时间超过该值的所有SQL语句都记录到慢查询的日志文件中。

二进制日志:记录对数据库执行更改的所有操作。

中继日志:中继日志也是二进制日志,用来给slave 库恢复

事务日志:重做日志redo和回滚日志undo

3.sql优化各种方法

(1)、explain出来的各种item的意义;

select_type

表示查询中每个select子句的类型

type

表示MySQL在表中找到所需行的方式,又称“访问类型”

possible_keys

指出MySQL能使用哪个索引在表中找到行,查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询使用

key

显示MySQL在查询中实际使用的索引,若没有使用索引,显示为NULL

key_len

表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度

ref

表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值

Extra

包含不适合在其他列中显示但十分重要的额外信息

4.MySQL中InnoDB引擎的行锁是通过加在什么上完成(或称实现)的?为什么是这样子的?

InnoDB是基于索引来完成行锁

例: select * from tab_with_index where id = 1 for update;

for update 可以根据条件来完成行锁锁定,并且 id 是有索引键的列,

如果 id 不是索引键那么InnoDB将完成表锁。

5.什么是索引?

索引是一种数据结构,方便我们快速的进行数据查找。

6. 索引是什么样的数据结构?

InnoDB使用的是B+树索引。

7.什么是回表查询?

例如:

select * from t where name='lisi';

是如何执行的呢?

Java面试-MySQL

如粉红色路径,需要扫码两遍索引树:

(1)先通过普通索引定位到主键值id=5;

(2)再通过聚集索引定位到行记录;
这就是所谓的回表查询,先定位主键值,再定位行记录,它的性能较扫一遍索引树更低。

①聚集索引(聚簇索引):以 InnoDB 作为存储引擎的表,表中的数据都会有一个主键,即使你不创建主键,系统也会帮你创建一个隐式的主键。

这是因为 InnoDB 是把数据存放在 B+ 树中的,而 B+ 树的键值就是主键,在 B+ 树的叶子节点中,存储了表中所有的数据。

这种以主键作为 B+ 树索引的键值而构建的 B+ 树索引,我们称之为聚集索引。

②非聚集索引(非聚簇索引):以主键以外的列值作为键值构建的 B+ 树索引,我们称之为非聚集索引。

非聚集索引与聚集索引的区别在于非聚集索引的叶子节点不存储表中的数据,而是存储该列对应的主键,想要查找数据我们还需要根据主键再去聚集索引中进行查找,这个再根据聚集索引查找数据的过程,我们称为回表。

明白了聚集索引和非聚集索引的定义,我们应该明白这样一句话:数据即索引,索引即数据。

8.Hash树和B+树有什么区别?

Hash树底层就是Hash表,进行查找时,调用一次hash函数就可以获得到响应的键值,之后进行回表查询获得实际数据。
B+树等底层是多路平衡查找树,对每一次查询都是从根节点出发,找到叶子节点后获得所查的键值,然后根据查询判断是否要回表操作。

  • hash索引进行等值查询更快,无法进行范围查询。(因为hash索引在经过hash函数建立索引之后,索引的顺序与原顺序无法保持一致)

  • hash不支持模糊查询以及多列索引最左前缀匹配。因为hash不知道AAAA和AAAAB索引有没有相关性。

  • hash任何时候都要进行回表查询,而B+树在某些条件下只用索引就可以完成查询。

  • hash如果某个键值存在大量重复时候会发生hash碰撞,效率会很低,而B+树的查询比较稳定,每次都是从根节点到子节点,且树的高度较低。

9.B+树和B树有什么区别?

B树,叶子节点和非叶子节点都存储数据。
B+树,只有在叶子节点上存储数据。
B树是有序数组+平衡多叉树。
B+树是有序数组链表+平衡多叉树。
B+树只需要便利叶子节点就可以对整棵树进行遍历,而B树需要查询非叶子节点效率不高。

10.什么是聚集索引?

在B+树的索引种,叶子节点除了可能存储了当前的K值,也可能存储了当前K值和整行数据,这就是聚集索引和非聚集索引。
在InnoDB中,只有主键是聚集索引,如果没有主键,则挑选一个唯一键来建立聚集索引,如果没有唯一键,则隐式的生成一个键来建立聚集索引。

当使用聚集索引时候,对应的叶子节点可以获取整行数据,所以不用再次回表查询。

11.非聚集索引一定会回表查询吗?

不一定,如果查询的字段如果全部命中索引,就没有必要进行回表查询。

12.在建立索引的时候,需要考虑哪些因素?

  1. 字段的使用频率。

  2. 联合索引的话,还需要考虑顺序。

  3. 不经常计算的字段。

13.联合索引是什么?为什么需要注意联合索引的顺序?

Mysql可以用多个字段同时建立一个索引,叫做联合索引。

在联合索引中如果命中索引,则需要按照建立索引的字段顺序挨个使用,否则无法命中索引。

MySQL使用索引时需要索引有序,假设现在建立了"name,age,school"的联合索引,那么索引的排序为: 先按照name排序,如果name相同,则按照age排序,如果age的值也相等,则按照school进行排序.

Java面试-MySQL

可以看到a的值是有顺序的,1,1,2,2,3,3,而b的值是没有顺序的1,2,1,4,1,2。所以b = 2这种查询条件没有办法利用索引,因为联合索引首先是按a排序的,b是无序的。

同时我们还可以发现在a值相等的情况下,b值又是按顺序排列的,但是这种顺序是相对的。所以最左匹配原则遇上范围查询就会停止,剩下的字段都无法使用索引。例如a = 1 and b = 2 a,b字段都可以使用索引,因为在a值确定的情况下b是相对有序的,而a>1and b=2,a字段可以匹配上索引,但b值不可以,因为a的值是一个范围,在这个范围中b是无序的。

最左匹配原则: 最左优先,以最左边的为起点任何连续的索引都能匹配上。同时遇到范围查询(>、<、between、like)就会停止匹配。

14.哪些情况会让索引失效?

  • 参与数学运算或者函数。

  • 在like左边使用了%。

  • 当mysql分析全表扫描比使用索引快时。

  • 当使用联合索引时,不符合最左前缀匹配原则。

  • varchar不加引号。

  • 使用 not <> != 都会失效。

15.什么是事务?

事务就是一系列的操作,要么全部成功,要么全部失败。需要符合ACID特性。

16.ACID是什么?

A=Atomicity

原子性:要么全部成功,要么全部失败。不可能只执行一部分操作。

C=Consistency

一致性:系统(数据库)总是从一个一致性的状态转移到另一个一致性的状态,不会存在中间状态。

I=Isolation

隔离性:通常来说一个事务在完全提交之前,对其他事务是不可见的。

D=Durability

持久性:一旦事务提交,那么就永远是这样子了,哪怕系统崩溃也不会影响到这个事务的结果。

17.同时有多个事务在进行会怎么样?

  • 脏读:A事务读取到了B事务未提交的内容,而B事务后面进行了回滚。

  • 不可重复读:当设置A事务只能读取B事务已经提交的部分,会造成A事务内的两次查询结果不一样,因为B在此期间对事务进行了提交。

  • 幻读:A事务读取了一个范围的内容,同时B事务在此期间插入了一条数据,造成”幻觉“。

18.如何解决这些问题?MySQL的事务隔离级别了解吗?

MySQL的四种隔离级别如下:

  • 未提交读(READ UNCOMMITTED)

这个隔离级别下,其他事务可以看到本事务没有提交的部分修改。因此会造成脏读的问题(读取到了其他事务未提交的部分,而之后该事务进行了回滚)。

这个级别的性能没有足够大的优势,但是又有很多的问题,因此很少使用。

  • 已提交读(READ COMMITTED)

其他事务只能读取到本事务已经提交的部分。这个隔离级别有不可重复读的问题,在同一个事务内的两次读取,拿到的结果竟然不一样,因为另外一个事务对数据进行了修改。

  • REPEATABLE READ(可重复读)

可重复读隔离级别解决了上面不可重复读的问题(看名字也知道),但是仍然有一个新问题,就是 幻读,当你读取id> 10 的数据行时,对涉及到的所有行加上了读锁,此时例外一个事务新插入了一条id=11的数据,因为是新插入的,所以不会触发上面的锁的排斥,那么进行本事务进行下一次的查询时会发现有一条id=11的数据,而上次的查询操作并没有获取到,再进行插入就会有主键冲突的问题。

  • SERIALIZABLE(可串行化)

这是最高的隔离级别,可以解决上面提到的所有问题,因为他强制将所以的操作串行执行,这会导致并发性能极速下降,因此也不是很常用。

隔离级别 脏读 不可重复读 幻读
READ UNCOMMITTED
READ COMMITTED
REPEATABLE READ

SERIALIZABLE


查看当前的事务隔离级别:
SELECT @@global.tx_isolation;

修改当前事务隔离级别:
set global transaction isolation level read committed;

19.InnoDB使用的是那种隔离级别?

InnoDB默认使用的是可重复读隔离级别。

20.MySQL都有哪些锁?

从类别上来讲,有共享锁和排它锁。

共享锁,又叫读锁:当用户要进行数据的读取时候,对数据加上共享锁,共享锁可以有多个。

排它锁,又叫写锁:当用户进行数据写入时,对数据加上排它锁,排它锁只能有一个。

锁的粒度取决于具体的存储引擎,InnoDB实现了行级锁、页级锁、表级锁。

加锁的开销从大到小,并发能力从大大小。

21.主键使用自增ID还是UUID?

推荐使用自增ID,不要使用UUID。

因为在InnoDB存储引擎中,主键索引是作为聚集索引存在的,也就是说,主键索引的B+树节点上存储了主键索引以及全部数据。如果是自增ID的话,只需要往后排列即可。如果是UUID,每个ID的大小不确定,会导致数据移动,产生垃圾碎片,从而造成性能下降。

图片来源于《高性能MySQL》: 其中默认后缀为使用自增ID,_uuid为使用UUID为主键的测试,测试了插入100w行和300w行的性能。

Java面试-MySQL

22.如果要存储用户密码,用什么字段合适?

密码散列,用户身份证号等固定长度的字符串都应该使用char而不是varchar,这样可以节省空间提高检索效率。

23.char和varchar有什么区别?

char是一个定长字段,如果申请的长度为10的空间,无论实际存储多少内容,该字段都占用10个字符。

varchar是变长的,也就是说申请的只是最大长度,占用的空间为实际字符长度+1,最后一个字符存储使用了多少空间。

在检索效率上来讲,char > varchar 因此在使用中,如果确定某个字段的值的长度,可以使用char,否则应该尽量使用varchar。例如存储用户MD5加密后的密码,则应该使用char。

24.什么是存储过程?有哪些优缺点?

存储过程是一些预编译的SQL语句。1、更加直白的理解:存储过程可以说是一个记录集,它是由一些T-SQL语句组成的代码块,这些T-SQL语句代码像一个方法一样实现一些功能(对单表或多表的增删改查),然后再给这个代码块取一个名字,在用到这个功能的时候调用他就行了。2、存储过程是一个预编译的代码块,执行效率比较高,一个存储过程替代大量T_SQL语句 ,可以降低网络通信量,提高通信速率,可以一定程度上确保数据安全。

25.说一说三个范式

第一范式:每个列都不可再拆分。

第二范式:非主键列完全依赖主键,而不是主键的一部分。

第三范式:非主键列只依赖主键,不依赖其他非主键。


更多精彩

以上是关于Java面试-MySQL的主要内容,如果未能解决你的问题,请参考以下文章

Java工程师面试题,二级java刷题软件

面试常用的代码片段

面向面试编程代码片段之GC

经验总结:Java高级工程师面试题-字节跳动,成功跳槽阿里!

从mysql的片段中加载ListView

Java面试题!mysql格式化查询结果