浅析数据库连接池(二)

来源:互联网 发布:udid定制后台源码 编辑:程序博客网 时间:2024/06/05 19:15

上一篇博客,主要是简单的介绍了普通数据库连接的过程以及耗费的资源,并且简单的谈了下连接池,这篇我们主要来看看数据库连接池的使用以及它最优的配置。


总目录:
-1.数据库连接过程是怎样的?
-2.连接所占用的资源有哪些?
-3.连接池简介
-4.连接池的使用
-5.最优连接池配置选择

今天主要看看4和5。


4.连接池的使用

这里我使用的是c3p0数据库连接池
简单的介绍一下c3p0:C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等。

连接池的种类也有很多,而且每种也有不同的适用场景,所以选择适合自己的连接池也是一方面~


先放不使用连接池和使用连接池的数据对比。
循环连接10次,图片为测试的第10组数据。

不使用连接池
这里写图片描述


使用连接池
红色为连接池部分配置信息
这里写图片描述


从图片我们可以明显的看出,连接池的速度要快于普通连接很多,这里很多不是指的二者差多少毫秒,而是倍数的差别。


java连接池代码:

import com.mchange.v2.c3p0.ComboPooledDataSource;import java.awt.color.ProfileDataException;import java.beans.PropertyVetoException;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.util.ResourceBundle;/** * Created by wwh on 15-6-10. */public class DBPollClass {    private static DBPollClass dbPoll;    private ComboPooledDataSource dbSource;    //静态代码块,一开始我们就执行构造函数加载配置信息    static {        dbPoll = new DBPollClass();    }    public DBPollClass(){        //设置配置信息        try{            dbSource = new ComboPooledDataSource();            dbSource.setUser("root");            dbSource.setPassword("123456789");            dbSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/XL_db?user=root&password=123456789&useUnicode=true");            dbSource.setDriverClass("com.mysql.jdbc.Driver");            dbSource.setInitialPoolSize(1);            dbSource.setMinPoolSize(2);            dbSource.setMaxPoolSize(10);            dbSource.setMaxStatements(50);            dbSource.setMaxIdleTime(60);        }catch (PropertyVetoException e){            throw new RuntimeException(e);        }    }    //获得连接    public final static DBPollClass getInstance(){        return dbPoll;    }    public final Connection getConnection(){        try{            return dbSource.getConnection();        }catch (SQLException e){            throw new RuntimeException("无法获取连接", e);        }    }    public static void main(String[] args) throws SQLException {        for(int i = 0; i < 10; i++) {            long begintime = System.currentTimeMillis();            Connection con = null;            try {                //取得空闲连接                con = dbPoll.getInstance().getConnection();                //执行sql语句并返回查询结果                //ResultSet rs = con.createStatement().executeQuery("SELECT * from UserInfo");                //使用PreparedStatement而不使用Statement                PreparedStatement pst = con.prepareStatement("SELECT * from UserInfo");                ResultSet rs = pst.executeQuery();                //输出查询结果                while (rs.next()) {                    System.out.println(rs.getObject(1) + " " + rs.getObject(2) + " " + rs.getObject(3) + " " + rs.getObject(4));                }            } catch (Exception e) {                e.printStackTrace();            } finally {                if (con != null) {                    //归还空闲连接                    con.close();                }            }            long endtime = System.currentTimeMillis();            System.out.println((i+1) + " time is:" + (endtime-begintime));        }    }}

从代码我们可以和清晰的看出连接池的使用是非常简单的,代码中我将连接池的配置等信息写到了构造函数中,其实现实中使用我们一般写在c3p0-config.xml,数据库连接池的配置文件中,然后放到src目录下即可。
连接池的使用步骤和普通的JDBC连接数据库基本一样。参数也类似
只不过部分含义不同,连接池的connection,并不是创建连接,而是从数据库连接池中间找出一个空闲的连接,con.close()也不是断开连接,而是归还给连接池。
还有注意我们不仅仅要归还connection资源,还要归还Preparedstatement和ResultSet的资源
我们也需要养成良好的习惯使用Preparedstatement而不是statement,因为Preparedstatement里面包含了部分已经编译好的sql语句,可以提高执行速度。


5.最优连接池配置选择

使用和使用好两个词是截然不同的,我们的目的不仅仅是使用线程池或者数据库连接池,而是通过使用它们来发挥服务器最大威力以及效率达到最优。
这就要我们根据自己服务器配置信息来选择参数了~。
先看看代码中我们设定了哪些参数。

设置初始化连接池大小
dbSource.setInitialPoolSize(1);

设置连接池内最小连接数
dbSource.setMinPoolSize(2);

设置连接池内最大连接数
dbSource.setMaxPoolSize(10);

用来控制Preparedstatement的数量
dbSource.setMaxStatements(50);

最大空闲时间,60秒内未使用连接则被丢取,设置为0则永不丢弃
dbSource.setMaxIdleTime(60);
以上为常用和关键的参数。


关于最关键的参数设定
1.最小连接数
连接池一直保持的数据库连接。最小连接数的大小我们要根据实际的使用情况不断的测试来决定,如果设定大了就会有许多空闲的连接,浪费了资源。

2.最大连接数
连接池的连接上限,一般当连接值大于最小连接数时,连接池就会创建新的connection来接受连接,我们设定的超时时间就是针对新创建的连接的,当使用完最小连接数外的连接时,它们不会被立即释放,而是停留MaxIdleTime时间,如果在MaxIdleTime时间没有再次被连接,则释放。如果超过最大连接数,那么新到的连接会被加入到等待队列中。

3.最大空闲时间MaxIdleTime,这个要根据实际情况来调整设定了。

如果最小连接数和最大连接数相差很大,那么最先到的连接最获利,连接速度非常快,后到的会稍微慢点,因为要创建连接。

我们一般设定池的大小时,比如线程池,首先要确定是CPU密集型还是IO密集型,如果是CPU密集型,那么我们如果线程池设定应该和CPU核数几乎一致,因为此时大量的计算,如果线程数量设定过大,那么线程切换消耗的时间就是主要花费,如果是IO密集型,那么线程数量要大于CPU数量,因为线程可能阻塞在IO处,所以阻塞时要切换其他线程继续执行,效率会高。

那么访问数据库是IO密集型的,因为内部也是创建单独的线程来连接,所以类似线程池,线程池IO密集型线程数计算公式为:
线程数 = CPU核数 / (1-阻塞系数),阻塞系数也应该根据我们具体情况来分析。
一般线程数为核心数的几倍。


我就简单的介绍到这里,上面所说也是根据自己现有的知识和查询的资料来描述的,并不一定全部正确,希望大家带着审视的眼光来看,如果哪部分错了,还望指出,谢谢~

2 0
原创粉丝点击