用Python逐行处理非常大的900M行MySQL表
我经常需要使用Python逐行处理MySQL表中的数亿行。我想要一个健壮且不需要监视的脚本 下面我粘贴了一个脚本,用于对我所在行消息字段的语言进行分类。它使用sqlalchemy和MySQLdb.cursors.SSCursor模块。不幸的是,这个脚本在远程运行4840行和本地运行42000行之后,始终抛出一个“查询期间与MySQL服务器的连接丢失”错误 另外,根据对这个stackoverflow问题的回答,我已经在我的MySQL服务器的/etc/MySQL/my.cnf文件上检查了max_allowed_packet=32M 任何关于修复此错误或使用另一种方法以健壮的方式使用Python处理非常大的MySQL文件的建议都将不胜感激用Python逐行处理非常大的900M行MySQL表,python,mysql,sqlalchemy,mysql-python,bigdata,Python,Mysql,Sqlalchemy,Mysql Python,Bigdata,我经常需要使用Python逐行处理MySQL表中的数亿行。我想要一个健壮且不需要监视的脚本 下面我粘贴了一个脚本,用于对我所在行消息字段的语言进行分类。它使用sqlalchemy和MySQLdb.cursors.SSCursor模块。不幸的是,这个脚本在远程运行4840行和本地运行42000行之后,始终抛出一个“查询期间与MySQL服务器的连接丢失”错误 另外,根据对这个stackoverflow问题的回答,我已经在我的MySQL服务器的/etc/MySQL/my.cnf文件上检查了max_al
import sqlalchemy
import MySQLdb.cursors
import langid
schema = "twitterstuff"
table = "messages_en" #900M row table
engine_url = "mysql://myserver/{}?charset=utf8mb4&read_default_file=~/.my.cnf".format(schema)
db_eng = sqlalchemy.create_engine(engine_url, connect_args={'cursorclass': MySQLdb.cursors.SSCursor} )
langid.set_languages(['fr', 'de'])
print "Executing input query..."
data_iter = db_eng.execute("SELECT message_id, message FROM {} WHERE langid_lang IS NULL LIMIT 10000".format(table))
def process(inp_iter):
for item in inp_iter:
item = dict(item)
(item['langid_lang'], item['langid_conf']) = langid.classify(item['message'])
yield item
def update_table(update_iter):
count = 0;
for item in update_iter:
count += 1;
if count%10 == 0:
print "{} rows processed".format(count)
lang = item['langid_lang']
conf = item['langid_conf']
message_id = item['message_id']
db_eng.execute("UPDATE {} SET langid_lang = '{}', langid_conf = {} WHERE message_id = {}".format(table, lang, conf, message_id))
data_iter_upd = process(data_iter)
print "Begin processing..."
update_table(data_iter_upd)
,
[使用SSCursor时,]在
已获取整个结果集
这篇文章说,如果您发出另一个查询,您将得到一个“命令顺序错误”错误,这不是您看到的错误。因此,我不确定以下内容是否一定能解决您的问题。尽管如此,还是值得尝试从代码中删除SSCursor
,并使用更简单的默认游标来测试这是否是问题的根源
例如,您可以在SELECT
语句中使用LIMIT chunksize OFFSET n
要以块的形式循环遍历数据集,请执行以下操作:
import sqlalchemy
import MySQLdb.cursors
import langid
import itertools as IT
chunksize = 1000
def process(inp_iter):
for item in inp_iter:
item = dict(item)
(item['langid_lang'], item['langid_conf']) = langid.classify(item['message'])
yield item
def update_table(update_iter, engine):
for count, item in enumerate(update_iter):
if count%10 == 0:
print "{} rows processed".format(count)
lang = item['langid_lang']
conf = item['langid_conf']
message_id = item['message_id']
engine.execute(
"UPDATE {} SET langid_lang = '{}', langid_conf = {} WHERE message_id = {}"
.format(table, lang, conf, message_id))
schema = "twitterstuff"
table = "messages_en" #900M row table
engine_url = ("mysql://myserver/{}?charset=utf8mb4&read_default_file=~/.my.cnf"
.format(schema))
db_eng = sqlalchemy.create_engine(engine_url)
langid.set_languages(['fr', 'de'])
for offset in IT.count(start=0, step=chunksize):
print "Executing input query..."
result = db_eng.execute(
"SELECT message_id, message FROM {} WHERE langid_lang IS NULL LIMIT {} OFFSET {}"
.format(table, chunksize, offset))
result = list(result)
if not result: break
data_iter_upd = process(result)
print "Begin processing..."
update_table(data_iter_upd, db_eng)
对我来说好像是超时了。您是否尝试过调整和/或?