2021年Java知识体系总结,Java开发面试中常问的数据库方面问题

本文深入探讨了Java开发中数据库相关的面试问题,涉及触发器、存储过程、MySQL优化策略,如查询缓存、EXPLAIN分析、索引使用。还对比了MyISAM与InnoDB引擎的区别,提供了表结构设计的最佳实践。此外,文章提到了Redis的单线程模型、线程安全问题以及主从复制机制,最后简单介绍了Docker的基础概念和实践操作。
摘要由CSDN通过智能技术生成
  1. ON <表名称> --触发器是属于某一个表的:当在这个表上执行插入、 更新或删除操作的时候就导致触发器的激活. 我们不能给同一张表的同一个事件安排两个触发器。

  2. FOR EACH ROW --触发器的执行间隔:FOR EACH ROW子句通知触发器 每隔一行执行一次动作,而不是对整个表执行一次。

  3. <触发器SQL语句> --触发器包含所要触发的SQL语句:这里的语句可以是任何合法的语句, 包括复合语句,但是这里的语句受的限制和函数的一样。

什么是存储过程


简单的说,就是一组SQL语句集,功能强大,可以实现一些比较复杂的逻辑功能,类似于JAVA语言中的方法;

ps:存储过程跟触发器有点类似,都是一组SQL集,但是存储过程是主动调用的,且功能比触发器更加强大,触发器是某件事触发后自动调用;

有哪些特性

  1. 有输入输出参数,可以声明变量,有if/else, case,while等控制语句,通过编写存储过程,可以实现复杂的逻辑功能;

  2. 函数的普遍特性:模块化,封装,代码复用;

  3. 速度快,只有首次执行需经过编译和优化步骤,后续被调用可以直接执行,省去以上步骤;


DROP PROCEDURE IF EXISTS `proc_adder`;

DELIMITER ;;

CREATE DEFINER=`root`@`localhost` PROCEDURE `proc_adder`(IN a int, IN b int, OUT sum int)

BEGIN

    #Routine body goes here...



    DECLARE c int;

    if a is null then set a = 0; 

    end if;

  

    if b is null then set b = 0;

    end if;



    set sum  = a + b;

END

;;

DELIMITER ;



set @b=5;

call proc_adder(0,@b,@s);

SELECT @s as sum;







create table tab2(

   tab2_id varchar(11)

);



DROP TRIGGER if EXISTS t_ai_on_tab1;

create TRAILING t_ai_on_tab1

AFTER INSERT ON tab1

for EACH ROW

BEGIN

   INSERT INTO tab2(tab2_id) values(new.tab1_id);

end;



INSERT INTO tab1(tab1_id) values('0001');



SELECT * FROM tab2; 

MySQL优化


  1. 开启查询缓存,优化查询

  2. explain你的select查询,这可以帮你分析你的查询语句或是表结构的性能瓶颈。EXPLAIN 的查询结果还会告诉你你的索引主键被如何利用的,你的数据表是如何被搜索和排序的

  3. 当只要一行数据时使用limit 1,MySQL数据库引擎会在找到一条数据后停止搜索,而不是继续往后查少下一条符合记录的数据

  4. 为搜索字段建索引

  5. 使用 ENUM 而不是 VARCHAR,如果你有一个字段,比如“性别”,“国家”,“民族”,“状态”或“部门”,你知道这些字段的取值是有限而且固定的,那么,你应该使用 ENUM 而不是VARCHAR。

  6. Prepared StatementsPrepared Statements很像存储过程,是一种运行在后台的SQL语句集合,我们可以从使用 prepared statements 获得很多好处,无论是性能问题还是安全问题。Prepared Statements 可以检查一些你绑定好的变量,这样可以保护你的程序不会受到“SQL注入式”攻击

  7. 垂直分表

  8. 选择正确的存储引擎

key和index的区别


  1. key 是数据库的物理结构,它包含两层意义和作用,一是约束(偏重于约束和规范数据库的结构完整性),二是索引(辅助查询用的)。包括primary key, unique key, foreign key 等

  2. index是数据库的物理结构,它只是辅助查询的,它创建时会在另外的表空间(mysql中的innodb表空间)以一个类似目录的结构存储。索引要分类的话,分为前缀索引、全文本索引等;

Mysql 中 MyISAM 和 InnoDB 的区别有哪些?


区别:

  1. InnoDB支持事务,MyISAM不支持,对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务;

  2. InnoDB支持外键,而MyISAM不支持。对一个包含外键的InnoDB表转为MYISAM会失败;

  3. InnoDB是聚集索引,数据文件是和索引绑在一起的,必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。而MyISAM是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。

  4. InnoDB不保存表的具体行数,执行select count(*) from table时需要全表扫描。而MyISAM用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快;

  5. Innodb不支持全文索引,而MyISAM支持全文索引,查询效率上MyISAM要高;

如何选择:

  1. 是否要支持事务,如果要请选择innodb,如果不需要可以考虑MyISAM;

  2. 如果表中绝大多数都只是读查询,可以考虑MyISAM,如果既有读写也挺频繁,请使用InnoDB。

  3. 系统奔溃后,MyISAM恢复起来更困难,能否接受;

  4. MySQL5.5版本开始Innodb已经成为Mysql的默认引擎(之前是MyISAM),说明其优势是有目共睹的,如果你不知道用什么,那就用InnoDB,至少不会差。

数据库表创建注意事项


一、字段名及字段配制合理性

  1. 剔除关系不密切的字段

  2. 字段命名要有规则及相对应的含义(不要一部分英文,一部分拼音,还有类似a.b.c这样不明含义的字段)

  3. 字段命名尽量不要使用缩写(大多数缩写都不能明确字段含义)

  4. 字段不要大小写混用(想要具有可读性,多个英文单词可使用下划线形式连接)

  5. 字段名不要使用保留字或者关键字

  6. 保持字段名和类型的一致性

  7. 慎重选择数字类型

  8. 给文本字段留足余量

二、系统特殊字段处理及建成后建议

  1. 添加删除标记(例如操作人、删除时间)

  2. 建立版本机制

三、表结构合理性配置

  1. 多型字段的处理,就是表中是否存在字段能够分解成更小独立的几部分(例如:人可以分为男人和女人)

  2. 多值字段的处理,可以将表分为三张表,这样使得检索和排序更加有调理,且保证数据的完整性!

四、其它建议

  1. 对于大数据字段,独立表进行存储,以便影响性能(例如:简介字段)

  2. 使用varchar类型代替char,因为varchar会动态分配长度,char指定长度是固定的。

  3. 给表创建主键,对于没有主键的表,在查询和索引定义上有一定的影响。

  4. 避免表字段运行为null,建议设置默认值(例如:int类型设置默认值为0)在索引查询上,效率立显!

  5. 建立索引,最好建立在唯一和非空的字段上,建立太多的索引对后期插入、更新都存在一定的影响(考虑实际情况来创建)。

redis


redis单线程问题


单线程指的是网络请求模块使用了一个线程(所以不需考虑并发安全性),即一个线程处理所有网络请求,其他模块仍用了多个线程。

为什么说redis能够快速执行


  1. 绝大部分请求是纯粹的内存操作(非常快速)

  2. 采用单线程,避免了不必要的上下文切换和竞争条件

  3. 非阻塞IO - IO多路复用

redis的内部实现


内部实现采用epoll,采用了epoll+自己实现的简单的事件框架。epoll中的读、写、关闭、连接都转化成了事件,然后利用epoll的多路复用特性,不在io上浪费一点时间 这3个条件不是相互独立的,特别是第一条,如果请求都是耗时的,采用单线程吞吐量及性能很差。redis为特殊的场景选择了合适的技术方案。

Redis关于线程安全问题


redis实际上是采用了线程封闭的观念,把任务封闭在一个线程,自然避免了线程安全问题,不过对于需要依赖多个redis操作的复合操作来说,依然需要锁,而且有可能是分布式锁。

使用redis有哪些好处?


  1. 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)

  2. 支持丰富数据类型,支持string,list,set,sorted set,hash

  3. 支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行

  4. 丰富的特性:可用于缓存,消息,按key设置过期时间,过期后将会自动删除

redis相比memcached有哪些优势?


  1. memcached所有的值均是简单的字符串,redis作为其替代者,支持更为丰富的数据类型

  2. redis的速度比memcached快很多

  3. redis可以持久化其数据

  4. Redis支持数据的备份,即master-slave模式的数据备份。

  5. 使用底层模型不同,它们之间底层实现方式 以及与客户端之间通信的应用协议不一样。Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。

  6. value大小:redis最大可以达到1GB,而memcache只有1MB

Redis主从复制


过程原理:

  1. 当从库和主库建立MS关系后,会向主数据库发送SYNC命令

  2. 主库接收到SYNC命令后会开始在后台保存快照(RDB持久化过程),并将期间接收到的写命令缓存起来

  3. 当快照完成后,主Redis会将快照文件和所有缓存的写命令发送给从Redis

  4. 从Redis接收到后,会载入快照文件并且执行收到的缓存的命令

  5. 之后,主Redis每当接收到写命令时就会将命令发送从Redis,从而保证数据的一致

缺点:所有的slave节点数据的复制和同步都由master节点来处理,会照成master节点压力太大,使用主从从结构来解决

redis两种持久化方式的优缺点


  1. RDB 持久化可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot)

  2. AOF 持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。

  3. Redis 还可以同时使用 AOF 持久化和 RDB 持久化。当redis重启时,它会有限使用AOF文件来还原数据集,因为AOF文件保存的数据集通常比RDB文件所保存的数据集更加完整

RDB的优点:

  1. RDB 是一个非常紧凑(compact)的文件,它保存了 Redis 在某个时间点上的数据集。 这种文件非常适合用于进行备份: 比如说,你可以在最近的 24 小时内,每小时备份一次 RDB 文件,并且在每个月的每一天,也备份一个 RDB 文件。 这样的话,即使遇上问题,也可以随时将数据集还原到不同的版本。

  2. RDB 非常适用于灾难恢复(disaster recovery):它只有一个文件,并且内容都非常紧凑,可以(在加密后)将它传送到别的数据中心,或者亚马逊 S3 中。

  3. RDB 可以最大化 Redis 的性能:父进程在保存 RDB 文件时唯一要做的就是 fork 出一个子进程,然后这个子进程就会处理接下来的所有保存工作,父进程无须执行任何磁盘 I/O 操作。

  4. RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快

Redis 常见的性能问题都有哪些?如何解决?


  1. Master写内存快照,save命令调度rdbSave函数,会阻塞主线程的工作,当快照比较大时对性能影响是非常大的,会间断性暂停服务,所以Master最好不要写内存快照。

  2. Master AOF持久化,如果不重写AOF文件,这个持久化方式对性能的影响是最小的,但是AOF文件会不断增大,AOF文件过大会影响Master重启的恢复速度。Master最好不要做任何持久化工作,包括内存快照和AOF日志文件,特别是不要启用内存快照做持久化,如果数据比较关键,某个Slave开启AOF备份数据,策略为每秒同步一次。

  3. Master调用BGREWRITEAOF重写AOF文件,AOF在重写的时候会占大量的CPU和内存资源,导致服务load过高,出现短暂服务暂停现象。

  4. Redis主从复制的性能问题,为了主从复制的速度和连接的稳定性,Slave和Master最好在同一个局域网内

redis 提供 6种数据淘汰策略


  1. volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰

  2. volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰

  3. volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰

  4. allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰

  5. allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰

  6. no-enviction(驱逐):禁止驱逐数据

我有一个微信公众号,经常会分享一些Java技术相关的干货;如果你喜欢我的分享,可以用微信搜索“Java团长”或者“javatuanzhang”关注。

Docker步步实践

目录文档:

①Docker简介

②基本概念

③安装Docker

④使用镜像:

⑤操作容器:

⑥访问仓库:

⑦数据管理:

⑧使用网络:

⑨高级网络配置:

⑩安全:

⑪底层实现:

⑫其他项目:

NZLa-1628214624253)]

④使用镜像:

[外链图片转存中…(img-MENcuj57-1628214624255)]

⑤操作容器:

[外链图片转存中…(img-OIlRBFac-1628214624257)]

⑥访问仓库:

[外链图片转存中…(img-CBTYyj2N-1628214624258)]

⑦数据管理:

[外链图片转存中…(img-iOYnutgi-1628214624259)]

⑧使用网络:

[外链图片转存中…(img-E8USk7qF-1628214624260)]

⑨高级网络配置:

[外链图片转存中…(img-Ja7aBPm8-1628214624261)]

⑩安全:

[外链图片转存中…(img-jyAGosyZ-1628214624261)]

⑪底层实现:

[外链图片转存中…(img-oDXhiDol-1628214624262)]

⑫其他项目:

[外链图片转存中…(img-gUkw3UYB-1628214624263)]

有需要完整版源码+笔记的朋友点击这里免费获取

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值