程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> DB2數據庫 >> DB2教程 >> 淺析數據庫連接池(二)

淺析數據庫連接池(二)

編輯:DB2教程

淺析數據庫連接池(二)


上一篇博客,主要是簡單的介紹了普通數據庫連接的過程以及耗費的資源,並且簡單的談了下連接池,這篇我們主要來看看數據庫連接池的使用以及它最優的配置。


總目錄:
-1.數據庫連接過程是怎樣的?
-2.連接所占用的資源有哪些?
-3.連接池簡介
-4.連接池的使用
-5.最優連接池配置選擇

今天主要看看4和5。


4.連接池的使用

這裡我使用的是c3p0數據庫連接池
簡單的介紹一下c3p0:C3P0是一個開源的JDBC連接池,它實現了數據源和JNDI綁定,支持JDBC3規范和JDBC2的標准擴展。目前使用它的開源項目有Hibernate,Spring等。

連接池的種類也有很多,而且每種也有不同的適用場景,所以選擇適合自己的連接池也是一方面~


先放不使用連接池和使用連接池的數據對比。
循環連接10次,圖片為測試的第10組數據。

不使用連接池
這裡寫圖片描述


使用連接池
紅色為連接池部分配置信息
這裡寫圖片描述


從圖片我們可以明顯的看出,連接池的速度要快於普通連接很多,這裡很多不是指的二者差多少毫秒,而是倍數的差別。<喎?http://www.Bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPC9ibG9ja3F1b3RlPgoKPGhyPgoKPGgzIGlkPQ=="java連接池代碼">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-阻塞系數),阻塞系數也應該根據我們具體情況來分析。
一般線程數為核心數的幾倍。


我就簡單的介紹到這裡,上面所說也是根據自己現有的知識和查詢的資料來描述的,並不一定全部正確,希望大家帶著審視的眼光來看,如果哪部分錯了,還望指出,謝謝~

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved