首先介紹下MySQLdb、DBUtil、sqlobject:python
(1)MySQLdb 是用於Python鏈接Mysql數據庫的接口,它實現了 Python 數據庫
API 規範 V2.0,基於 MySQL C API 上創建的。除了MySQLdb外,python還能夠經過oursql, PyMySQL, myconnpy等模塊實現MySQL數據庫操做;mysql
(2)DBUtil中提供了幾種鏈接池,用以提升數據庫的訪問性能,例如PooledDB,PesistentDB等sql
(3)sqlobject能夠實現數據庫ORM映射的第三方模塊,能夠以對象、實例的方式輕鬆操做數據庫中記錄。數據庫
爲測試這三者的性能,簡單作一個例子:50個併發訪問4000條記錄的單表,數據庫記錄以下:編程
測試代碼以下:併發
一、MySQLdb的代碼以下,其中在connDB()中把鏈接池相關代碼暫時作了一個註釋,去掉這個註釋既可使用鏈接池來建立數據庫鏈接:ide
(1)DBOperator.py性能
01 |
import MySQLdb |
02 |
from stockmining.stocks.setting import LoggerFactory |
03 |
import connectionpool |
04 |
05 |
class DBOperator( object ): |
06 |
|
07 |
def __init__( self ): |
08 |
self .logger = LoggerFactory.getLogger( 'DBOperator' ) |
09 |
self .conn = None |
10 |
|
11 |
def connDB( self ): |
12 |
self .conn = MySQLdb.connect(host = "127.0.0.1" ,user = "root" ,passwd = "root" ,db = "pystock" ,port = 3307 ,charset = "utf8" ) |
13 |
#當須要使用鏈接池的時候開啓 |
14 |
#self.conn=connectionpool.pool.connection() |
15 |
return self .conn |
16 |
17 |
def closeDB( self ): |
18 |
if ( self .conn ! = None ): |
19 |
self .conn.close() |
20 |
|
21 |
def execute( self , sql): |
22 |
try : |
23 |
if ( self .conn ! = None ): |
24 |
cursor = self .conn.cursor() |
25 |
else : |
26 |
raise MySQLdb.Error( 'No connection' ) |
27 |
|
28 |
n = cursor.execute(sql) |
29 |
return n |
30 |
except MySQLdb.Error,e: |
31 |
self .logger.error( "Mysql Error %d: %s" % (e.args[ 0 ], e.args[ 1 ])) |
32 |
|
33 |
def findBySQL( self , sql): |
34 |
try : |
35 |
if ( self .conn ! = None ): |
36 |
cursor = self .conn.cursor() |
37 |
else : |
38 |
raise MySQLdb.Error( 'No connection' ) |
39 |
|
40 |
cursor.execute(sql) |
41 |
rows = cursor.fetchall() |
42 |
return rows |
43 |
except MySQLdb.Error,e: |
44 |
self .logger.error( "Mysql Error %d: %s" % (e.args[ 0 ], e.args[ 1 ])) |
(2)測試代碼testMysql.py,作了50個併發,對獲取到的數據庫記錄作了個簡單遍歷。測試
01 |
import threading |
02 |
import time |
03 |
import DBOperator |
04 |
05 |
def run(): |
06 |
operator = DBOperator() |
07 |
operator.connDB() |
08 |
starttime = time.time() |
09 |
sql = "select * from stock_cash_tencent" |
10 |
peeps = operator.findBySQL(sql) |
11 |
for r in peeps: pass |
12 |
operator.closeDB() |
13 |
endtime = time.time() |
14 |
diff = (endtime - starttime) * 1000 |
15 |
print diff |
16 |
|
17 |
def test(): |
18 |
for i in range ( 50 ): |
19 |
threading.Thread(target = run).start() |
20 |
time.sleep( 1 ) |
21 |
|
22 |
if __name__ = = '__main__' : |
23 |
test() |
二、鏈接池相關代碼:fetch
(1)connectionpool.py
01 |
from DBUtils import PooledDB |
02 |
import MySQLdb |
03 |
import string |
04 |
05 |
maxconn = 30 #最大鏈接數 |
06 |
mincached = 10 #最小空閒鏈接 |
07 |
maxcached = 20 #最大空閒鏈接 |
08 |
maxshared = 30 #最大共享鏈接 |
09 |
connstring = "root#root#127.0.0.1#3307#pystock#utf8" #數據庫地址 |
10 |
dbtype = "mysql" |
11 |
12 |
def createConnectionPool(connstring, dbtype): |
13 |
db_conn = connstring.split( "#" ); |
14 |
if dbtype = = 'mysql' : |
15 |
try : |
16 |
pool = PooledDB.PooledDB(MySQLdb, user = db_conn[ 0 ],passwd = db_conn[ 1 ],host = db_conn[ 2 ],port = string.atoi(db_conn[ 3 ]),db = db_conn[ 4 ],charset = db_conn[ 5 ], mincached = mincached,maxcached = maxcached,maxshared = maxshared,maxconnections = maxconn) |
17 |
return pool |
18 |
except Exception, e: |
19 |
raise Exception, 'conn datasource Excepts,%s!!!(%s).' % (db_conn[ 2 ], str (e)) |
20 |
return None |
21 |
22 |
23 |
pool = createConnectionPool(connstring, dbtype) |
三、sqlobject相關代碼
(1)connection.py
1 |
from sqlobject.mysql import builder |
2 |
3 |
conn = builder()(user = 'root' , password = 'root' , |
4 |
host = '127.0.0.1' , db = 'pystock' , port = 3307 , charset = 'utf8' ) |
(2)StockCashTencent.py對應到數據庫中的表,50個併發並做了一個簡單的遍歷。(實際上,若是不作遍歷,只作count()計算,sqlobject性能是至關高的。)
01 |
import sqlobject |
02 |
import time |
03 |
from connection import conn |
04 |
import threading |
05 |
06 |
class StockCashTencent(sqlobject.SQLObject): |
07 |
_connection = conn |
08 |
|
09 |
code = sqlobject.StringCol() |
10 |
name = sqlobject.StringCol() |
11 |
date = sqlobject.StringCol() |
12 |
main_in_cash = sqlobject.FloatCol() |
13 |
main_out_cash = sqlobject.FloatCol() |
14 |
main_net_cash = sqlobject.FloatCol() |
15 |
main_net_rate = sqlobject.FloatCol() |
16 |
private_in_cash = sqlobject.FloatCol() |
17 |
private_out_cash = sqlobject.FloatCol() |
18 |
private_net_cash = sqlobject.FloatCol() |
19 |
private_net_rate = sqlobject.FloatCol() |
20 |
total_cash = sqlobject.FloatCol() |
21 |
22 |
def test(): |
23 |
starttime = time.time() |
24 |
query = StockCashTencent.select( True ) |
25 |
for result in query: pass |
26 |
endtime = time.time() |
27 |
diff = (endtime - starttime) * 1000 |
28 |
print diff |
29 |
|
30 |
if __name__ = = '__main__' : |
31 |
for i in range ( 50 ): |
32 |
threading.Thread(target = test).start() |
33 |
time.sleep( 1 ) |
測試結果以下:
MySQLdb平均(毫秒) | 99.63999271 |
DBUtil平均(毫秒) | 97.07998276 |
sqlobject平均(毫秒) | 343.2999897 |
結論:其實就測試數據而言,MySQLdb單鏈接和DBUtil鏈接池的性能並無很大的區別(100個併發下也相差無幾),相反sqlobject雖然具備的編程上的便利性,可是卻帶來性能上的巨大不足,在實際中使用哪一個模塊就要斟酌而定了。