python3 executemany 效率_Python MySQLdb 循环插入execute与批量插入executemany性能分析

本文分析了Python使用MySQLdb库时,循环执行execute与一次性使用executemany进行批量插入的性能差异。通过模拟10000条用户数据,发现executemany方法在插入效率上远超循环执行,耗时仅为0.86秒,而循环执行耗时约200秒。此外,还提到了MySQL的`LOAD DATA INFILE`命令,其在导入数据时表现出更高的效率。
摘要由CSDN通过智能技术生成

Python MySQLdb 循环插入execute与批量插入executemany性能分析

用Python连接MySQL数据库时,会用到MySQLdb库,这里下载↓↓↓

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

这个库提供了对数据库的普遍操作,增删改查之类的,教程可以参考:

python下的MySQLdb使用

其中,有一个很cooooooooooool的功能就是批量操作executemany,可以进行多行插入

先写sql语句。要注意的是里面的参数,不管什么类型,统一使用%s作为占位符

例如,向user表(username,salt,pwd)插入数据

sql = 'INSERT INTO 表名 VALUES(%s,%s,%s)'

对应的param是一个tuple或者list

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

这样就包含了三条数据,通过executemany插入

n=cursor.executemany(sql,param)

上个双休日在学校往毕设系统里导名单,想到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秒……

想到昨天一个上午都在磨磨唧唧研究循环跟批量,这下被打脸也是打的有点爽……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值