Monday, December 12, 2011

SQLiteを用いて、iOSで高速全文検索をしよう


まえがき

ある日突然Twitterで@TeamMOSA2さんが@glassonion1さんのつぶやきをリツイットしてくれました。なんか面白そうなイベントだなと思って、 すぐにATNDに参加しました。時期が早かった!6人目になって、自動的に12月6日の担当になってしまいました。しかし、製作中のtuneTVの新しいバージョンがサブミット予定日辺りなので、無理やりに@glassonion1にお願いして、12月12日にリスケして頂きました。本当にありがとうございます。
前回は@happy_ryoさんの記事:XCodeからappCodeへ乗り換える8つの理由でした。面白い記事ので、ぜひご覧ください。
さて、今回僕の記事はSQLiteを使って、全文検索をする方法を紹介しようと思っています。皆さんに少し役に立てばと思います。

えぇ?SQLiteを使って全文検索ができるの?

SQLiteがFTSをサポートしていることを知らない開発者がいると思います。そして、iOSのアプリに全文検索をサポートしようと思っている開発者もいると思いますね。でも、SQLiteって本当に全文検索が出来ますか?
はい、答えはもちろんYESです。
そうじゃないと、この記事が成り立たないですね!
では、簡単にSQLiteのリリースログを見てみましょう。 1. SQLiteは2006年の10月9日にリリースしたVer 3.3.8に初めてFTS1 Betaを実験的にリリースした 2. 2007年1月4日、Ver 3.3.9にFTS2を追加した 3. 2007年11月27日、Ver 3.5.3にFTS3を追加した。その後FTS3が安定して、バグフィックスを中心として、更新されていた 4. 2010年12月8日、Ver 3.7.4にFTS4を追加した 5. 2011年4月12日、Ver 3.7.6にFTS4に圧縮したデータをサポートした

iOS既存のSQLiteライブラリは大丈夫?

ダメですね。iOS 5.0.1まで、既存のsqliteのライブラリはFTSをサポートしていません。しばらく先のバージョンに追加される見込みはないと思います。
では、なぜ、SQLiteがFTSをサポートしていることはあんまり聞いていなかったのでしょうか?それはAppleがiOSのでディフォルトのsqliteライブラリをコンパイルするとき、FTS機能をわざと消した訳です。
じゃ、どうすれば良いのでしょうか?
答えは一つしかないです。自分でSQLiteをコンパイルすることです。

どうすれば良い?

SQLiteは完全にCに書かれていたので、Xcode中でも簡単にコンパイルできます。コンパイルするとき、少しの設定が必要ですので、僕はその作業をまとめました。
それはsqliteFTSです。
XcodeのStatic Libraryの形に整えました。簡単に別のプロジェクトにドロップインしたら、使えます。

一番重要!本当に速いの?

開発者に関心してるのは「本当に速いの?」という事ですね。
もちろん僕もそれに一番関心しています。では、早速テスト用のアプリを作りました。
それはsqliteFTSTestです。
ちなみに、そのテストアプリはARCを使っていたので、iOS5の環境で実行してみてください。
僕のiPhone 4Sに実行してみましょう。テストを行うために、Jim Breenさんが作ったフリーの和英辞書EDictのデータを使っています。
合計19万件レコードの和英辞書ですが、簡単に(word, body)の組合でFTSのDBに読み込みました。wordは日本語単語です、bodyは英語の解釈です。
では、早速検索してみましょう。
bodyに"bed"を検索
↑bodyに”bed”を検索
bodyに"be*"を検索
↑bodyに”be*”を検索
bodyに"*be"を検索
↑bodyに”*be”を検索
wordに"アート"を検索
↑wordに”アート”を検索
wordに"あ*"を検索
↑wordに”あ*”を検索
wordに"*あ"を検索
↑wordに”*あ”を検索
wordに"電*"を検索
↑wordに”電*”を検索
wordに"*電"を検索
↑wordに”*電”を検索
注意: ここの実行時間は'SELECT COUNT(\*) from edict WHERE word MATCH ?;'の結果です。普段のDatabaseでは、その検索さえ速く行けません。
その結果、どうですか?デバイスでほとんど0.001秒前後と言うのは1000FPSでUIが更新されてもスムーズに動けます。(もちろん複雑な検索は遅くなる可能性があります)
iOSは普段30~60FPSの更新なので、0.02s~0.05sぐらいに検索出来れば十分ではないでしょうか? FTSの検索は普通のSQL文と組み合わせて、LIMITORDER BYなどと一緒に使えばもっと効率良いと思います。
FTSの具体的なドキュメントはSQLiteの公式サイトを見ればわかると思います。

さあ、使ってみよう!

さて、僕のサンプルをダンロードして、実機に転送して、やってみませんか?
SQLiteはPublic Domainに貢献しましたので、僕のサンプルコードも無料でApache License 2.0の形で公開します。
何かの質問・Feedbackがあれば、僕のTwitter、@TonnyXuまでご連絡ください。

次回の担当者は@haoyayoiさんです。ぜひご注目ください。

No comments:

Post a Comment