我正在使用 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()
这样,文本文件中的 50,000 行现在需要大约 40 秒。所以,我在总时间上增加了 11%,但是,内存是恒定的,这更重要。