我需要从一个巨大的表中读取数据(> 1百万行,16个原始文本)并对其进行一些处理。一行一行地阅读它看起来非常慢(python,MySQLdb),我希望能够一次读取多行(可能并行化)。
仅供参考,我的代码目前看起来像这样:
cursor.execute('select * from big_table')
rows = int(cursor.rowcount)
for i in range(rows):
row = cursor.fetchone()
.... DO Processing ...
我试图运行程序的多个实例来迭代表的不同部分(例如,第一个实例将遍历第一个200k行,第二个实例将遍历行200k-400k ......)但是问题是第二个实例(和第三个实例,依此类推)需要FOREVER才能进入开始查看行200k以后的阶段。它似乎仍然在处理第一个200k行而不是跳过它们。在这种情况下,我使用的代码(第二个实例)类似于:
for i in range(rows):
#Fetch the row but do nothing (need to skip over 1st 200k rows)
row = cur.fetchone()
if not i in range(200000,400000):
continue
.... DO Processing ...
如何加快这个过程?有没有一种干净的方法可以通过python从MySQL数据库中进行更快/并行的读取?
EDIT 1
:我根据以下建议尝试了“LIMIT”。出于某种原因,虽然当我在我的四核服务器上启动2个进程时,似乎一次只运行一个进程(CPU似乎是在这些进程之间共享时间,而不是每个核心运行一个单独的进程)。 2个python进程分别使用了14%和9%的CPU。有什么想法可能是错的吗?
答案 0 :(得分:2)
LIMIT
子句可以有两个参数,第一个是起始行,第二个是行数。
SELECT ...
...
LIMIT 200000,200000
答案 1 :(得分:1)
您也可能在数据库服务器上遇到i / o争用(即使您正在以块的形式获取数据,磁盘也需要在某种程度上序列化读取)。因此,不是并行读取mysql,而是单个读取可能对您更有效。
不是一次读取200K行,而是可以在一次命中中转储整个数据,并在python中处理内存中的数据(可能并行)。
可能您可以使用psycopg.copy_expert()
之类的内容。或者,在单个文件中执行mysql转储,并使用csv.reader
迭代它(如果您并行处理它,则使用它的部分)。
答案 2 :(得分:0)
您完全正确地尝试并行化第二个块是在开始处理之前请求前200k记录。您需要使用LIMIT
关键字来要求服务器返回不同的结果:
select * from big_table LIMIT 0,200000
...
select * from big_table LIMIT 200000,200000
...
select * from big_table LIMIT 400000,200000
...
等等。根据需要选择数字 - 但请注意,内存,网络和磁盘带宽可能无法为您提供完美的扩展。事实上,我要警惕同时启动两个或三个以上。