我正在使用Python 2.7和SQLite。我正在构建一个包含数百万行的数据库。我希望只在必要时才将数据写入磁盘,以提高性能。我的想法是只定期调用commit()。我已经尝试了下面的代码。中间的查询显示我们获得了一致的读取结果。但是,当我查看硬盘时,我看到了一个名为example.db-journal的文件。这必须是数据被缓存的地方。在这种情况下,这对性能没有任何好处。有没有办法让插入操作先收集到内存中,然后再刷新到磁盘上?有更好的方法吗?
import sqlite3
conn = sqlite3.connect('example.db')
c = conn.cursor()
c.execute('CREATE TABLE if not exists stocks (date text, trans text, symbol text, qty real, price real)')
c.execute("INSERT INTO stocks VALUES ('2006-01-05','BUY','RHAT',100,35.14)")
c.execute("INSERT INTO stocks VALUES ('2006-01-05','BUY','RHAT',100,35.14)")
t = ('RHAT',)
c.execute('SELECT date, symbol, trans FROM stocks WHERE symbol=?', t)
# Here, we get 2 rows as expected.
print c.fetchall()
c.execute("INSERT INTO stocks VALUES ('2006-01-05','BUY','RHAT',100,35.14)")
c.execute("INSERT INTO stocks VALUES ('2006-01-05','BUY','RHAT',100,35.14)")
c.execute("INSERT INTO stocks VALUES ('2006-01-05','BUY','RHAT',100,35.14)")
c.execute("INSERT INTO stocks VALUES ('2006-01-05','BUY','RHAT',100,35.14)")
c.execute("INSERT INTO stocks VALUES ('2006-01-05','BUY','RHAT',100,35.14)")
conn.commit()
t = ('RHAT',)
c.execute('SELECT date, symbol, trans FROM stocks WHERE symbol=?', t)
# Here, we get all the rows as expected.
print c.fetchall()
conn.close()
更新:
如果有人遇到这个问题,我想给出一些代码的更新。我正在处理来自文本文件的5+百万行数据,并需要一个地方存储数据以供进一步处理。我最初将所有数据存储在内存中,但是内存不够用。因此,我切换到SQLite作为磁盘缓存。我的原始内存版本处理每50,000行的原始文本文件需要大约36秒。
经过测量,我第一次尝试使用SQLite进行批处理的版本需要大约660秒才能处理50,000行数据。根据评论(感谢发布者),我编写了以下代码:
self.conn = sqlite3.connect('myDB.db', isolation_level='Exclusive')
self.cursor.execute('PRAGMA synchronous = 0')
self.cursor.execute('PRAGMA journal_mode = OFF')
此外,我承诺在处理完1000行文本文件后提交。
if lineNum % 1000 == 0:
self.conn.commit()
因此,这样一来,从文本文件中提取的5万行现在只需要约40秒。 所以,虽然整体时间增加了11%,但是内存是恒定的,这更为重要。