2012年8月6日月曜日

SQLiteの高速化:クエリのトランザクションは本当に有効か測定してみた

書籍「Androidアプリ高速化プログラミング」の輪講会に参加しています。

Androidアプリ高速化プログラミング















先日の第1章の輪読の際に、クエリの高速化の項で気になった点があったので検証を行ってみました。

  1. 書籍の主張:クエリの高速化
  2. 書籍の主張:推論
  3. 性能測定してみる(条件など)
  4. 性能測定してみた
  5. まとめ(?)
  6. 参考(計測に利用したクラス)


  1. 書籍の主張:クエリの高速化

気になった記述は、以下の箇所です。

第1章 Javaコードの最適化 (P.36) 1.7.3 クエリ
複数のトランザクションを使う場合、iterateBothColumns()は61ミリ秒かかるが、iterateFirstColumn()は23ミリ秒で実行される。すべての行を1つのトランザクションにまとめると、すべての行の処理にかかる時間はさらに短くなる。iterateBothColumns()は11ミリ秒かかるが、iterateFirstColumn()は7ミリ秒で実行される。
iterateXXColumn()は、SQLiteデータベースに対してクエリを発行するメソッドであり、それぞれ、カラムを指定しない場合、する場合で処理速度に差が発生するという内容なのですが、それに対する説明で、「すべての行を1つのトランザクションにまとめると」という記載があり、性能がさらに改善する上記の記述があります。


  2. 書籍の主張:推論

上記、書籍の主張ですが、輪読会でも全レコードを一括で取得するクエリに対して、「すべての行を1つのトランザクションにまとめると」というのがイメージがつかないよねーという話になりました。

推論1:
一回のクエリでもトランザクションを制御することで処理速度が向上する(そんなバカな)


推論2:
Selectクエリでもトランザクションが開始、終了しており、複数回のクエリをひとつのトランザクションにまとめることで処理速度が向上する。

以下、各推論に対して処理速度の計測を行ってみました。


  3. 性能測定してみる(条件など)

以下の条件でクエリの性能測定を行ってみました。

環境

Android:2.3.3
機種:エミュレータ


テーブル構造

テーブル名:cheese ※世界のチーズ一覧を格納します。
レコード数:650件

カラム名
idINTEGER ※インデックスカラム
nameTEXT
originTEXT


測定パターン

いずれも全件に対するクエリを発行。
取得対象のカラムと、トランザクション制御の違いを検証します。

取得方法トランザクション制御
全レコード(一括)AutoCommitあり
全レコード(一括)AutoCommitなし
各レコードAutoCommitあり
各レコードAutoComitなし


  4. 性能測定してみた

全レコードを一括で取得















全レコードを一括で取得(Where句なしのSelect文)では、トランザクション制御を手動で行った場合のほうが、処理時間が長くなってしまいました。

いずれもクエリ回数は一回であるため、トランザクションを操作するオーバヘッドが差につながったのではないかと推測されます。

推論1は、あえなく崩れました。
それでは、書籍のトランザクションをまとめて扱うとはどういうことなのでしょうか。
おそらく、下記のパターン(推論2)のことを言っているのではないでしょうか。


全レコードを個別に取得















全レコードを個別に取得(Where句にIDを指定し、レコード数だけループで全件取得)では、トランザクション制御をループの前後のみで行った場合のほうが処理時間が短くなりました。

このことからSelect文を複数発行する場合、ひとつのトランザクションとして扱ってあげるほうが性能の向上が見込めることがわかります。

ただし、処理時間自体は、クエリの回数が増えているため、一括で取得する場合に比べて大幅に増加してしまっています。
書籍のような7ミリ秒での実行からは離れてしまいました。


  5. まとめ(?)

複数回のクエリに対してトランザクションをまとめることが処理性能に有効だということは確認できました。

ただし、検証の結果、ますます書籍の言っていることがわからなくなってしまうという情けない結果になってしまいました。とほほ…。

書籍でいうような処理速度改善の方法があればアプリに適用したいのですが…。

検証結果、書籍の内容について、アドバイス等いただければ幸いです。


  6. 参考(計測に利用したクラス)

性能測定で利用したクラスです。

これらのTaskを別途準備した計測用のクラスに渡して計測を行いました。

こういう計測を行ったほうが効果的だよというのがあればご指摘もらえればと思います。


以上です。

0 件のコメント:

コメントを投稿