- 博客(79)
- 收藏
- 关注
原创 MySQL 日志:undo log、redo log、binlog 概述
undo log:记录的是逻辑日志,比如对某一行数据进行了 insert 操作,那么 undo log 就记录一条与之相反的 delete 操作;redo log:记录的是物理日志,记录了某个数据页做了什么修改,比如对 XXX 表空间中的 YYY 数据页 ZZZ 偏移量的地方做了AAA 更新;binlog:记录的是逻辑日志,记录内容是语句的原始逻辑,类似于 “给 ID=2 这一行的 c 字段加 1”;undo log:①用于事务的回滚,保证事务的原子性;②用于 MVCC,实现事务的隔离性;
2025-01-25 10:51:55
725
原创 简单工厂模式、工厂模式、抽象工厂模式、工厂方法模式
工厂模式提供了一种创建对象的方式,而无需指定要创建的具体类,这使得创建对象的过程与使用对象的过程实现了分离。一句话概括工厂模式简单工厂:一个具体工厂类,一个产品抽象类。普通工厂:多个具体工厂类,一个产品抽象类。抽象工厂:多个具体工厂类,多个产品抽象类。生活中的工厂模式简单工厂:一个鼠标工厂,只生产鼠标(可以是不同品牌)。普通工厂:多个不同品牌的鼠标工厂,只生产鼠标。抽象工厂:多个不同品牌的 PC 工厂,即可以生产鼠标、又可以生产键盘。简单工厂模式、普通工厂模式、抽象工厂模式的关联。
2025-01-25 10:51:20
819
原创 Java8 - flatMap() 介绍
在 Java8 中引入了 SteamAPI,其中有一个功能是 flatMap()。它的作用是将一个二维数组处理成一维数组,或者说是将一个 2 级 Stream 处理成 1 级 Stream。举例来说,下面的二维数组可以通过 flatMap() 处理成一维数组。这一过程也可以理解为将 2 级的流展平成了 1 级的流。从语法上来看,我们在 flatMap 中要写的是一个 lambda 表达式(或上图中的方法引用),而这个表达式要做的是将一维数组(比如 Integer[])转成流形式。更多的例子可以参考。
2025-01-24 20:52:25
289
原创 实时、准实时、离线事件
批式事件是指以固定时间间隔(如每日、每小时)处理和分析一批积累的事件数据。批处理对时效性的要求较低,更多用于离线分析、数据聚合或报表生成。准实时事件是指数据从产生到处理和反馈之间允许一定的延迟,通常为。内完成处理和反馈的业务事件。
2024-12-26 21:02:47
490
原创 MySQL 锁概述
InnoDB 的表级锁比较鸡肋,一般不会被用到,重点在于理解 InnoDB 的行级锁。悲观锁:悲观锁是一种思想,顾名思义,就是很悲观,对数据被其他事务的修改持保守态度,会通过数据库自身的锁机制来实现,从而保证数据操作的排它性。悲观锁总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会锁,这样别人再去操作这个数据时就会被阻塞直到它拿到锁(比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁,当其他线程想要访问数据时,都需要阻塞挂起。
2024-12-26 20:44:56
842
原创 InnoDB 事务并发问题
如果我们的一些业务场景不允许读取记录的旧版本,而是每次都必须去读取记录的最新版本,比方在银行存 款的事务中,你需要先把账户的余额读出来,然后将其加上本次存款的数额,最后再写到数据库中。在将账 户余额读取出来后,就不想让别的事务再访问该余额,直到本次存款事务执行完成,其他事务才可以访问账 户的余额。这样在读取记录的时候也就需要对其进行加锁操作,这样也就意味着读操作和写操作也像写-写操 作那样排队执行。所以在多个事务相继对同一条记录进行写操作的时候,需要让他们排队执行,这个过程是通过在内存中创建一个。
2024-12-26 20:42:40
255
原创 InnoDB 查询成本
与之对应的是「基于索引统计数据」来预估记录条数,一般是发生在使用 IN 进行范围查询,且 IN 里面的条件较多时。,然后再计算这两条记录之间有多少记录(记录条数少的时候可以做到精确计算,多的时候只能估算)。如果是走索引,则需要计算需要回表的记录数量,来计算 CPU 成本。记录数量的计算方式为:先获取索引对应的。表的成本常数,可以引导 MySQL 去生成倾向于全表扫描或倾向于搜索索引的执行计划。这里的扇出数实际上就是驱动表经过条件过滤后剩余的记录数。树来计算某个范围区间对应的索引记录条数的方式称之为。
2024-12-19 20:22:32
247
原创 谓词下推、逻辑优化、列剪枝
是数据库查询优化中的一种技术,它将查询中的(通常是WHERE子句、JOIN条件等)尽早地应用到或的过程中(这个过程即),以减少需要处理的数据量,从而提高查询效率。谓词下推的目标是通过在数据访问的早期阶段就过滤不必要的数据,避免从数据源加载大量不符合条件的行,最终减少 I/O 操作和提高性能。优化过程:如果表employees是一个大表,数据库优化器会将这个谓词推到扫描操作之前。优化后的执行计划会首先扫描employees表,并且只读取满足条件的行。优化器推导出查询不需要加载。
2024-12-15 19:49:50
1305
原创 精准率、准确率、召回率
(1)若一个实例是正类,但是被预测成为正类,即为真正类(True Postive TP)(2)若一个实例是负类,但是被预测成为负类,即为真负类(True Negative TN)(3)若一个实例是负类,但是被预测成为正类,即为假正类(False Postive FP)(4)若一个实例是正类,但是被预测成为负类,即为假负类(False Negative FN)
2024-12-15 19:10:03
430
原创 同步调用、异步调用、同步回调、异步回调
在这个例子里,你的电话号码就叫回调函数,你把电话留给店员就叫登记回调函数,店里后来有货了叫做触发了回调关联的事件,店员帮你买了叫做调用回调函数,送到了你家叫做响应回调事件。其实 3 中方法 b() 能调用方法 callback(),即可以是把类 A 的实例对象传给方法 b(),也可以是把 callback() 方法传给 b()。在方法 a() 中调用方法 b(),方法 b() 中又回过来调用 A 类中的方法 callback()。这里的 funB(),就被称为回调函数。可见,异步调用的好处是:不阻塞线程。
2024-12-15 19:05:21
314
原创 唯一索引、普通索引的使用场景
对于需要频繁更新的字段,建议用普通索引,因为他能通过使用来提升更新表的性能。此外,如果所有的更新后面,都马上伴随着对这个记录的查询 ,那么你应该关闭。如果数据需要保证唯一性,但业务无法保证,即需要数据库来保证唯一性。那为了业务的正确性,就必须要用唯一索引。对于联表查询的情况,可以考虑将被驱动表的连接字段设置为唯一索引,因为 InnoDB 在选择执行计划前会去计算成本,而唯一索引的成本一般被认为是更低的,那生成的执行计划就会更加偏向于走索引。
2024-12-09 21:23:20
483
原创 MySQL覆盖索引
覆盖索引一般是针对二级索引而言的,我们知道二级索引的叶子节点存储了索引列 + 主键 id的信息。当叶子节点包含了满足查询结果的所有数据,那么这个二级索引就被称为覆盖索引。此时,不再需要回表去查询其他列的信息,因此性能较高。key2 INT,-- 由于联合索引 idx_key_part 包含了 key_part1, key_part2 的完整记录,因此不需要回表。我们称它为覆盖索引。
2024-12-09 20:56:50
303
原创 ON和WHERE有何不同?
在这个例子中,ON 子句用于指定连接条件,并且立即应用这个条件。结果集将包含所有学生,无论他们是否选修了数学课。下面通过两个例子来说明,这两个例子将展示不同的结果集。时,对应的学生记录才会被包含在结果集中。因此,结果集将只包含那些选修了数学课的学生,未选修数学课的学生不会出现在结果集中。如果上面使用的是内连接(Inner Join),那结果就是一致的了。未选修数学课的学生也会出现在结果集中,只是对应的。现在,我们使用相同的表,但是这次我们将选课条件放在。子句用于过滤连接后的结果集。
2024-12-04 21:28:28
209
原创 关联查询的本质、为何要小表驱动大表?
首先,我们创建两个表t1和t2,这两个表都有一个主键索引 id 和一个索引 a,字段 b 上无索引。存储过程 idata() 往表t2里插入了 1000 行数据,在表t1里插入的是 100 行数据。delimiter;;set i=i+1;end while;end;;delimiter;对于下面的 SQL 语句,由于t2表只需要取前 50 行,因此认为t2为小表。在下面的例子中,表t1和t2都是只有 100 行参加join,但是表t1。
2024-12-04 21:26:55
1206
原创 查询优化:索引下推
如果开发者理解索引条件下推的原理,就可以主动引导优化器选择走索引的访问方法(当然了,走索引快还是不走索引快,得经过实测)。我们可以发现,ICP 通过用联合索引中的多个列作为过滤条件,减少了需要回表的记录数,减少了返回给 server 层的记录数,从而优化了查询效率。将回表得到的完整记录返回给 server 层,并在 server 层按其他条件做进一步过滤。的一种优化方式,可以减少在存储引擎层回表的次数,减少返回给 server 层的数据量。作为过滤条件,在联合索引树中找到符合条件的记录。
2024-12-01 19:02:20
554
原创 数据库范式
遵守数据库范式可以帮我们减少数据冗余、更好地保证数据一致性。目前关系型数据库有六种常见范式,按照范式级别,从低到高分别是:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。高级别的范式一定遵守低级别的范式,比如满足 3NF 的表一定满足 1NF 和 2NF。越高级别的范式代表更少的冗余,也往往对应着更多的联表查询,因此一般我们遵守到 3NF 即可。且为了提升数据查询的效率,可以考虑使用反范式化。
2024-12-01 18:59:27
841
原创 MySQL 子查询
具体实现方式是:在 SQL 执行过程中,第一次需要子查询结果时执行子查询并将子查询的结果保存为临时表(一般情况下优化器就会帮我们做这件事) ,后续对子查询结果集的访问将直接通过临时表获得。假设我们有一个学生表 student 和班级表 class,学生表记录了学生的学号 stu_no,而班级表记录了班级信息以及每个班级的班长的学号 monitor_no。此时,整个查询的执行逻辑不再是像我们想象的一样:先执行子查询获取到一个小的结果集,然后以这个小结果集在 g1 中作为过滤条件去过滤。
2024-11-24 18:42:13
612
原创 索引使用原则、索引失效
虽然索引能带来查询上的效率,但是维护索引的成本也是不小的。如果一个字段不被经常查询,反而被经常修改,那么就更不应该在这种字段上建立索引了。因为索引是需要占用磁盘空间的,可以简单理解为每个索引都对应着一颗 B+树。如果一个表的字段过多,索引过多,那么当这个表的数据达到一个体量后,索引占用的空间也是很多的,且修改索引时,耗费的时间也是较多的。如果是联合索引,多个字段在一个索引上,那么将会节约很大磁盘空间,且修改数据的操作效率也会提升。此外,使用多列索引时,选择性强(字段的重复值越低,选择性越强)的放左边。。
2024-11-18 22:44:56
765
原创 cron表达式
在不同系统或框架下,月或星期的取值范围可能不同。比如月可能是取 0-11,也可能是 1-12。为此可以通过月或星期的简写来表示。星期可能是取 0-6,也可能是 1-7。此外,为了方便使用。来指定月的最后一天,通过。
2024-10-07 17:39:54
553
原创 SQL语句执行顺序
一般情况下 SQL 执行的优先级从高到低依次是:1.from2.on3.join4.where5.group by6.聚合函数7.having8.select9.distinct11.limit。
2024-10-01 17:24:23
159
原创 MVCC 详解
一个事务对某条记录进行读操作时,会查看这一条记录的一系列事务 id(由 undo log 构成的版本链中的事务 id),并根据事务的隔离级别(“读已提交”、“可重复读”)去选择生成 Read View 的方式,通过比较事务 id 来确定可见的版本。下图记录了某一行数据的变更过程,图中虚线框里是同一行数据的 4 个版本,当前最新版本是 V4,k 的值是 22,它是被 transaction id 为 25 的事务更新的,因此它的 row trx_id 也是 25。用来存储“活跃”的事务的 id。
2024-08-19 21:27:21
1328
原创 全局锁、表级锁、行级锁
WHY:锁的出现是为了解决并发场景下不同用户同时对共享资源进行操作,而可能引发的并发问题。HOW:控制不同线程对资源访问的规则。
2024-08-19 20:51:26
625
原创 基于 Mockito 框架的 Mock 单元测试
Mock 通常是指,在测试一个对象 A 时,我们构造一些假的对象(一般是不容易构造或者不容易获取的对象,比如测试类所依赖的实现类、第三方接口、数据库操作对象)来模拟与 A 之间的交互,这些对象被称为 Mock 对象,而 Mock 对象的行为是我们事先设定且符合预期。通过这些 Mock 对象来测试 A 在正常逻辑,异常逻辑或压力情况下工作是否正常。
2024-07-20 22:07:46
913
原创 Spring Boot 单元测试什么时候需要添加 @RunWith
在高版本的 Spring Boot 中,一般默认用的是 JUnit5。此时通过添加 @SpringBootTest 注解,即可成功注入相关的 bean 对象,并进行测试。如果使用的是 JUnit4,则需要额外添加 @Runwith(SpringRunner.class) 注解,用于声明测试的环境为 Spring环境。建立 Spring Boot 单元测试方法一般依赖于 JUnit4 或 JUnit5 框架。
2024-07-20 21:38:28
501
4
原创 StreamAPI 的 Collectors.toMap 方法
由于最终返回的是一个 Map 对象,因此我们需要在 Collectors.toMap() 方法中定义 key、value 的映射关系。(v1, v2) -> v1 表示:如果 key 值相同,则采用前一个 key 对应的 value 值作为最终的 value 值。k -> k.getId() 表示:采用 person 对象的 id 指作为 key 值。v -> v 表示:采用原来的 person 对象作为 value 值。
2024-01-21 12:20:57
514
原创 一个方法重写的小案例
可以发现,虽然子类的 age() 方法的实现是调用了父类 age() 方法,但 say() 方法实际上调用的还是子类重写后的 say()。发现输出结果仍旧是一样的,这说明这里的 this,所指的对象仍旧是子类对象 son,因此调用的还是子类重写后的 say() 方法。此时 this 指代的是父类对象。
2023-11-29 23:13:17
203
原创 map 和 flatMap 的区别
StreamAPI 中的 map 方法,实现是一种映射关系。类似数学中的 x -> f(x)。而 flatMap 方法是在 map 的基础上做了一次 flat。
2023-11-28 22:48:43
394
原创 开发、测试、生产环境
开发环境:开发环境是程序猿们专门用于开发的服务器,配置可以比较随意, 为了开发调试方便,一般打开全部错误报告。简单讲就是项目尚且处于编码阶段,一般这时候会把代码放在开发环境中,不会放在生产环境中。生产环境:是指正式提供对外服务的,一般会关掉错误报告,打开错误日志。简单讲就是所谓的线上,就是正式给用户使用的环境。测试环境:是开发环境到生产环境的一个过渡,配置会参考生产环境,用于测试程序是否有错误,力求在将代码部署到生产环境前对所有问题进行排查解决。
2023-11-26 22:34:36
224
原创 如何使用 arrayList.removeAll(Collection<?> c)?
如果原集合对象的元素数量 < c 中元素数量,那么调用原集合对象的迭代器去遍历原集合,检查元素是否包含在 c 中,并调用原集合迭代器的。如果原集合对象的元素数量 > c 中元素数量,那么调用 c 的代器去遍历 c ,查看元素是否包含在原集合中,并使用原集合的。方法,该方法是通过哈希计算的方式去查询的,因此速度十分快。中存在的所有元素的总体时间复杂度为 O( n * m )。方法来判断是否存在相同的元素,效率与 c 的类型有关。中存在的所有元素的总体时间复杂度为 O( n )。方法的时间复杂度为 O(1)。
2023-10-12 23:09:19
381
原创 @PathVariable、@RequestParam、@RequestBody、@ResponseBody、RequestEntity、ResponseEntity
上面这个接口可通过 get 请求 http://xxxxx/1111 来得到想要的数据,1111 既是 getUser 的方法参数又是。修饰的参数最后通过 key=value 的形式放在http请求的Body传过来,对比下上面的。注解是标识在整个控制器方法上面的。格式的数据,接收到数据之后会自动将数据绑定到 Java 对象上去。将请求的 body 中的 json 字符串转换为 java 对象。这样我们的后端就可以直接把 json 格式的数据映射到我们的。用于封装整个请求报文,包括请求体、请求头、请求行。
2023-10-08 23:51:03
176
原创 Bean注入方式:@Autowired、@Resource的区别
这种方式就无法正确注入对象了,因为这个时候 Spring 会同时找到多个满足条件的选择,默认情况下它自己不知道选择哪一个。(根据类型进行匹配),也就是说会优先根据接口类型去匹配并注入 Bean (接口的实现类)。(根据名称进行匹配),这个名称通常就是类名(首字母小写)。如果无法通过名称匹配到对应的 Bean 的话,注入方式会变为。属于 Spring 内置的注解,默认的注入方式为。属于 JDK 提供的注解,默认注入方式为。属性(不建议这么做)则注入方式为。这种情况下,注入方式会变为。就是我这里所说的名称。
2023-10-08 22:52:24
310
druid 和 druid-spring-boot-starter 1.1.13 版本和 1.2.8 版本的 jar 包
2023-06-24
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人