我在写爬虫的时候,经常会获取大量的数据。这个时候大量数据的数据库操作如果不做一定的优化的话,将会耗费大量的时间。通过实践我发现,批量的数据操作将会极大的提高数据库操作的效率。同时,很多时候存在数据如果存在做更新操作,如果数据不存在,做插入插入操作的情况。于是我造了一个只需传入一个数组,就会自动更新或插入数据的工具。
实测以下方法操作几十万条数据只需要几秒到十几秒
以下为代码:

#说明:
#使用时直接调用saveAll方法,其他方法将被saveAll调用,你可以无视
#saveAll参数说明:
#   table 表名
#   datas 数据的数组 例 :[{"key1":"value1","key2":"value2"},{"key1":"value1","key2":"value2"}] 建议数组大小不要超过一千。
#   searchKeys 用于确定唯一行的键的数组,如用户表的用户名,选课表的课程ID与学生ID等 例 ["user_id","class_id"]
#   ifIgnoreSearchKey 是否忽略searchKey 如果你的searchKeys 是自增长的ID 你肯定不希望插入的时候插入这个字段 "1"是,"0"否
#   ifNotUpdate 是否不做更新操作 如果这个设为 "0" ,datas中数据如果已在数据库中,将不会做更新操作
#getConnection 方法中的DB 是我从我的配置文件中导入的,你可以换成你的
def getConnection():conn = MySQLdb.connect(host=DB["host"],user=DB["user"],passwd=DB["passwd"],db=DB["db"],charset=DB["charset"])return conndef saveAll(table,datas,searchKeys,ifIgnoreSearchKey,ifNotUpdate):print datasconn = getConnection()cursor = conn.cursor()where = []#转义数据,避免sql发生错误for data in datas:for key in data:data[key] = MySQLdb.escape_string(str(data[key]))for searchKey in searchKeys:searchKeyDatas = []for data in datas:searchKeyDatas.append(data[searchKey])searchKeyDatasString = "`"+searchKey+"` in ('"+"','".join(searchKeyDatas)+"')"where.append(searchKeyDatasString)whereString = " AND ".join(where)selectSql = "SELECT `"+"`,`".join(searchKeys)+"` from "+table+" WHERE " + whereStringcursor.execute(selectSql)conn.commit()results = cursor.fetchall()updateData = []insertData = []existKey = []for result in results:keyValue = []for value in result:keyValue.append(str(value))existKey.append(",".join(keyValue))for data in datas:keyValue = []for key in searchKeys:keyValue.append(data[key])currentKey = ",".join(keyValue)if currentKey in existKey:updateData.append(data)else:insertData.append(data)if ifNotUpdate == "0":updateAll(updateData,table,searchKeys)insertAll(insertData,table,searchKeys,ifIgnoreSearchKey)conn.close()passdef updateAll(datas,table,searchKeys):#同时更新多条数据if len(datas) == 0:returnconn = getConnection()cursor = conn.cursor()sets = {}updateSql = "UPDATE `"+table+"` set "whereValues = []whereKey = "WHERE CONCAT(`"+"`,',',`".join(searchKeys)+"`) IN "for data in datas:whereValue = []for searchKey in searchKeys:whereValue.append(data[searchKey])whereValueString = ",".join(whereValue)whereValues.append(whereValueString)for key in data:if key in searchKeys:passelse:searchValue = []for searchKey in searchKeys:searchValue.append(str(data[searchKey]))searchValueString = ",".join(searchValue)try:sets[key][searchValueString] = data[key]except KeyError as e:sets[key] = {}sets[key][searchValueString] = data[key]searchKeysString = "(`"+"`,',',`".join(searchKeys)+"`)"whereValuesString = "('"+"','".join(whereValues)+"')"setStringArray = []for key1 in sets:setString = ""for key2 in sets[key1]:if setString == "":setString = "`"+key1+"` = CASE WHEN (CONCAT"+searchKeysString+"='"+key2+"') THEN '"+sets[key1][key2]+"'"else:setString = setString + " WHEN (CONCAT"+searchKeysString+"='"+key2+"') THEN '"+sets[key1][key2]+"'"setString += " END "setStringArray.append(setString)setStrings = ",".join(setStringArray)whereStrings = whereKey + whereValuesStringupdateSql += setStringsupdateSql += whereStringsprint updateSqltry:cursor.execute(updateSql)result = cursor.fetchall()except Exception as e:print e.messageprint updateSqlconn.commit()conn.close()def insertAll(datas,table,searchKeys,ifIgnoreSearchKey):#多条数据同时添加if len(datas) == 0:returnconn = getConnection()cursor = conn.cursor()keys=[]for key in datas[0]:if key not in searchKeys or ifIgnoreSearchKey!= "1":keys.append(key)insertSql = "INSERT INTO "+table+" (`"+"`,`".join(keys)+"`) VALUES "valueStrings = []for data in datas:value = []for key in keys:value.append(data[key])valueString = "('" + "','".join(value) + "')"valueStrings.append(valueString)insertSql += ",".join(valueStrings)print insertSqltry:cursor.execute(insertSql)conn.commit()conn.close()except Exception as e:print insertSqlprint e.message

如果有帮到您,打个赏呗

python封装一个效率极高的 批量更新、插入合一的工具相关推荐

  1. 论文浅尝 | 一种嵌入效率极高的 node embedding 方式

    论文笔记整理:叶群,浙江大学计算机学院,知识图谱.NLP方向. 会议:WSDM 2019 链接:https://dl.acm.org/citation.cfm?id=3290961 Motivatio ...

  2. python封装一个requests请求

    python封装一个requests请求 更新:https://blog.csdn.net/qq_42846555/article/details/126401051 from requests im ...

  3. python socket能做什么_用python写一个聊天小程序!和女朋友的专属聊天工具!

    原标题:用python写一个聊天小程序!和女朋友的专属聊天工具! 1.UDP简介 Internet协议集支持一个无连接的传输协议,该协议称为用户数据报协议(UDP).UDP为应用程序提供了无需建立就可 ...

  4. 使用Python 封装一个简单的Mysql工具类

    pymysql操作mysql,虽然简单,但每次都要链接数据库,获取游标,关闭游标,关闭链接.这些操作无技术含量,还要重复编写!!想一想不如封装一个DBUtil,来提高开发效率. 要编写工具类首先要把公 ...

  5. 用python封装一个学生类

    #  封装一个学生类,(自行分辨定义为类属性还是实例属性) #  属性:身份(学生),姓名,年龄,性别,英语成绩,数学成绩,语文成绩, 职责. # 如果是类属性请提前定义, # 如果是实例属性请初始化 ...

  6. excel 复制数据 sql server 粘贴_一个Excel妙招,一个SQL技巧,解决批量数据插入问题

    #Excel技巧# #数据库# #MySQL# 业务背景 不知道您在工作中有没有遇到过这样几种情况: 业务定期给你一批数据结构相同的名单或者数据,要求你插入到库里并进行处理. 机器学习指标加工时,一个 ...

  7. mysql allowmultiqueries=true_Mysql批量更新的一个坑-allowMultiQueries=true允许批量更新(转)...

    实际上,我们经常会遇到这样的需求,那就是利用Mybatis批量更新或者批量插入,但是,实际上即使Mybatis完美支持你的sql,你也得看看你说操作的数据库是否支持,而阿福,最近就遇到这样的一个坑. ...

  8. Mysql批量更新的一个坑-allowMultiQueries=true允许批量更新

    前言         实际上,我们经常会遇到这样的需求,那就是利用Mybatis批量更新或者批量插入,但是,实际上即使Mybatis完美支持你的sql,你也得看看你说操作的数据库是否支持,而阿福,最近 ...

  9. spring boot- JdbcTemplate、NamedParameterJdbcTemplate基本使用(批量更新插入)

    文章目录 第一部分:JdbcTemplate 一.了解JdbcTemplate 二.JdbcTemplate使用步骤 1. sql直接插入一条数据 2. 通过Statement方式批量插入[推荐] 批 ...

最新文章

  1. java.util.concurrent.Callable 接口 源码
  2. [LeetCode]ZigZag Conversion
  3. java有 号_JAVA揭竿而起总要有名号
  4. 重启IIS和SqlServer的命令行
  5. 如何做一个合格的面试官?
  6. 17.立体匹配——匹配两个图 Matlab实战,立体效果_3
  7. Makingware调用静态块,实现自定义html内容的常用方法(不需要修改模版部分)...
  8. egon说一切皆对象--------面向对象进阶紫禁之巅
  9. null value in entry: destinationDir=null
  10. 女神节福利来了!(自动驾驶/三维重建/SLAM/点云/标定/深度估计/3D检测)
  11. 使用Tftpd64收集交换机日志
  12. Ubuntu20.04下opencv的安装
  13. 网络抓取ts文件转mp4_TS格式的视频文件怎么转换成mp4文件。
  14. validation
  15. 漂泊的旅途,云淡风轻
  16. 华为交换机命令 端口速率_华为S5700交换机的端口QOS限速问题
  17. 链接、图像、列表、计数器
  18. 2019北航计科保研夏令营(非优营)
  19. tensorflow踩坑
  20. python-23-递归:这帮小兔崽子

热门文章

  1. 成功解决 .Quit() File COMObject InternetExplorer.Application, line 2, in Quit pywintypes.com_error
  2. 成功解决AttributeError: 'map' object has no attribute 'items'
  3. TF:利用TF的train.Saver将训练好的W、b模型文件保存+新建载入刚训练好模型(用于以后预测新的数据)
  4. JAVA_OA(十四):SSM练手项目bug-Oracle分页web页面无法转到下一页
  5. GridSearchCV.grid_scores_和mean_validation_score报错
  6. 机器学习-特征工程中的特征选择
  7. Spring使用笔记(一)Spring简介
  8. es6 - foreach
  9. 使用dtd--属性声明
  10. 提高SQL语句的性能