阅读更多

1顶
0踩

编程语言

转载新闻 构建高性能Java持久层的14个建议

2016-07-06 10:07 by 副主编 mengyidan1988 评论(3) 有11038人浏览
引用

Introduction
一个高性能的数据访问层需要很多关于数据库的内部结构、JDBC、JPA、Hibernate以及很多优化商业应用的技术建议。

SQL Statement Logging:SQL语句日志
如果你正在使用譬如Hibernate或者MyBatis这样的ORM框架,那么可以参考验证执行语句的效率。另外推荐一个测试中断言机制可以帮你在提交代码之前就发现很多的查询问题。
Connection management:连接管理
数据库连接一直是数据库中比较耗时的操作,因此建议是务必使用数据库连接池 机制。另外,数据库连接还受到数据库底层的限制,因此也需要合理有效地释放无用的数据库连接。在性能调优中,我们经常需要测试并且设置合理的连接池大小。这里推荐一个FlexyPool工具可以帮助你选择生产环境下合适的连接池大小。

JDBC Batching:批量JDBC操作
JDBC Batching允许在单次数据库连接中发送多个SQL语句。这篇博客里进行了对比可以看出Batch操作的性能提升非常巨大 ,无论是在客户端还是数据库端。 PreparedStatements 是不错的用于Batching操作的选择,像Oracle也仅支持基于PreparedStatements的Batching操作。

JDBC中已经基于PreparedStataement.addBatch 与 PreparedStataement.executeBatch)提供了Batching操作的辅助,不过如果打算手动的构造Batching操作,那么在设计阶段就要考虑到是否需要引入Batching。如果你用的是Hibernate,那么可以用简单的配置就开启Batching,Hibernate 5.2 提供了 Session级别的Batching, 也是非常方便的。

Statement Caching:语句缓存
Statement Caching算是最不常用的几种优化手段之一了,你可以利用PreparedStatements同时在客户端(Driver)或者数据库端同时缓存语句。

Hibernate Identifiers
如果你是使用Hibernate作为ORM工具,那么IDENTITY生成器可能会影响到你的性能,因为它会禁止掉JDBC Batching。Table生成器也不是啥好选择,它会使用独立的事务上下文进行捕获操作,而导致底层的事务日志承受额外的压力,并且导致了每次连接池中的新的请求都需要一个新的Identifier。因此笔者还是推荐SEQUENCE生成器,SQL Server在2012版本之后也开始支持了该生成器。

选择合适的列类型
在数据库设计的时候,我们应该尽可能地选用合适的列类型,这样可以让你的数据库以最合适的方式去索引存储你的数据。譬如在PostgreSQL中你应该使用inet来存放IPv4的地址,特别是Hibernate还允许你自定义数据类型,这样方面和数据库中的列类型一一对应。

Relationships:映射关联
Hibernate提供了很多的关系映射,不过并不是所有的映射都是性能优化的。



我们在开发的过程中需要注意避免单向的关系映射,以及@ManyToMany这种映射。对于集合查询而言,双向的@OneToMany关系才是值得推荐的。

Inheritance:继承
继承是面向对象的语言中的不可或缺的一部分,但这也是关系型数据库与面向对象的语言之间的不协调最甚的地方。JPA提供了譬如SINGLE_TABLE、JOIN以及TABLE_PER_CLASS来处理继承映射的问题,而这几个办法都是各有千秋。
  • SINGLE_TABLE在SQL语句中的表现最好,不过不能使用NOT NULL约束,数据完整性的控制较差。
  • JOIN 通过更复杂的语句控制来保证了数据的完整性,只要你不使用多态查询或者@OneToMany关系注解,那一切还好。
  • 应该避免使用TABLE_PER_CLASS,它基本上无法生成高效的SQL语句。

Persistence Context Size:持久化上下文的大小
在使用JPA或者Hibernate时候,应该随时注意持久化上下文的大小,避免同时管理过多的实体类。通过限制受管实体类的数量,我们可以更好地进行内存管理,而默认的脏检测机制也会有更好的效果。

只获取必要的数据
获取过多的冗余数据可能是导致数据访问层性能下降的原因之一,即使是包含了投影等操作,对于实体的查询应该也是排外的,即不会引入冗余数据的。我们应该只获取那些业务逻辑需要到的数据,这里推荐使用DTO Projections。过早的数据获取以及Open Session In View这种反模式都是要被避免的。

Caching:缓存



关系型数据库使用了很多的内存缓冲结构体来避免大量的磁盘访问,但是我们往往忽略了数据库缓存。我们可以通过调整数据库查询引擎,将更多的内容留于内存中以避免磁盘查询最终明显的减少响应耗时。应用层的缓存则利用高速副本的方式来保证低响应时间。而Second-Level缓存能够有效减少读写事务的响应时间,特别是在主从复制架构中。根据不同的应用取钱,Hibernate提供了 READ_ONLY, NONSTRICT_READ_WRITE, READ_WRITE, 以及 TRANSACTIONAL这几种方式。

Concurrency Control:并发控制
在考虑性能和数据完整性的时候,事务隔离层 就变得至关重要。对于并发较高的应用,需要避免更新失败, 可以使用 乐观锁或者扩展的持久化上下文.

而为了避免 乐观锁中的 false positives, 可以使用无版本的乐观控制或者基于写属性集的实体划分

提高数据库查询能力
虽然你是用了JPA或者Hibernate,但是你可以用一些原生查询,建议是好好利用Window Functions, CTE (Common Table Expressions), CONNECT BY, PIVOT等等。这些工具能够避免你一次性传输过多的数据进入应用层,如果你可以把这个操作托付给数据库层进行,那么可以仅关心最终的结果,从而节约了磁盘IO与网络带宽。

集群扩展
关系型数据库能够方便地进行扩展,像Facebook、Twitter、Pinterest这些大公司都扩展了数据库系统:



数据副本与分片是两种常用的增加吞吐量的扩展方式,你应该合理的组合应用这些方式从而提高你的商业应用的能力。
  • 大小: 132.6 KB
  • 大小: 154.9 KB
  • 大小: 128.7 KB
1
0
评论 共 3 条 请登录后发表评论
3 楼 diferent 2016-07-07 10:45
afeifqh 写道
liu4187915336 写道
文章很不错,大部分都用到过;这里想问下,项目orm用的hibernate,在services层用redis做了缓存数据库,那么还有必要实现hibernate的二级缓存吗?

有必要。这样更能减轻数据库压力。。

如果Cache的Key在一致性上没有问题,多服务之间共享也没有问题.可以不需要二级缓存.两者互斥,Services层缓存应用更广
2 楼 afeifqh 2016-07-07 09:39
liu4187915336 写道
文章很不错,大部分都用到过;这里想问下,项目orm用的hibernate,在services层用redis做了缓存数据库,那么还有必要实现hibernate的二级缓存吗?

有必要。这样更能减轻数据库压力。。
1 楼 liu4187915336 2016-07-06 17:12
文章很不错,大部分都用到过;这里想问下,项目orm用的hibernate,在services层用redis做了缓存数据库,那么还有必要实现hibernate的二级缓存吗?

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • java源码包---java 源码 大量 实例

    14个目标文件 内容索引:JAVA源码,系统相关,日历,日期选择  Java语言开发的简洁实用的日期选择控件,源码文件功能说明:  [DateChooser.java] Java 日期选择控件(主体类) [public]  [TablePanel.java] 日历表格...

  • Java数据持久层框架

    JDBC是一个规范,其分为两个部分: 厂商:完成数据库驱动 Java开发者:调用统一接口 1.整体结构 对应组件: DriverManager:数据库驱动管理器 Driver:数据库驱动的抽象接口,用于与数据库服务进行通信 ...

  • java持久层框架分析

     目前在java应用程序开发中,使用广泛的,开源的持久层框架是Hibernate 和 Ibatis 。  ibatis和hibernate都是ORM解决方案,不同的是两者各有侧重。Hibernate提供了Java对象到数据库表之间的直接映射,开发者无需...

  • 01-Mybatis持久层框架快速入门(环境搭建、xml配置文件、注解)

    Mybatis 是一个优秀的基于 java 的持久层框架,它内部封装了 jdbc,使开发者只需要关注 sql 语句本身, 而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。mybatis 通过 xml 或注解的方式...

  • 10万字208道Java经典面试题总结(附答案)

    JDK中包含JRE,JDK中有一个名为jre的目录,里面包含两个文件夹bin和lib,bin就是JVM,lib就是JVM工作所需要的类库。 2、== 和 equals 的区别是什么? 对于基本类型,==比较的是值; 对于引用类型,==比较的是地址...

  • 构建互联网高性能WEB系统

    所以如何构建一个优秀的高性能、高可靠的应用系统对每一个开发者至关重要。本文将我所学到和在工作中使用到的一些方法归纳总结,希望给其他同学起到一些借鉴作用,在以后的开发中遇到类似的问题,能快速的找到解决...

  • 【Spring Cloud 13】构建高性能的大型分布式网站

    高性能:提供快速的访问体验。 高可用:网站服务一直可以正常访问。 可伸缩:通过硬件增加/减少,提高/降低处理能力。 扩展性:方便地通过新增/移除方式,增加/减少新的功能/模块。 安全性:提供网站安全访问和...

  • Java性能优化

    在多处理器系统中,每个处理器有自己的高速缓存,而他们又共享同一块内存(下文成主存,main memory 主要内存),当多个处理器运算都涉及到同一块内存区域的时候,就有可能发生缓存不一致的现象。 为了解决这一问题...

  • 编写高性能Java代码的最佳实践

    摘要:本文首先介绍了负载测试、基于APM工具的应用程序和服务器监控,随后介绍了编写高性能Java代码的一些最佳实践。最后研究了JVM特定的调优技巧、数据库端的优化和架构方面的调整。以下是译文。 介绍 在这篇文章...

  • java开源持久层框架集

    Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端...

  • Java知识体系最强总结(2021版)

    本人从事Java开发已多年,平时有记录问题解决方案和总结知识点的习惯,整理了一些有关Java的知识体系,这不是最终版,会不定期的更新。也算是记录自己在从事编程工作的成长足迹,通过博客可以促进博主与阅读者的共同...

  • 怎么做好Java性能优化

    性能优化是一个很复杂的工作,且充满了不确定性。它不像Java业务代码,可以一次编写到处运行(write once, run anywhere),往往一些我们可能并不能察觉的变化,就会带来惊喜/惊吓。能够全面的了解并评估我们所负责...

  • 【JAVA高并发-1】必备技能

    文章目录1.1 Netty1.1.1 Netty火热的程度1.1.2 面试杀器1.2 Redis1.2.1 什么是Redis1.2.2 Redis特点1.3 ZooKeeper1.3.1 什么是ZooKeeper1.3.2 ZooKeeper优势1.4 高性能HTTP通信技术1.4.1 十万级以上高并发场景中的高...

  • 超级硬核!Java 自学路线总结,已 Get 大厂 Offer,建议立马收藏!

    ModelAndView 指定的视图 视图负责将结果显示到客户端 MyBatis 是一个支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架。 MyBatis 对 JDBC 做了封装,它让数据库底层操作变的透明。 MyBatis 的操作都是围绕一...

  • 掌握P5级Java面试技巧

    HashMap底层原理,扩容机制,jdk8以后会使用红黑树优化?红黑树和二叉平衡树的区别,红黑树和B树,B+树的区别,Mysql二大引擎索引底层实现,HashMap在多线程环境中为何出错?...当我们向HashMap中存放一个元素(k1,v1)

  • Java高级看这篇就足够了(高级知识汇总)

    编程语言中,封装有2层意思: 1.将重复的代码提取到一个公共的方法中,从而提升代码的复用性、可维护性 2.如果成员变量未加封装密封,可以在类的外部被肆无忌惮的修改 封装性是指,将对象的属性和行为进行密封,...

  • 怎样写出高性能的 Java 代码?

    在这篇文章中,我们将讨论几个有助于提升Java应用程序性能的方法。我们首先将介绍如何定义可度量的性能指标,然后看看有哪些工具可以用来度量和监控应用程序性能,以及确定性能瓶...

  • node的性能和java对比分析

    我们众所周知Java具有一个称作JRE的运行时环境来使得java程序能够顺利运行。JRE有一个称为JVM的虚拟机。JVM有许多组件,如垃圾回收器(GC),即时(JIT)编译器,解释器,类装载器,线程管理器,异常处理器,用于在...

  • 高级java开发必问面试题

    封装继承多态== 和equals比较hashCode与equals重载和重写的区别Finalspring是什么AOP的理解谈谈你对IOC的理解零拷贝RocketMQ 架构设计RocketMq 事务消息原理RockeMq顺序消息消费原理简述RockerMQ持久化机制RocketMQ...

  • pocketsphinx-0.1.15-cp34-cp34m-win32.whl.rar

    python whl离线安装包 pip安装失败可以尝试使用whl离线安装包安装 第一步 下载whl文件,注意需要与python版本配套 python版本号、32位64位、arm或amd64均有区别 第二步 使用pip install XXXXX.whl 命令安装,如果whl路径不在cmd窗口当前目录下,需要带上路径 WHL文件是以Wheel格式保存的Python安装包, Wheel是Python发行版的标准内置包格式。 在本质上是一个压缩包,WHL文件中包含了Python安装的py文件和元数据,以及经过编译的pyd文件, 这样就使得它可以在不具备编译环境的条件下,安装适合自己python版本的库文件。 如果要查看WHL文件的内容,可以把.whl后缀名改成.zip,使用解压软件(如WinRAR、WinZIP)解压打开即可查看。 为什么会用到whl文件来安装python库文件呢? 在python的使用过程中,我们免不了要经常通过pip来安装自己所需要的包, 大部分的包基本都能正常安装,但是总会遇到有那么一些包因为各种各样的问题导致安装不了的。 这时我们就可以通过尝试去Python安装包大全中(whl包下载)下载whl包来安装解决问题。

Global site tag (gtag.js) - Google Analytics