[英]Fastest way to write database table to file in python
我正在嘗試從數據庫中提取大量數據並將其寫入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
具有可比的性能,並且在眼睛上要容易得多,所以我想我會使用它。 謝謝一群!
有了您給我們的一些支持,就很難再具體了,但是…
我已經將您的代碼包裝為一個函數,並編寫了三個替代版本:
def row():
with open(filename, 'w') as f:
writer = csv.writer(f, delimiter='\t')
cursor = db.execute("SELECT * FROM mytable")
writer.writerow([i[0] for i in cursor.description])
for row in cursor:
writer.writerow(row)
def rows():
with open(filename, 'w') as f:
writer = csv.writer(f, delimiter='\t')
cursor = db.execute("SELECT * FROM mytable")
writer.writerow([i[0] for i in cursor.description])
writer.writerows(cursor)
def rowsall():
with open(filename, 'w') as f:
writer = csv.writer(f, delimiter='\t')
cursor = db.execute("SELECT * FROM mytable")
writer.writerow([i[0] for i in cursor.description])
writer.writerows(cursor.fetchall())
請注意,最后一個是您說過嘗試的一個。
現在,我編寫了這個測試驅動程序:
def randomname():
return ''.join(random.choice(string.ascii_lowercase) for _ in range(30))
db = sqlite3.connect(':memory:')
db.execute('CREATE TABLE mytable (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR)')
db.executemany('INSERT INTO mytable (name) VALUES (?)',
[[randomname()] for _ in range(10000)])
filename = 'db.csv'
for f in manual, row, rows, rowsall:
t = timeit.timeit(f, number=1)
print('{:<10} {}'.format(f.__name__, t))
結果如下:
manual 0.055549702141433954
row 0.03852885402739048
rows 0.03992213006131351
rowsall 0.02850699401460588
因此,在我的測試中,您的代碼花費的時間幾乎是調用fetchall
和writerows
兩倍!
但是,當我對其他數據庫重復進行類似的測試時, rowsall
速度要比manual
速度快20%到15%(從不慢40%,但rowsall
可快15%)…但是row
或rows
總是比manual
速度快得多。
我認為這是因為您的自定義代碼比csv.writerows
要慢得多,但是在某些數據庫中,使用fetchall
而不是fetchone
(或只是迭代游標)會大大降低速度。 對於內存中的sqlite3數據庫而言,這並非如此,原因是fetchall
與fetchone
做着所有相同的工作,然后一次向您提供列表。 對於遠程數據庫, fetchone
可能會執行任何操作,從獲取所有行到一次獲取緩沖區,一次到獲取一行,這可能會比fetchall
慢或快得多,具體取決於您的數據。
但是對於真正有用的解釋,您必須准確地告訴我們您正在使用哪個數據庫和庫(以及哪個Python版本-CPython 3.3.2的csv
模塊似乎比CPython 2.7.5和PyPy 2.1快很多。 /2.7.2似乎也比CPython 2.7.5還要快,但是任何一個都可能也可以更快地運行您的代碼……),依此類推。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.