Python MySQLdb 循環插入execute與批量插入executemany性能分析

Python MySQLdb 循環插入execute與批量插入executemany性能分析

用Python鏈接MySQL數據庫時,會用到MySQLdb庫,這裏下載↓↓↓python

https://pypi.python.org/pypi/MySQL-python/mysql

 

這個庫提供了對數據庫的廣泛操做,增刪改查之類的,教程能夠參考:正則表達式

python下的MySQLdb使用sql

 

其中,有一個很cooooooooooool的功能就是批量操做executemany,能夠進行多行插入數據庫

先寫sql語句。要注意的是裏面的參數,無論什麼類型,統一使用%s做爲佔位符
例如,向user表(username,salt,pwd)插入數據app

sql = 'INSERT INTO 表名 VALUES(%s,%s,%s)'
對應的param是一個tuple或者listdom

param = ((username1, salt1, pwd1), (username2, salt2, pwd2), (username3, salt3, pwd3))函數

這樣就包含了三條數據,經過executemany插入
n=cursor.executemany(sql,param) oop


上個雙休日在學校往畢設系統裏導名單,想到Java就心累因而用Python寫性能

做爲一個老實的土鱉,在知道有這個酷炫的方法狀況下,仍是有點不敢用,先保守地寫了一個循環的版本

幾百條數據很快就導進去的,原本這就該結束了,可是又以爲有點不甘心,想知道兩種插入方式效率有多大差異

因而簡單模擬了10000個用戶的數據,試着用兩種方法各跑了一遍

# -------------------------------------------
# Python MySQLdb 循環插入execute與批量插入executemany性能分析
# 插入數據量:10000條
# 每條字段:username, salt, pwd
# Author : Lrg
# -------------------------------------------
# encoding = utf-8
import MySQLdb
import xlrd
import time
import sys
reload(sys)
sys.setdefaultencoding("utf-8")

# 從users.xls文件獲取10000條用戶數據
# 該文件由create_users.py生成
def get_table():
FILE_NAME = 'users.xls'
data = xlrd.open_workbook(FILE_NAME)
table = data.sheets()[0]
return table

# 循環插入execute
def insert_by_loop(table):
nrows = table.nrows
for i in xrange(1,nrows):
param=[]
try:
sql = 'INSERT INTO user values(%s,%s,%s)'
# 第一列username,第二列salt,第三列pwd
print 'Insert: ',table.cell(i, 0).value, table.cell(i, 1).value, table.cell(i, 2).value
param = (table.cell(i, 0).value, table.cell(i, 1).value, table.cell(i, 2).value)
# 單條插入
cur.execute(sql, param)
conn.commit()
except Exception as e:
print e
conn.rollback()
print '[insert_by_loop execute] total:',nrows-1

# 批量插入executemany
def insert_by_many(table):
nrows = table.nrows
param=[]
for i in xrange(1,nrows):
# 第一列username,第二列salt,第三列pwd
param.append([table.cell(i, 0).value, table.cell(i, 1).value, table.cell(i, 2).value])
try:
sql = 'INSERT INTO user values(%s,%s,%s)'
# 批量插入
cur.executemany(sql, param)
conn.commit()
except Exception as e:
print e
conn.rollback()
print '[insert_by_many executemany] total:',nrows-1


# 鏈接數據庫
conn = MySQLdb.connect(host="127.0.0.1", port=3306, user="lrg", passwd="lrg", db="pythontest")
cur = conn.cursor()

# 新建數據庫
cur.execute('DROP TABLE IF EXISTS user')
sql = """CREATE TABLE user(
username CHAR(255) NOT NULL,
salt CHAR(255),
pwd CHAR(255)
)"""
cur.execute(sql)

# 從excel文件獲取數據
table = get_table()

# 使用循環插入
start = time.clock()
insert_by_loop(table)
end = time.clock()
print '[insert_by_loop execute] Time Usage:',end-start

# 使用批量插入
start = time.clock()
insert_by_many(table)
end = time.clock()
print '[insert_by_many executemany] Time Usage:',end-start

# 釋放數據鏈接
if cur:
cur.close()
if conn:
conn.close()


一共10000條數據

一行行循環execute,耗時200秒左右(下面244秒的數據是每次循環加了輸出語句的,應該有點影響)

而用executemany一次提交所有,耗時只有0.86秒……

[insert_by_loop execute] total: 10000
[insert_by_loop execute] Time Usage: 244.164735527
[insert_by_many executemany] total: 10000
[insert_by_many executemany] Time Usage: 0.861406346583
[Finished in 245.7s]

土鱉如今有一種難以言喻的微妙感
想起前兩天用正則表達式用的正爽時,看到一篇文章說,一樣的功能用字符串函數完成比正則快幾十幾百倍……

討厭啦泥們不要欺負新手啊!!【捂臉】

 

 

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

附上生成模擬數據user.xls的代碼,簡單粗暴(MD5部分實驗程序:Python簡單密碼加密程序,加鹽(salt)md5)

# -------------------------------------------
# Python生成user程序
# Author : Lrg
# -------------------------------------------
# encoding = utf-8
from random import Random
from hashlib import md5
import xlwt

# 獲取由4位隨機大小寫字母、數字組成的salt值
def create_salt(length = 4):
salt = ''
chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789'
len_chars = len(chars) - 1
random = Random()
for i in xrange(length):
# 每次從chars中隨機取一位
salt += chars[random.randint(0, len_chars)]
return salt

# 獲取原始密碼+salt的md5值
def create_md5(pwd,salt):
md5_obj = md5()
md5_obj.update(pwd + salt)
return md5_obj.hexdigest()

# 建立一個xls文件
book = xlwt.Workbook()
# 建立一個sheet
sheet = book.add_sheet('users', cell_overwrite_ok=True)
# 每列第一行寫上列名
sheet.write(0, 0, 'username')
sheet.write(0, 1, 'salt')
sheet.write(0, 2, 'pwd')
# 生成user數量
count = 10000
# 第一個id
first_id = 311010000
for i in xrange(count):
current_id = str(first_id + i)
salt = create_salt()
pwd = create_md5(current_id, salt)
sheet.write(i+1, 0, current_id)
sheet.write(i+1, 1, salt)
sheet.write(i+1, 2, pwd)
# 保存
book.save('users.xls')


--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

過了一天,又學到一個打臉方法

MySQL自己有個load data infile的方法,格式相似這樣:

load data infile 'D:/Python workspace/user.txt' into table user(username, salt, pwd)

這個方法有多快?
從txt導5個字段的9086條數據到mysql,先讀到程序裏,再用executemany是0.29秒,直接用這個語句導的話,0.17秒……

想到昨天一個上午都在磨磨唧唧研究循環跟批量,這下被打臉也是打的有點爽……

相關文章
相關標籤/搜索