高性能 Java 持久化的 14 个技巧

一个高性能的数据访问层需要大量关于数据库内部、JDBC、JPA、Hibernate的知识,本文总结了一些可用来优化企业应用程序的重要的技术。

1. SQL语句日志

如果您用了生成符合自己使用习惯的语句的框架,则应始终验证每个语句的有效性和效率。测试时使用断言机制验证更好,因为即使在提交代码之前,也可以捕获N + 1个查询问题。

2.连接管理

数据库的连接开销非常大,因此您应该始终使用连接池机制。

由于连接数由底层数据库集群的功能给出,所以您需要尽可能快地释放连接。

在性能调优中,你总是要测量、设置出正确的连接池,池的大小又是差不多的。 但像FlexyPool这样工具可以帮助您找到合适的大小,即使您已经将应用程序部署到生产环境中。

3.JDBC批处理

JDBC批处理允许我们在单个数据库往返中发送多个SQL语句。性能增益在驱动程序和数据库端都很重要。PreparedStatements 非常适合批处理,而某些数据库系统(例如 Oracle)仅支持用于预处理语句的批处理。

由于JDBC为批处理定义了独特的API(例如PreparedStatement.addBatch和PreparedStatement.executeBatch),如果您手动生成语句,那么您应该从一开始就知道是否应该使用批处理。 使用Hibernate,您可以切换到使用单个配置的批处理。

Hibernate 5.2 提供了会话级别的批处理,所以在这方面更加灵活。

4.语句缓存

语句缓存是您可以轻松利用的最鲜为人知的性能优化之一。 根据基础的JDBC驱动程序,可以在客户端(驱动程序)或数据库端(语法树甚至执行计划)上缓存PreparedStatements。

5.Hibernate 标识符

当使用Hibernate时,IDENTITY生成器不是一个好的选择,因为它禁用了JDBC批处理。

TABLE生成器更糟糕,因为它使用一个单独的事务来获取新的标识符,这会对底层事务日志以及连接池造成压力,因为每次我们需要一个新的标识符时都需要单独的连接。

SEQUENCE是正确的选择,甚至从2012版本就开始支持SQL Server。对于SEQUENCE标识符,Hibernate一直提供优化器,如pooled 或 pooled-lo,这可以减少获取新的实体标识符值所需的数据库往返次数。

6.选择正确的列类型

您应该始终在数据库端使用正确的列类型。 列类型越紧凑,数据库工作集中可容纳的条目越多,索引将更好地适应于内存。 为此,您应该利用特定于数据库的类型(例如PostgreSQL中的IPv4地址的inet),尤其是在实现新自定义类型时,Hibernate非常灵活。

7 .关系

Hibernate 带有许多关系映射类型,但并不是所有的关系映射类型在效率上都是相等的。

应该避免单向集合和@ManyToMany列表。如果您确实需要使用实体集合,则首选双向 @OneToMany关联。对于@ManyToMany关系,使用 Set(s),因为在这种情况下它们更高效,或者简单地映射链接的多对多表,并将@ManyToMany关系转换为两个双向的 @OneToMany 关联。

然而,与查询不同,集合不够灵活,因为它们不易分页,这意味着当子关联的数量相当高时,我们不能使用它们。出于这个原因,你应该考虑一个集合是否真的有必要。 在许多情况下,实体查询可能是更好的选择。

8.继承

就继承而言,面向对象语言和关系数据库之间的不匹配变得更加明显。 JPA提供了SINGLE_TABLE,JOINED和TABLE_PER_CLASS来处理继承映射,每个策略都有其优缺点。

SINGLE_TABLE在SQL语句方面表现最好,但由于我们不能使用NOT NULL约束,所以我们在数据完整性方面失败了。

当同时提供更复杂的语句时,JOINED采用数据完整性限制。 只要你不使用基本类型的多态查询或@OneToMany关联,这个策略就没有问题。 它的真正的作用在于对数据访问层上由策略模式支持的多态@ManyToOne关联。

应该避免使用TABLE_PER_CLASS,因为它不会生成有效的SQL语句。

9.持久性上下文的大小

在使用 JPA 和 Hibernate 时,应该始终关注持久性上下文的大小。 出于这个原因,您不应该过多地使用托管实体。 通过限制托管实体的数量,我们可以获得更好的内存管理,并且默认的检查机制也将更加高效。

10.只抓取必要的东西

获取太多的数据可能是导致数据访问层性能出问题的首要原因。 一个问题是,即使是只读的 Projections,实体查询也是专用的。

DTO projections更适合于获取自定义视图,而实体只能在业务流需要修改时才能获取。

EAGER抓取是最糟糕的,您应该避免反模式(Anti-Pattern),例如Open-Session in View

11.高速缓存

关系数据库系统使用许多内存缓冲区结构来避免磁盘访问。 数据库缓存经常被忽视。 我们可以通过适当调整数据库引擎来显着降低响应时间,以便工作集驻留在内存中,而不是一直从磁盘中获取。

应用程序级缓存对于许多企业应用程序来说是不可选的。 应用程序级缓存可以减少响应时间,同时为数据库关闭以进行维护或由于某些严重系统故障提供只读辅助存储库。

二级缓存对于减少读写事务响应时间非常有用,特别是在主从复制体系结构中。 根据应用程序的要求,Hibernate允许你在READ_ONLYNONSTRICT_READ_WRITEREAD_WRITETRANSACTIONAL之间进行选择。

12.并发控制

在性能和数据完整性方面,事务隔离级别的选择是非常重要的。 对于多请求Web流程,为避免丢失更新,您应该对分离的实体或 EXTENDED 持久性上下文使用optimistic锁定。

为避免optimistic locking误报,您可以使用无版本optimistic并发控制或基于读写的属性集来拆分实体。

13.释放数据库查询功能

仅仅因为您使用JPA或Hibernate,并不意味着您不应该使用原生查询。 您应该利用窗口函数,CTE(公用表表达式),CONNECT BY,PIVOT 查询。

这些构造允许您避免获取太多的数据,以便稍后在应用程序层进行转换。 如果可以让数据库进行处理,那么只能获取最终结果,因此可以节省大量的磁盘I / O和网络开销。 为避免主节点重载,可以使用数据库复制和拥有多个从属节点,这样数据密集型的任务就会在从属节点而不是主节点上执行。

14.横向扩展和纵向扩展

关系数据库的伸缩性非常好。如果Facebook、Twitter、Pinterest或StackOverflow可以扩展他们的数据库系统,那么很有可能您可以将企业应用程序扩展到其特定的业务需求。

数据库复制和分片是提高吞吐量的很好的方法,您应该完全可以利用这些经过测试的架构模式来扩展您的企业应用程序。

结论

高性能数据访问层必须与底层数据库系统互相响应。 了解关系数据库和正在使用的数据访问框架的内部工作原理可以使企业高性能应用程序和几乎没有crawls的应用程序之间产生差异。

原文:https://vladmihalcea.com/2016/06/28/14-high-performance-java-persistence-tips/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,905评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,140评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,791评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,483评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,476评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,516评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,905评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,560评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,778评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,557评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,635评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,338评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,925评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,898评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,142评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,818评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,347评论 2 342

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,559评论 18 399
  • 一. Java基础部分.................................................
    wy_sure阅读 3,785评论 0 11
  • 不少女孩子的一生都在追求减肥,因为都想不用考虑尺码就能买买买,面对镜头也不怕自拍站在最前面。但是很多人即使不胖,穿...
    赫美生活阅读 392评论 0 1