なら@はてなブログ

福岡で働くスマートフォンエンジニア(おっさん)のブログ。更新頻度がとにかく低いのが悩み。

SQLiteに大量の初期データを登録したい

Androidアプリのお話。
軽いアプリを作るだけならあんまり気にしなくていい話ですが、本格的というか大量のデータを使うアプリを作ろうと思ったら、やはりデータベースは避けては通れないわけで。
で、開発者の方ならご存知の通り、AndroidにはSQLiteが組み込まれています。


データベースを作って、マスタデータ的なものを登録しておきたいところなのですが、Androidアプリのお作法だと、だいたいSQLiteOpenHelperでデータベースを作成したり定義更新したり、ってのが一般的ですね。
それだと、初回起動時にデータベースを作成して、初期データをえんえんINSERTし続けるという処理が必要になってきます。そしてSQLiteのINSERTは遅いです。しかも、登録元のデータをWebサーバから落としたりする仕様だと、ネットワークとデータベースのコストがそのままユーザのストレスにつながります。


さて、どうしよう?


いくつか案があるのですが、まずは通信コストをなくす方向。
登録元データをアプリに同梱します。たぶんassetsあたりに入れるのが正しいのかなー? これが第1案として。


第2案。SQLiteデータベースのファイルをあらかじめ作っておいて(データベース作成してINSERTまでやっておく)、それを同じようにassetsにおいて端末なりSDカードなりにコピーする方法。


で、双方ともメリット・デメリットがあります。
前提として、assetsに置いたファイルはアプリ起動後に更新できません。削除もできません。なので、初期データ登録後はゴミファイルが残ることになります。


第1案のメリットは圧縮効率。たとえば、元データをCSVファイルにしてzip圧縮すれば、かなりサイズは小さくなります。
カラム数とかサイズも関係しますが、一例として、20万レコードくらいのデータがCSVで約4MB、zip圧縮したら700KBくらい。
デメリットは、結局はデータベース作ってINSERTせなあかんので、初期登録のレスポンスが悪い。上記の例だと2分くらい。


第2案のメリット・デメリットは、そのまま第1案の逆。
圧縮効率は悪いです。上記と同じデータだと、SQLiteデータベースファイルの状態で約6.5MB。CSVより大きいですね。で、圧縮したら2MB。圧縮効率もテキストのCSVに劣ります。
メリットは初期データ登録が速いこと。zip圧縮したファイルを端末に解凍して配置するだけなので、ほんの数秒です。
あ、デメリットもういっこあった。SQLiteOpenHelperが使いづらい(使えないわけではない)。普通にやったら使えないと思います。SQLiteDatabase.openOrCreateDatabase()とかを使うことに。


試していませんが、おそらく事前にデータベースファイルを作るとき、Androidアプリ内でSQLiteOpenHelper使って作っておけば、データベースのバージョン管理とかもできそうな気がします。
ちなみに、別パッケージで作ったSQLiteファイルでも、使いたいアプリに同梱して展開すれば普通に読み込めます。Androidアプリって、各種パーミッションはOSのファイルパーミッションでやってるので、そのファイル自体を自分のアプリで作成してしまえば問題なくアクセスできるかと。



いや、データそんなに多くないのであれば、普通にサーバから元データ落としてくるのが一番簡単だと思いますけどね。



うわ、今回文字ばっかや。