Mysql高效插入/更新数据
从tushare抓取到的财务数据,最开始只是想存下来,用的办法想简单点,是:插入--报错—update
但发现这个方法太蠢,异常会导致大量无效连接,改为:
for idx,row in d2.iterrows(): try: rs=db.getData("select f_Code,f_Time,%s from caiwu where f_Code=:1 and f_Time=:2"%fldname,row["code"],dat) if len(rs)==0: db.doNonQuery("insert into caiwu (f_Code,f_Time,%s) values(:1,:2,:3)"%fldname,row["code"],dat,row[colname]) else: if rs[0][2] is None: db.doNonQuery("update caiwu set %s=:1 where f_Code=:2 and f_Time=:3"%fldname,row[colname],row["code"],dat) except: log.errorlogger().exception("数据入库错误!")
运行没啥大问题,但就是太慢,取两年数据,万条左右,一早上还没全部入库。只得研究优化,结果发现mysql居然有专门的语法,可以插入记录,遇到重复记录则为自动更新:
ON DUPLICATE KEY UPDATE
上面的处理直接用一条sql语句就解决了:
INSERT INTO TABLE (a,c) VALUES (1,3) ON DUPLICATE KEY UPDATE c=c+1;
然后再进一步,批量入库也没问题,还能分别处理:
INSERT INTO TABLE (a,b,c) VALUES (1,2,3), (2,5,7), (3,3,6), (4,8,2) ON DUPLICATE KEY UPDATE b=VALUES(b);
简直不要太方便:
#数据入库: # d2:待入库dataframe,第一列为code,第二列为数值 # dat:时间 # fldname:数据在库中的字段名 def addtodb(d2,dat,fldname): i=0 while i<len(d2): kvs=reduce(lambda x,y:"%s%s('%s' , '%s' , %s)"%(x,"" if x=="" else ",",y[0],dat,y[1]),d2.values[i:i+1000],"") sqlstr="insert into caiwu (f_Code,f_Time,%s) values %s ON DUPLICATE KEY UPDATE %s=VALUES(%s)"%(fldname,kvs,fldname,fldname) try: db.doNonQuery(sqlstr) except: log.errorlogger().exception("数据入库错误!") i+=1000
测试,基本上瞬间入库!