SQLiteのインメモリモードとファイルモードの性能を比較してみた


  • 簡単なベンチマークプログラムを用いてインメモリモードとファイルモードのCRUDの性能を比較

概要

ふと「SQLiteってインメモリモードとファイルモードでどれくらい性能差があるのか?」という疑問が浮かんだので、なるべく時間をかけずにベンチマークコードを書いて試してみた。せっかくなので結果を共有する。

結果

単位は秒。10回実施した平均値を示す。

Mac/SSD

  機種ID: MacBookPro10,2
  プロセッサ名:   Intel Core i5
  プロセッサ速度:    2.5 GHz
  メモリ:    8 GB
# 操作 ファイルモード インメモリモード
1 100万行のbulk-insert 6.290 5.835
2 1行をinsert 0.247 0.225
3 文字列カラムでソート 0.221 0.195
4 数値カラムでソート 0.238 0.175
5 文字列・数値でフィルタ 0.008 0.007
6 更新 0.130 0.086
7 削除 0.186 0.127

Windows/HDD

プロセッサ: Intel Core i7-7700
プロセッサ速度: 3.6 GHz
メモリ: 32 GB
# 操作 ファイルモード インメモリモード
1 100万行のbulk-insert 4.655 3.417
2 1行をinsert 0.285 0.132
3 文字列カラムでソート 0.209 0.185
4 数値カラムでソート 0.242 0.220
5 文字列・数値でフィルタ 0.009 0.007
6 更新 0.556 0.105
7 削除 0.781 0.127

ベンチマークコード

Githubで公開している。

以下は抜粋。

db.create_all()
sw = StopWatch()
sw.start()

entities = [dict(
    text1=random_text(3),
    text2=random_text(3),
    number1=random(),
    number2=random(),
) for i in range(args.records)]
sw.wrap('generate {0} records'.format(args.records))

db.session.execute(ItemMapper.__table__.insert(), entities)
db.session.commit()
sw.wrap('bulk insert {0} records'.format(args.records))

del entities

item = ItemMapper()
item.text1 = 'aaa'
item.text2 = 'bbb'
item.number1 = 0.1
item.number2 = 0.2
db.session.add(item)
db.session.commit()
sw.wrap('insert 1 records')

result1 = ItemMapper.query.order_by(ItemMapper.text1, ItemMapper.text2).offset(1000).limit(20).all()
sw.wrap('select order by text1, text2 offset 1000 limit 20')

result2 = ItemMapper.query.order_by(ItemMapper.number1, ItemMapper.number2).offset(1000).limit(20).all()
sw.wrap('select order by number1, number2 offset 1000 limit 20')

result3 = ItemMapper.query.filter(ItemMapper.text1.startswith('a')) \
    .filter(ItemMapper.number1 > 0.5).offset(1000).limit(20).all()
sw.wrap('select where text1 like a* and number1 > 0.5 offset 1000 limit 20')

ItemMapper.query.filter(ItemMapper.text1 == 'aaa').update(dict(text1='bbb'))
db.session.commit()
sw.wrap('update text1 bbb where text1==aaa')

ItemMapper.query.filter(ItemMapper.text1 == 'bbb').delete()
db.session.commit()
sw.wrap('delete where text1 == bbb')

sw.describe()
reports.append(sw.get_report())

db.drop_all()