4

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% を追加しましたが、メモリは一定であり、これはより重要です。

4

2 に答える 2

1

あなたの場合、自動コミットモードで db 接続を作成しています。つまり、ステートメントを実行するたびINSERTに、データベースはトランザクションを開始し、ステートメントを実行してコミットします。したがって、あなたcommitは - この場合 - 無意味です。python docs の sqlite3 を参照してください

しかし、大量の行を挿入することは、理想的にはトランザクション内で行う必要があることは正しいです。これは、すべての着信INSERTステートメントをジャーナル ファイルに記録する必要があることを接続に通知しますが、トランザクションがコミットされるまでデータベース ファイルへの書き込みを遅らせます。実行は I/O 操作によって制限されますが、ジャーナル ファイルへの書き込みによってパフォーマンスが大幅に低下することはありません。

于 2013-05-15T19:00:09.200 に答える