はじめに
ソーシャルゲームのローカルリソースバージョンを管理する際にLiteDBとSQLiteどちらが高速なのか気になったので、ベンチマークしてみることにしました。
ソーシャルゲームのリソースは運用が長くなると数が多くなり、管理するレコード数も増加していきます。
主に管理するデータはダウンロード済みかどうかとダウンロード済みの場合最新のリソースとバージョンがあっているかを確認するためのハッシュ値です。
アプリ起動時にすべてのリソースのバージョン確認、ダウンロードが一つ完了するたびにバージョン情報の更新がはいるので速度が重要になってきます。
今回の検証で使用したプロジェクトはGitHubにあげておきました。
レコード数が100,10000,100000のケースで計測してみます。
Meanが平均時間になるのでこちらが一番重要な結果です。
使用パッケージ
ベンチマーク
LiteDB
SQLiteNet
InsertBulk(一括挿入)
Method | insertCount | Mean | Error | StdDev | Median | Min | Max |
---|---|---|---|---|---|---|---|
LiteDBInsert | 100 | 12.98 ms | 0.457 ms | 1.333 ms | 12.50 ms | 10.63 ms | 16.48 ms |
SQLiteInsert | 100 | 18.56 ms | 0.440 ms | 1.270 ms | 18.35 ms | 16.54 ms | 22.15 ms |
LiteDBInsert | 10000 | 325.93 ms | 6.463 ms | 10.975 ms | 326.41 ms | 296.67 ms | 342.32 ms |
SQLiteInsert | 10000 | 84.65 ms | 6.556 ms | 18.706 ms | 79.68 ms | 60.74 ms | 140.95 ms |
LiteDBInsert | 100000 | 4,613.43 ms | 91.210 ms | 235.442 ms | 4,543.66 ms | 4,176.39 ms | 5,163.66 ms |
SQLiteInsert | 100000 | 615.54 ms | 12.134 ms | 9.473 ms | 615.57 ms | 599.93 ms | 629.06 ms |
GetAllRecords(全レコード取得)
100レコードの時の単位がμsと小さかったため、別々に計測結果を出しました。
100レコード
Method | Mean | Error | StdDev | Min | Max |
---|---|---|---|---|---|
LiteDBGetCollection | 901.8 us | 17.47 us | 18.69 us | 874.2 us | 946.9 us |
SQLiteGetCollection | 659.4 us | 13.05 us | 28.08 us | 618.0 us | 741.3 us |
10,000レコード
Method | Mean | Error | StdDev | Min | Max |
---|---|---|---|---|---|
LiteDBGetCollection | 33.45 ms | 0.418 ms | 0.391 ms | 32.57 ms | 33.98 ms |
SQLiteGetCollection | 13.90 ms | 0.277 ms | 0.647 ms | 12.99 ms | 15.66 ms |
100,000レコード
Method | Mean | Error | StdDev | Min | Max |
---|---|---|---|---|---|
LiteDBGetCollection | 375.1 ms | 6.99 ms | 6.54 ms | 367.0 ms | 386.0 ms |
SQLiteGetCollection | 143.7 ms | 2.18 ms | 1.93 ms | 140.7 ms | 147.8 ms |
Find&Update(レコード更新)
Method | insertCount | Mean | Error | StdDev | Median | Min | Max |
---|---|---|---|---|---|---|---|
LiteDBUpdateCollection | 100 | 11.70 ms | 0.360 ms | 0.956 ms | 11.66 ms | 9.308 ms | 14.33 ms |
SQLiteUpdateCollection | 100 | 13.99 ms | 0.461 ms | 1.238 ms | 13.75 ms | 11.749 ms | 18.25 ms |
LiteDBUpdateCollection | 10000 | 11.37 ms | 0.243 ms | 0.648 ms | 11.47 ms | 9.852 ms | 13.18 ms |
SQLiteUpdateCollection | 10000 | 15.46 ms | 0.893 ms | 2.549 ms | 14.58 ms | 12.668 ms | 22.13 ms |
LiteDBUpdateCollection | 100000 | 12.70 ms | 0.492 ms | 1.370 ms | 12.38 ms | 10.353 ms | 16.77 ms |
SQLiteUpdateCollection | 100000 | 14.09 ms | 0.479 ms | 1.302 ms | 13.82 ms | 11.359 ms | 18.18 ms |
考察
検証する前はLiteDBのほうが高速かと思っていましたが、大量のレコードに対してはSQLiteのほうが高速のようです。
大量のレコードのInsertはSQLiteが圧勝しています。
全レコード一括取得に関してはどのレコード数でもSQLiteが勝っていますが、100レコードの場合はどちらもμsなのでゲームアプリ上ではあまり問題にならない速度です。
Updateに関してはLiteDBのほうが高速ですがあまり差はありません。
トータルで見ると少ないレコード数はLiteDB、大量のレコード数の場合はSQLiteを使用するのがよさそうです。
また、LiteDBはNoSQLで、RDBのSQLiteより柔軟な形でデータを保存することができるためローカルセーブに向いている思います。
(ソーシャルゲームでゲームに関するデータを大量にローカルに持つことはないので)
最後に
初めてBenchmarkDotNetを使用して計測したため、正確な計測結果ではないかもしれませんがご了承ください。
Unityの場合、ローカルセーブにはEasySaveというアセットがあるのでパフォーマンスの面ではLiteDBを使用するよりこちらのほうが高速かもしれません。
ソーシャルゲームでよく利用されるReadOnlyのマスタデータに関してはMasterMemoryで管理するのが良いと思います。
ローカルリソースのバージョン管理にSQLiteを使用するのはどうかなと思っていましたが、今回の検証結果からSQLiteを使用するのは割と良い選択だと思いました。