批量更新mysql数据库数据

任务:

数据库有多篇文档(file),每篇文档有多个段落(para),每个段落有多个句子(sentence),现在是要为250万个句子标注句子位置信息(第n句第m句话标为m-1)

方法一:

使用python脚本,对于每句话用update语句进行数据更新,用时1天多

sen_index = 0
last_para = 0
last_file_id = 0
for i,a_data in data:
    para = a_data['para']
    file_id = a_data['file_id']
    sentence_id = a_data['id']
    if para == last_para and file_id == last_file_id:
        sen_index += 1
    else:
        sen_index = 0
        last_para = para
        last_file_id = file_id
    执行update的SQL,更新sentence_id对应的sen_index 

方法二:导出数据再导入

1、将数据导出至txt,用时约为60s

(注:Excel 的行列数不能超过 1,048,576 行和 16,384 列的限制。)

2、使用python对数据进行编辑,几秒搞定

f = open('res.csv','r')
text = f.read()
f.close()
data = text.split('\n')

sen_index = 0
last_para = 0
last_file_id = 0
res_data = [data[0]]
for a_data in data[1:]:
    cols = a_data.split(',')
    if len(cols) < 4:
        break
    para = cols[2]
    file_id = cols[1]
    s_id = cols[0]
    if para == last_para and file_id == last_file_id:
        sen_index += 1
    else:
        sen_index = 0
        last_para = para
        last_file_id = file_id
    cols[3] = str(sen_index)
    res_data.append(','.join(cols))

f = open('dst.csv', 'w')
f.write('\n'.join(res_data))
f.close()

3、再将数据导入到数据库中,大约需要450秒

方法三:使用update case when 语句

#接方法二,循环体最后一句话改为res_data.append(cols)
from pymysql import *
batch = 10000
conn = connect(host='localhost', port=3306, database='db', user='root',
                   password='root', charset='utf8')

res_data = res_data[1:]
for i in range(len(res_data)//batch+1):
    sub_data = res_data[i*batch:(i+1)*batch]
    if len(sub_data) <= 0:
        break
    condition = ' '.join([f'when {a_data[0]} then {a_data[3]}' for a_data in sub_data])
    where = ','.join([a_data[0] for a_data in sub_data])
    sql = f'update table set sen_index = (case id {condition} end) where id in ({where})'
    cs1 = conn.cursor()
    cs1.execute(sql)
    conn.commit()
    cs1.close()

conn.close()

运行这段代码需要大约1800s

注:update语句后面必须跟where,这是因为不加where会锁定全表,降低查询效率(更新1000条数据需要100s,加上where需要0.13s),甚至还会让系统误认为发生了死锁。

参考资料:https://www.cnblogs.com/ldj3/p/9288187.html

下面方法不可行:

更新语句,id必须连续,用时大约1000s,结果只能更新所有为0的行

因为更新时会先产生临时表,更新临时表的数据时不会使原表数据立即生效,只有等所有数据更新完成后才会更新原表数据

UPDATE ner_sentence_temp t1
INNER JOIN ner_sentence_temp t2 ON t1.id - 1 = t2.id
SET t1.para_index = (
	CASE
	WHEN t1.para_order = t2.para_order
	AND t1.file_id = t2.file_id THEN
		t2.para_index + 1
	ELSE
		0
	END
)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值