這篇文章主要介紹了python測試mysql寫入性能完整實例,具有一定借鑒價值,需要的朋友可以參考下
本文主要研究的是python測試mysql寫入性能,分享了一則完整代碼,具體介紹如下。
測試環境:
(1) 阿里雲服務器centos 6.5
(2) 2G內存
(3) 普通硬盤
(4) mysql 5.1.73 數據庫存儲引擎為 InnoDB
(5) python 2.7
(6) 客戶端模塊 mysql.connector
測試方法:
(1) 普通寫入
(2) 批量寫入
(3) 事務加批量寫入
普通寫入:
1
2
3
4
|
def
ordinary_insert(count):
sql
=
"insert into stu(name,age,class)values('test mysql insert',30,8)"
for
i
in
range
(count):
cur.execute(sql)
|
批量寫入,每次批量寫入20條數據
1
2
3
4
5
6
7
8
9
10
11
12
13
|
def
many_insert(count):
sql
=
"insert into stu(name,age,class)values(%s,%s,%s)"
loop
=
count
/
20
stus
=
((
'test mysql insert'
,
30
,
30
), (
'test mysql insert'
,
30
,
31
), (
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
)
,(
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
),
(
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
)
,(
'test mysql insert'
,
30
,
30
), (
'test mysql insert'
,
30
,
31
), (
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
)
,(
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
),
(
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
))
#並不是元組里的數據越多越好
for
i
in
range
(loop):
cur.executemany(sql, stus)
|
事務加批量寫入,每次批量寫入20條數據,每20個批量寫入作為一次事務提交
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
def
transaction_insert(count):
sql
=
"insert into stu(name,age,class)values(%s,%s,%s)"
insert_lst
=
[]
loop
=
count
/
20
stus
=
((
'test mysql insert'
,
30
,
30
), (
'test mysql insert'
,
30
,
31
), (
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
)
,(
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
),
(
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
)
,(
'test mysql insert'
,
30
,
30
), (
'test mysql insert'
,
30
,
31
), (
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
)
,(
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
),
(
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
))
#並不是元組里的數據越多越好
for
i
in
range
(loop):
insert_lst.append((sql,stus))
if
len
(insert_lst)
=
=
20
:
conn.start_transaction()
for
item
in
insert_lst:
cur.executemany(item[
0
], item[
1
])
conn.commit()
print
'0k'
insert_lst
=
[]
if
len
(insert_lst) >
0
:
conn.start_transaction()
for
item
in
insert_lst:
cur.executemany(item[
0
], item[
1
])
conn.commit()
|
實驗結果如下
1
2
3
4
|
數量 普通寫入 many寫入 事務加many寫入
1萬 26.7s 1.7s 0.5s
10萬 266s 19s 5s
100萬 2553s 165s 49s
|
批量寫入,相比於普通的多次寫入,減少了網絡傳輸次數,因而寫入速度加快。
不論是單次寫入還是批量寫入,數據庫內部都要開啟一個事務以保證寫入動作的完整,如果在應用層,我們自己開啟事物,那么就可以避免每一次寫入數據庫自己都開啟事務的開銷,從而提升寫入速度。
事務加批量寫入速度大概是批量寫入速度的3倍,是普通寫入的50倍。
完整的測試代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
#coding=utf-8
'''''
采用三種方法測試mysql.connector對mysql的寫入性能,其他的例如mysqldb和pymysql客戶端庫的寫入性能應該和mysql.connector一致
采用批量寫入時,由於減少了網絡傳輸的次數因而速度加快
開啟事務,多次寫入后再提交事務,其寫入速度也會顯著提升,這是由於單次的insert,數據庫內部也會開啟事務以保證一次寫入的完整性
如果開啟事務,在事務內執行多次寫入操作,那么就避免了每一次寫入都開啟事務,因而也會節省時間
從測試效果來看,事務加批量寫入的速度大概是批量寫入的3倍,是普通寫入的50倍
數量 普通寫入 many寫入 事務加many寫入
1萬 26.7s 1.7s 0.5s
10萬 266s 19s 5s
100萬 2553s 165s 49s
將autocommit設置為true,執行insert時會直接寫入數據庫,否則在execute 插入命令時,默認開啟事物,必須在最后commit,這樣操作實際上減慢插入速度
此外還需要注意的是mysql的數據庫存儲引擎如果是MyISAM,那么是不支持事務的,InnoDB 則支持事務
'''
import
time
import
sys
import
mysql.connector
reload
(sys)
sys.setdefaultencoding(
'utf-8'
)
config
=
{
'host'
:
'127.0.0.1'
,
'port'
:
3306
,
'database'
:
'testsql'
,
'user'
:
'root'
,
'password'
:
'sheng'
,
'charset'
:
'utf8'
,
'use_unicode'
:
True
,
'get_warnings'
:
True
,
'autocommit'
:
True
}
conn
=
mysql.connector.connect(
*
*
config)
cur
=
conn.cursor()
def
time_me(fn):
def
_wrapper(
*
args,
*
*
kwargs):
start
=
time.time()
fn(
*
args,
*
*
kwargs)
seconds
=
time.time()
-
start
print
u
"{func}函數每{count}條數數據寫入耗時{sec}秒"
.
format
(func
=
fn.func_name,count
=
args[
0
],sec
=
seconds)
return
_wrapper
#普通寫入
@time_me
def
ordinary_insert(count):
sql
=
"insert into stu(name,age,class)values('test mysql insert',30,8)"
for
i
in
range
(count):
cur.execute(sql)
#批量
@time_me
def
many_insert(count):
sql
=
"insert into stu(name,age,class)values(%s,%s,%s)"
loop
=
count
/
20
stus
=
((
'test mysql insert'
,
30
,
30
), (
'test mysql insert'
,
30
,
31
), (
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
)
,(
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
),
(
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
)
,(
'test mysql insert'
,
30
,
30
), (
'test mysql insert'
,
30
,
31
), (
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
)
,(
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
),
(
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
))
#並不是元組里的數據越多越好
for
i
in
range
(loop):
cur.executemany(sql, stus)
#事務加批量
@time_me
def
transaction_insert(count):
sql
=
"insert into stu(name,age,class)values(%s,%s,%s)"
insert_lst
=
[]
loop
=
count
/
20
stus
=
((
'test mysql insert'
,
30
,
30
), (
'test mysql insert'
,
30
,
31
), (
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
)
,(
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
),
(
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
)
,(
'test mysql insert'
,
30
,
30
), (
'test mysql insert'
,
30
,
31
), (
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
)
,(
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
),
(
'test mysql insert'
,
30
,
32
), (
'test mysql insert'
,
30
,
32
))
#並不是元組里的數據越多越好
for
i
in
range
(loop):
insert_lst.append((sql,stus))
if
len
(insert_lst)
=
=
20
:
conn.start_transaction()
for
item
in
insert_lst:
cur.executemany(item[
0
], item[
1
])
conn.commit()
print
'0k'
insert_lst
=
[]
if
len
(insert_lst) >
0
:
conn.start_transaction()
for
item
in
insert_lst:
cur.executemany(item[
0
], item[
1
])
conn.commit()
def
test_insert(count):
ordinary_insert(count)
many_insert(count)
transaction_insert(count)
if
__name__
=
=
'__main__'
:
if
len
(sys.argv)
=
=
2
:
loop
=
int
(sys.argv[
1
])
test_insert(loop)
else
:
print
u
'參數錯誤'
|