最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

当前短讯!读Java性能权威指南(第2版)笔记05_数据库性能JDBC

来源:博客园


(资料图片)

1.影响数据库应用程序性能最重要的因素

1.1.JDBC驱动

1.1.1.JPA底层使用了JDBC

2.瘦驱动

2.1.为了让Java应用程序的内存占用很小

2.2.依赖数据库服务器来完成更多的处理工作

3.胖驱动

3.1.工作从数据库移至Java应用程序

3.2.进行更多处理、消耗更多内存

4.JDBC连接池

4.1.规则1:让应用程序中的每个线程都有一个连接

4.1.1.在服务器中,在初始时将线程池和连接池设置为相同的大小

4.1.2.在独立应用程序中,可以根据应用程序创建的线程数确定连接池的大小

4.1.3.程序中的任何线程都不必等待可用的数据库连接,并且数据库有足够的资源来处理应用程序施加的负载

4.2.数据库是瓶颈,规则1就不适用了

4.2.1.用连接池限制发送到小规模数据库的工作量

4.2.1.1.应用程序线程可能需要等待一个空闲的连接

4.2.1.2.如果数据库没有被压垮,系统的总吞吐量会最大化

4.3.初始化连接对象的成本很高

4.3.1.在Java中它们经常被池化

4.3.2.在池化对象所占用的内存和池化将触发的额外GC数量之间取得适当的平衡是非常重要的

4.4.优化连接池很重要

4.4.1.减少对垃圾回收器产生不利影响

4.4.2.减少对数据库的性能产生不利影响

5.驱动类型

5.1.1型驱动

5.1.1.ODBC和JDBC之间的桥梁

5.1.1.1.Open Database Connectivity,开放数据库互连

5.1.2.一个程序必须使用ODBC与数据库进行通信,就必须使用

5.1.3.性能一般很差

5.2.3型驱动

5.2.1.纯Java语言编写

5.2.2.为特定的架构设计

5.2.3.有个中间件能提供中间转换过程

5.2.4.中间件可以位于DMZ中,为数据库连接提供额外的安全保障

5.3.2型驱动

5.3.1.使用原生库来访问数据库

5.3.2.允许Java驱动利用多年来在编写C库上所做的工作

5.3.3.数据库供应商必须为驱动提供与平台相关的原生库,Java程序也必须设置环境变量才能使用该库

5.3.4.性能往往非常好

5.4.4型驱动

5.4.1.纯Java驱动

5.4.2.实现了数据库供应商为访问数据库定义的线路协议

5.4.3.性能通常和2型驱动一样好

5.4.4.最容易使用

5.5.推荐使用

6.预处理语句

6.1.不是Statement进行JDBC调用

6.1.1.语句只使用一次

6.1.1.1.最好使用Statement常规语句

6.2.使用PreparedStatement场景

6.2.1.重用

6.2.2.包含很多JDBC调用的批处理程序

6.2.3.在其生命周期中会服务大量请求的服务器

6.3.具有安全性和编程的优势

6.4.会消耗大量的堆空间

6.4.1.避免因池化太多非常大的对象而产生GC问题

7.预处理语句被池化

7.1.重用PreparedStatement对象关键点

7.1.1.JDBC连接池

7.1.2.JDBC驱动配置

7.2.必须在每个连接的基础上进行池化

7.2.1.大多数JDBC驱动和数据框架可以自动地做到这一点

7.2.2.确保JDBC驱动和数据框架只有一个在管理预处理语句池是非常重要的

7.2.3.预期JDBC驱动能够更好地池化语句

7.2.3.1.驱动是针对特定数据库的

7.2.3.2.比更通用的应用程序服务器代码更好

7.3.连接池的大小很重要

7.3.1.会缓存预处理语句

7.3.1.1.语句缓存

7.3.1.2.会消耗大量的堆空间

7.4.管理语句池

7.4.1.ConnectionPoolDataSource类的setMaxStatements()方法可以启用或禁用语句池

7.4.1.1.setMaxStatements()方法的值为0,语句池就会被禁用

7.4.2.配置JDBC驱动来创建和管理语句池

7.4.2.1.查阅该驱动的文档

7.4.2.2.设置驱动,将maxStatements属性设定为所需的值(语句池的大小)

7.4.2.3.额外的设置

7.4.2.3.1.Oracle设置确定是使用隐式语句池还是显式语句池
7.4.2.3.2.MySQL设置另一个属性来启用语句池

7.4.3.在应用程序代码中创建和管理语句池

8.事务

8.1.应用程序对正确性的要求最终决定了事务的处理方式

8.1.1.不要让对性能的渴望超过应用程序的正确性

8.2.性能损失

8.2.1.数据库事务的创建和提交需要时间

8.2.1.1.确保数据库的更改完全存储到磁盘上

8.2.1.2.要确保数据库事务日志是一致的

8.2.2.事务通常会获得一组特定数据的锁

8.3.事务的开始和结束都基于Connection对象的使用方式

8.3.1.通过setAutoCommit()方法设置连接有一个自动提交模式

8.4.事务提交成本很高

8.4.1.一个目标是在一个事务中执行尽可能多的工作

8.4.2.另一个目标执行时间应该尽可能短

8.4.3.矛盾

8.5.锁可以保护数据的完整性

8.6.事务隔离模式

8.6.1.TRANSACTION_SERIALIZABLE

8.6.1.1.序列化事务

8.6.1.2.成本最高

8.6.1.3.在事务进行期间,事务访问的所有数据都被锁定

8.6.1.4.适用于通过主键访问的数据和通过WHERE子句访问的数据

8.6.1.5.在使用WHERE子句的时候,表会被锁定,这样在事务进行期间就不能添加满足该子句的新数据

8.6.1.6.每次查询时看到的数据就都是一样的

8.6.2.TRANSACTION_REPEATABLE_READ

8.6.2.1.重复读

8.6.2.2.在事务进行期间,被访问的所有数据都被锁定

8.6.2.3.其他事务可以在任何时候向表中插入新的数据

8.6.2.4.幻读(phantom read)

8.6.2.4.1.一个事务重新执行使用某个WHERE子句的查询时,第二次可能会得到不同的数据

8.6.2.5.MySQL默认

8.6.2.6.Oracle不支持

8.6.3.TRANSACTION_READ_COMMITTED

8.6.3.1.不可重复读

8.6.3.2.锁定事务进行期间被写入的数据

8.6.3.3.在事务进行期间,某一时刻读取的数据可能和另一时刻读取的数据不同

8.6.3.4.Oracle默认

8.6.3.5.IBM Db2默认

8.6.4.TRANSACTION_READ_UNCOMMITTED

8.6.4.1.成本最低

8.6.4.1.1.不涉及锁

8.6.4.2.脏读(dirty read)

8.6.4.2.1.一个事务可以读取在另一个事务中写入(但未提交)的数据
8.6.4.2.2.第一个事务可能会回滚(写入操作没有实际发生),因此第二个事务会在错误的数据上操作

8.6.4.3.Oracle不支持

8.6.5.TRANSACTION_NONE

8.6.5.1.JDBC规范定义了第5种事务隔离模式

8.6.6.setTransactionIsolation()方法

8.6.6.1.给数据库提供必要的事务隔离级别

8.6.6.2.如果数据库不支持给定的级别

8.6.6.2.1.JDBC驱动会抛出异常
8.6.6.2.2.自动将隔离级别设置为它支持的下一个更严格的级别

8.6.7.悲观锁(pessimistic locking)

8.6.8.乐观锁(optimistic locking)

8.6.8.1.数据访问不存在竞争,采用乐观锁会显著提升性能

8.6.8.2.当两个数据源之间发生竞争的概率很小时,乐观锁的效果最好

8.7.结果集

8.7.1.设置JDBC驱动一次传输的数据行数

8.7.1.1.可以使用PreparedStatement对象上的setFetchSize()方法

8.7.1.2.默认值因JDBC驱动的不同而不同

8.7.2.处理大量查询数据的应用程序时应该考虑更改数据的提取大小

8.7.3.权衡

8.7.3.1.在应用程序中加载太多数据(给垃圾回收器增加压力)

8.7.3.2.为了检索一组数据而频繁调用数据库

关键词: 应用程序 程序中的 垃圾回收