【发布时间】:2014-01-21 22:12:45
【问题描述】:
我正在尝试从数据库中提取大量数据并将其写入 csv 文件。我试图找出最快的方法是什么。我发现在 fetchall 的结果上运行 writerows 比下面的代码慢 40%。
with open(filename, 'a') as f:
writer = csv.writer(f, delimiter='\t')
cursor.execute("SELECT * FROM table")
writer.writerow([i[0] for i in cursor.description])
count = 0
builder = []
row = cursor.fetchone()
DELIMITERS = ['\t'] * (len(row) - 1) + ['\n']
while row:
count += 1
# Add row with delimiters to builder
builder += [str(item) for pair in zip(row, DELIMITERS) for item in pair]
if count == 1000:
count = 0
f.write(''.join(builder))
builder[:] = []
row = cursor.fetchone()
f.write(''.join(builder))
编辑:我正在使用的数据库对于我工作的小公司来说是独一无二的,所以很遗憾我无法提供这方面的太多信息。我正在使用 jpype 连接数据库,因为唯一的连接方式是通过 jdbc 驱动程序。我正在运行 cPython 2.7.5;很想使用 PyPy,但它不适用于 Pandas。
由于我要提取如此大量的行,所以我对使用 fetchall 犹豫不决,因为担心内存不足。 row 具有相当的性能,并且更容易看,所以我想我会使用它。非常感谢!
【问题讨论】:
-
哪个数据库?哪个接口库?你能给我们一个表模式和一些数据吗?
-
例如:对于某些数据库,
fetchone从服务器一次获取一行(或者,更好的是,一次获取一个充满行的缓冲区),这使其效率更高而不是fetchall,它显然会获取所有这些,这意味着在它们都准备好之前你不能做任何工作,而且你也可能会浪费很多工作来为它们分配和管理内存。但在其他情况下,fetchone在幕后(实际上)是fetchall,所以没有优势,实际上是一个小幅放缓。 -
此外,如果任何数据中有任何制表符、换行符或其他特殊字符,您的代码将生成损坏的 CSV 文件。这可以接受吗?
-
了解您正在使用哪个数据库系统来回答这个问题至关重要。一般来说,从数据库端创建表可能会更好,这样您就不必担心将其引入 Python 的开销。我猜最快会像stackoverflow.com/questions/1517635/…那样使用COPY
标签: python database performance