続JSONをSQLiteで置き換えた時の話
前回の記事が予想以上に反応を頂いたので、少し補足します。
ユースケース
記事中ではあまり書いていなかったのですが、基本的に参照系のデータが対象になります。
サーバー側で生成しておいたDBをそのまま使う形です。
なので更新系のデータについては別DBに保存してます。
SQLiteのATTACH DATABASEを使えば、異なるDB(別のファイル)でもJOINが使えるので、 CoreDataで作ったSQLiteのファイルも問題なく扱えます。
ただ、DBのサイズが大きくなりすぎると通信に時間が掛かり過ぎるため、 そのような場合は従来通りAPI経由でJSONなりXMLを使う方がよいです。
他にも日本のネットワーク環境を前提にしているので、通信が遅い環境では別の配慮が必要になります。
あと、ブラウザでは残念ながら使えないと思います。
SQLiteのDBをDOMストレージに突っ込んで、JavaScriptでSQLiteのDBを扱う処理を自前で実装すれば不可能でないとは思いますが、現実的とは思えません。
ただ、拡張機能なら使えるかもです。
また、当然ですがURLを調べればデータは簡単に取得できます。
私自身は試していませんが、恐らく暗号化も可能なので、暗号化ができれば多少安心はできるかと。
その場合は暗号化のバージョン依存など、別の問題がでるかも知れませんが。。。
他に思いつくのは通信を暗号化した上で、認証を入れるとかかな。 いずれにしても、クリティカルなデータの扱いには向かないと思います。
サーバーリソースを削減したい
そもそもこの発想がでてきたのは、サーバーリソースを節約したいということがありました。
アプリの場合、急にアクセスが増えてサーバーがパンクするということが考えられるので、 サーバー側で定期的に生成したデータをおいておく形を採用しました。
AWSなり使えば急なトラフィックも捌けますが、個人のアプリでそこまで費用を掛けられないという事情も存在します。
なるべくサーバーリソースを使わないようにしながらも、利便性を損なわない方法を探した結果思いついた方法です。
サーバー側の処理をクライアント側にもってきているだけです。
今思えば最近のWeb業界のような、サーバー側の処理がクライアント側で実装されるようになったことと近いのかも知れません。
用途は限定的ですが、大規模なサービスでも上手く使えればかなりのサーバーリソースを削減できると思います。
定期配信しているニュースアプリなんかは相性がよさそうです。
ファイルサイズについて
通信時の転送量を少なくするために圧縮するのは常套手段なので、JSONやMessagePack利用時にも使ってました。
ファイルサイズ自体はさほど問題ではなくて、データを取り扱う時の手間を省けるのがこの手法の最大の利点です。
同じデータなのにソートや絞込で毎回通信が発生することを考えると、ローカルにデータに持っておけばいいんじゃね?という話です。
先にも書いた通り参照系での利用が前提なので、使えるケースは限定的ですがJSONで扱うには大きすぎるデータ量の場合は選択肢に入ると思います。
また、SQLiteのDBファイルもJSONなどと同様にgzipによる圧縮は有効です。
私のケースではSQLiteのファイルサイズが1/3ぐらいになりました。
圧縮率が高ければ展開にも時間が掛かるので、その辺のチューニングが必要なのもJSON同様です。
JSONの代替になるのか?
自アプリと自サーバー間という、コントロールが可能な範囲であればSQLiteを選択肢にいれるというのはアリと思いますが、
JSONを置き換える形になるとまでは思いません。
元記事の書き方が少し悪かったのですが、JSONがダメな子と言っているのではなく、 JSONで扱い辛いケースがでてきた時にSQLiteという選択肢もあるよという話です。
異なるプラットフォームや言語間でのやりとりについては、依然としてJSONやXMLが扱いやすいと思います。
何でもかんでもSQLiteにしておけばいいということではなく、ケースバイケースで選択すればよいかと。
API用途ではJSONの方が扱いやすいですし、アニマネでも用途に応じて使い分けています。
アプリでの実装について
DBファイルをコピー中にデータを参照したりするとクラッシュするので、データ取り込み時のロック処理は実装が必要になります。 バックグラウンドでDBファイルをダウンロードして、ダウンロード後に元々あったDBを参照していないタイミングでファイルを置き換えています。
1年ぐらい運用していますが、この方法でクラッシュしたことはないので、恐らく大丈夫と思います。
あと、データ量が少ないと当然ながら必要最低限のJSONを表示した方が動作速度は早いです。
Realmは?
Realmは軽く試しただけですが、とても良さそうなので、同様の方法は使いたいと思っています。 現在のところRealmはサーバーサイドで生成ができないので、サーバーサイドで作れるようになったら、SQLiteから置き換える選択肢もあります。
Swiftがオープンソースになってサーバーサイドで使えるようになったら使えるんじゃないかと思って期待しています。
長期的なメンテナンスについて
サーバーとクライアント間でバージョンの違いによる問題が発生する可能性はあります。
実際に導入して1年ぐらいたった現在の所は問題がでていませんが、互換性の問題がでてきた場合はアプリ側にサーバー側が合わせる形がベターかと思います。
JSONやXMLのようにシンプルなデータフォーマットであれば互換性の問題はほぼないですが、 DBの場合は懸念すべき材料となります。
ただ、SQLiteという枯れた技術だからこそ、そのようなリスクが少なく運用できると考えています。 個人的にはRealmみたいな新しいDBだと躊躇します。
最後に
ブコメやTwitterで色々な意見を頂きありがとうございます。 賛否両論といったところですが、勉強になります。
通常なら突飛なアイデアに思われるのは承知していますが、 既存の枯れた技術でも使い方次第で、まだまだ新しい事ができる可能性があるという一例と思って頂ければ。
ちなみにですが、アニマネでは全てのデータをSQLiteでやりとりしているのではなく、MessagePackやXMLも併用しています。
何も考えずにアプリとサーバー間のやりとりをJSONなどの既存の方法でやりとりするのではなく、 目の前の課題を解決するためにあれこれ工夫するのがエンジニアリングの楽しいところと考えています。
他にも何かあれば追記するかもです。
さらに追記しました。