读Java性能权威指南(第2版)笔记06_数据库性能JPA&SpringData
Posted lying7
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了读Java性能权威指南(第2版)笔记06_数据库性能JPA&SpringData相关的知识,希望对你有一定的参考价值。
1. JPA
1.1. 性能直接受底层JDBC驱动性能的影响
1.2. 性能提升是通过改变实体类的字节码来实现的
1.2.1. 在类加载到JAR文件或者由JVM运行之前增强字节码的方法
1.2.1.1. 在编译过程中完成的
1.2.1.2. 在实体类编译完成后,它们会被传递给一个特定实现的后置处理器
1.2.1.3. 该后置处理器会“增强”字节码,产生一个修改过的类文件,其中包含所需的优化
1.2.2. 在类被加载到JVM时动态增强字节码的方法
1.2.2.1. 在JVM中运行一个代理,当类被加载时,代理会收到通知并介入类加载的过程,在字节码定义类之前对其进行修改
1.2.2.2. 代理是在应用程序的命令行上指定的
2. 优化JPA写
2.1. 写入更少的字段
2.2. 可以从限制数据库的写入调用数量中获益
2.3. 语句池可以在JPA层面或JDBC层面实现
2.3.1. 应该首先尝试在JDBC层面实现
2.3.2. 如果JDBC驱动能够提供语句池,通常最好在驱动中启用语句池,并将从JPA的配置中删除语句池配置
2.4. JDBC驱动不能自动实现语句批处理
2.4.1. 设置size属性
2.4.2. JPA的批量更新可以用声明的方式在persistence.xml文件中完成
2.4.3. 应用程序可以定期调用实体管理器的flush()方法,这个调用会立即执行所有需要批量处理的语句
3. 优化JPA读
3.1. 读取更少的数据
3.1.1. 因为有些数据不需要
3.1.2. 目的
3.1.2.1. 在检索实体时可以让SQL更快
3.1.2.2. 可以节省大量内存,从而减少了GC压力
3.1.3. 指定需要延迟加载的相关字段
3.1.3.1. 当一个实体被检索时,带有延迟加载注解的字段将被排除在用于加载数据的SQL之外
3.1.3.2. 对于基本类型的简单列,很少使用
3.1.3.3. 基于BLOB或基于CLOB的大型对象考虑使用
3.1.3.4. 延迟加载注解最终只是对JPA实现的建议
3.1.3.4.1. JPA实现可以自由决定数据库是否立即提供该数据
3.2. 一次读取更多的数据
3.2.1. 因为将来肯定需要这些数据
3.3. 提取组(fetch group)
3.3.1. 非标准JPA
3.3.2. 可以将某些延迟加载字段指定为一组,在其中一个字段被访问时,整个组都会被加载
3.3.3. 多个独立的字段组,每个组会在需要时被加载
3.4. 立即提取(eager fetching)
3.4.1. 当获取一个实体时,其他相关实体的数据也应该被返回
3.5. 在查询中使用JOIN
3.5.1. 特殊的@JoinFetch注解,它也可以用于连接提取关系
3.5.2. 选择立即加载关系时,可以使用命名查询来发出一条使用JOIN的SQL语句
3.6. 处理结果集
3.6.1. 一次获取所有结果
3.6.2. 在程序遍历查询结果时一次获取一个结果
3.6.3. 一次获取几个结果
3.7. 命名查询的速度更快
3.7.1. JPA实现几乎总是使用带有绑定参数的预处理语句,同时利用语句缓存池
4. JPA缓存
4.1. 提供一个中间层来缓存后端数据库返回的数据
4.1.1. 缓存频繁使用的数据可以大幅缩短客户端的响应时间
4.1.2. JPA缓存只对通过主键访问的实体进行操作
4.2. 一级缓存
4.2.1. L1缓存
4.2.2. 实体管理器中的本地缓存
4.2.3. 几乎不需要优化
4.2.4. 在所有JPA实现中都是开启的
4.3. 二级缓存
4.3.1. L2缓存
4.3.2. 全局缓存
4.3.3. 在所有的实体管理器之间共享的
4.3.4. 不是所有的JPA实现都会默认开启它
4.3.5. L2缓存会自动为应用程序缓存实体
4.3.6. 当有很大的JPA L2缓存时,堆的优化对于良好的性能就相当重要了
4.4. 通过查询检索到的数据不会保存在L2缓存中
4.4.1. 即使JPA实现支持查询缓存,实体本身也不会存储在L2缓存中,也不能在随后调用find()方法时被返回
4.4.2. 只有在每次执行查询时,查询中使用的参数完全相同的情况下,查询缓存才会起作用
4.4.3. 除非正在使用的JPA实现支持查询缓存,否则使用JOIN查询经常会对性能造成负面影响,因为它没有利用L2缓存
4.4.4. 从长远来看,避免查询是有益的
4.5. 当所有的数据都被使用时,立即加载和延迟加载的性能基本相同
4.6. 当关系数据没有被实际使用时,延迟加载会节省一些时间
4.6.1. 特别是在循环第一次执行时
4.6.2. 循环的后续执行并不会节省时间
4.6.2.1. 在这些后续的迭代中,立即加载的代码并没有重新加载数据,它是从L2缓存中查找的数据
4.7. 如果实体都不是通过查询检索到的,那么在初始的预热期之后,通过L2缓存可以访问所有的实体
4.7.1. 即使SQL语句返回多行数据,JPA仍然能够缓存实体,这和执行查询不同
4.7.2. 如果通过遍历实体来预热L2缓存,不要单独遍历相关实体,通过访问关系来遍历更简单
4.8. 如果缓存消耗了太多内存,就会给GC造成压力
4.8.1. 设置缓存大小的选项
4.8.1.1. 针对全局的
4.8.1.2. 针对每个实体的
4.8.2. 另一种可用方法是让L2缓存使用软引用或/和弱引用
4.8.2.1. 比为每个实体找到最佳大小要容易一些
4.8.2.2. 弱引用在任何GC操作中都会被回收
5. Spring Data
5.1. 关系数据库和NoSQL数据库的数据库访问模块集合
6. Spring Data JDBC
6.1. JPA的一个简单替代方案
6.2. 提供了类似于JPA的实体映射
6.3. 没有缓存、延迟加载或脏实体跟踪等功
7. Spring Data JPA
7.1. 标准JPA的包装器
7.2. 减少开发人员需要编写的模板代码量
7.2.1. 提高开发人员的效率
7.2.2. 并不能真正影响应用程序性能
8. Spring Data for NoSQL
8.1. 各种NoSQL和类NoSQL技术的连接器
8.2. MongoDB
8.3. Cassandra
8.4. Couchbase
8.5. Redis
9. Spring Data R2DBC
9.1. 允许对Postgres、H2和Microsoft SQL Server数据库进行异步访问
9.2. 遵循典型的Spring Data编程模型
9.3. 不是直接使用JDBC
9.4. 和Spring Data JDBC类似
9.5. 通过仓库中的简单实体进行访问
9.6. 没有缓存、延迟加载和JPA的其他功能
以上是关于读Java性能权威指南(第2版)笔记06_数据库性能JPA&SpringData的主要内容,如果未能解决你的问题,请参考以下文章