スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

AndroidにおけるSQLiteを使いやすくする Vol.1

AndroidはSQLite3に対応しており、(ただし、外部キー制約がサポートされていないバージョン)
これを利用することでデータ管理の自由度が高まります。

Androidでは連想配列方式で手軽にデータ管理ができるプリファレンスというものがあるため、意外に使わないことも多いかも知れませんが、プリファレンスは大量のデータ管理には向いていないということと、RDBのようにトランザクション処理を行うことができないので、そのような管理を行いたい場合はやはりSQLiteを利用する必要が出てきます。

ただし、SQLiteは他のRDBと比べて非常に癖のあるシステムです。Oracle, MySQL, PostgreSQLと同じように使っていると大きくパフォーマンスに影響を及ぼす可能性が多々あります。

また、そもそもAndroidそのものがSQLiteは使いやすくしていません。JDBCで組んでいるのとそれほど大差がないため、ソースも乱雑になりがちで、保守もしにくいといった大きな問題を抱えています。

これについては、DB操作をしやすくしたよいフレームワークが存在しないことが一番大きいかと思われます。
一応ORMLiteというO/Rマッピングをサポートしたライブラリがありますが、これは専用のActivityを利用しなければいけなかったり、そもそもAndroidのライフサイクルを考慮しきれていなかったりして、使い勝手に問題があります。

というわけで結局自作!という話になっていくのですが、
これについては長くなるので次回以降に回すとして、
まずはAndroidにおけるSQLiteの問題点について洗いだしてみようかと思います。


01. INSERTやUPDATEが遅い

これはSQLite特有の仕様です。
SQLiteは他のRDBとは異なり、1つのファイルにデータを書き込むRDBです。
そして、INSERTやUPDATEを行うと、fsync()と呼ばれる関数が実行され
結果をファイルへ書き込みます。

これが1回であれば影響はありませんが、例えば10000回INSERTやUPDATEを行うとなると、10000回ディスクアクセスが発生するということになります。ディスクI/Oが大きなボトルネックとなることは皆様もご存知だと思われますが、まさにそのディスクI/Oが大量に発生するために遅くなっているわけです。

じゃあどうすればいい?ということですが、SQLiteにおいてはトランザクション中はこのfsync()が実行されないため、大量の書き込み処理を行う場合は常にトランザクション処理を行うようにします。

こうすることで、理論上はMySQLに近い、またはそれに匹敵する速度を出すことも可能になります。これは何も10000回などの複数回処理を行う場合だけでなく、1回のINSERT、UPDATEにおいてもトランザクション中に処理させることで速度を上げることが出来ます。

そのため、INSERTやUPDATEを行う場合は、常にトランザクション処理を行うようにしましょう。


02. SQLiteDatabaseクラスがイマイチ

Androidでデータベース処理を行う場合に、上記クラスを利用しますが、実はこいつがあまり良く出来たクラスではありません。具体的なポイントを挙げると

・JDBCっぽい組み方をしなければならず、O/Rマッピングツールを利用しがちなWeb系プログラマには相当な苦痛
・SQLiteのトランザクションを開始する beginTransaction メソッドが、「BEGIN EXCLUSIVE」固定となっているため、マルチスレッドプログラミングを利用していると「database is locked」みたいなエラーが発生することがある

どうにも一からすべて作り直したい衝動に駆られてしまいますが、そんなことをしたら大変なことになるので、使えるところだけは使うように上手くお付き合いします。

幸いにも、これらの問題は、O/Rマッピングツールの自作や、SQLiteDatabaseのラッピングをしてしまえば解決しますので、詳しい解決方法は次回以降にポイントを説明させて頂きます。


03. Cursorが遅い

Cursorとは SQLiteDatabase クラスで rawQuery メソッドなどでSELECT文を実行したときに、返却されたレコード1つ1つにアクセスするためのクラスです。これが遅いということは、大量のデータをSELECTすることには向いていないということにもなります。なので、大量のデータを取り出すときに UIスレッドでそのまま実行することはANR発生に繋がる問題となりますので、別スレッドで実行させるようにしたいところです。

とはいえ、プログラム的に問題なくてもUX(User Experience Design)的にはどうなのか?といわれると、何秒も待たされるのはやっぱり苦痛ですよね。なので、このあたりはアプリのUI設計がモノを言います。50件以上は「次のページ」ボタンを設けるなど、ある程度制限を掛けて少しずつユーザに見せていく方がUX的には満足度が高い傾向があります。

なので、「全レコードを一気に取り出す」なんてことはプログラム的に問題なくてもUX的には問題ありなのでオススメできません。LIMIT文やOFFSET文を利用して、約50レコードずつ表示していくようなUIにするように心がけましょう。




簡単ではありましたが、以上3つのポイントがSQLiteと付き合うためのちょっとしたポイントになります。
次回はこれらの問題を解決していくための、O/Rマッピングツールの作成についてご紹介します。
スポンサーサイト
プロフィール

Author:Kou
モバイル関連の開発ばかりやってる人のブログです。たまにWebもやります。

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QR
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。