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()
アップデート:
誰かがこの問題に遭遇した場合に備えて、いくつかのコードで更新を行うと考えました。テキスト ファイルから 500 万行以上を処理しており、さらに処理するためにデータを保存する場所が必要でした。もともとメモリ内にすべてのデータがありましたが、メモリが不足していました。そこで、ディスク キャッシュを SQLite に切り替えました。元のメモリ内バージョンの処理では、元のテキスト ファイルから 50,000 行あたり約 36 秒かかりました。
測定後、バッチ処理の SQLite バージョンでの最初のカットは、50,000 行で約 660 秒かかりました。コメントに基づいて (ポスターのおかげで)、次のコードを思いつきました。
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% を追加しましたが、メモリは一定であり、これはより重要です。