淺析資料庫連接池(二),淺析資料庫連接池
上一篇部落格,主要是簡單的介紹了普通資料庫連接的過程以及耗費的資源,並且簡單的談了下串連池,這篇我們主要來看看資料庫連接池的使用以及它最優的配置。
總目錄:
-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-阻塞係數),阻塞係數也應該根據我們具體情況來分析。
一般線程數為核心數的幾倍。
我就簡單的介紹到這裡,上面所說也是根據自己現有的知識和查詢的資料來描述的,並不一定全部正確,希望大家帶著審視的眼光來看,如果哪部分錯了,還望指出,謝謝~