SQLite、手軽で便利なデータベースですが激しく使っていると速度が気になる時もあります。
SQLiteはインメモリデータベースもサポートしているので、既存のSQLiteのデータベースからインメモリ化して読み取り専用にすると早くなります。
データベース準備
適当に大きなデータベースを用意します。
#!/bin/env python
# coding:utf-8
import sqlite3
con=sqlite3.connect("test.db")
con.cursor().execute("CREATE TABLE test( key integer, val integer , primary key(key))")
con.commit()
for key in range(1,10000000+1):
con.cursor().execute("insert into test values(?,?)",(key,key+1,))
con.commit()
1000万レコードのデータベースを作成しました。
$ sqlite3 test.db
SQLite version 3.7.6.3
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> select count(*) from test;
10000000
プログラム
こちらを参考にプログラムを作成します。
#!/bin/env python
# coding:utf-8
import sqlite3
from StringIO import StringIO
import time
import random
# in memory化
con=sqlite3.connect("test.db")
tempfile=StringIO()
for line in con.iterdump():
tempfile.write("%s\n" % line)
tempfile.seek(0)
mcon=sqlite3.connect(":memory:")
mcon.cursor().executescript(tempfile.read())
mcon.commit()
mcon.row_factory=sqlite3.Row
current_milli_times = lambda: int(round(time.time() * 1000))
print "ready.."
# normal
# select 10000 times
N=10000
nstart=current_milli_times()
for i in range(N):
key=random.randrange(10000000)
res=con.cursor().execute("select * from test where key=?",(key,))
nend=current_milli_times()
print "normal:"+str(nend-nstart)
# inmemory
mstart=current_milli_times()
for i in range(N):
key=random.randrange(10000000)
res=mcon.cursor().execute("select * from test where key=?",(key,))
mend=current_milli_times()
print "inmemory:"+str(mend-mstart)
conのコネクションが通常のデータベースアクセス、mconがデータベースファイルをインメモリ化したものになります。10000回ランダムにSELECTしてみます。
結果
ready.. normal:414 inmemory:171
大学のスパコンで計算したのですが2倍以上の差が出ました。