LoginSignup
8
8

More than 5 years have passed since last update.

AndroidでSQLiteはどこまで書くものか

Posted at

最近ちょっとしたきっかけがありまして、AndroidでSQLiteを触っていたときは、基本ロジックを入れなかったし、そういうサンプルなどもなかったなと思ったのですが、実際のところ、どういうバランスが良いのだろうか、と気になったのです。

というようなことをTwitterでつぶやいてみた所、大学時代のスパハカ先輩から、「重くなるからモバイル系では基本SQLはシンプルにするよ。」とのお言葉を賜りました。

じゃぁ、どの程度までが許されるのかなー、ということで、少し確認をしてみたのが、本稿です。

実行環境

  • Android 4.3 (Nexus 7 (2012))

実験

CREATE TABLE時にフィールドにCHECK制約を入れてみる。

テーブル

フィールド名 制約 備考
ID INTEGER primary key autoincrement ただのID
VALUE_INT INTEGER - int型のデータを受け取るだけ
VALUE_LONG INTEGER - long型のデータを受け取るだけ
VALUE_BOOL INTEGER VALUE_BOOL IN (0, 1) booleanとして1(true)とfalse(0)に制限
STRING_8 TEXT length(STRING_8) = 8 8 bytes 限定
STRING_100 TEXT length(STRING_100) = 100 100 bytes 限定
STRING_1000 TEXT length(STRING_1000) = 1000 1000 bytes 限定
STRING_LT_100 TEXT length(STRING_100) < 100 100 bytes 未満

コード

CHECK有りテーブル

SqlSampleData.java
public class SqlSampleData extends SampleData {
    public static final String CREATE_TABLE = ""
            + "create table " + TABLE_NAME + " ( "
            +           FIELD_ID                    + " integer primary key autoincrement "
            + ", " +    FIELD_VALUE_INT             + " integer " 
            + ", " +    FIELD_VALUE_LONG            + " integer "
            + ", " +    FIELD_VALUE_BOOL            + " integer "   + "check(" + FIELD_VALUE_BOOL + " IN (0, 1)) "
            + ", " +    FIELD_VALUE_STRING_8        + " text "      + "check(length(" + FIELD_VALUE_STRING_8 + ") = 8)"
            + ", " +    FIELD_VALUE_STRING_100      + " text "      + "check(length(" + FIELD_VALUE_STRING_100 + ") = 100)"
            + ", " +    FIELD_VALUE_STRING_1000     + " text "      + "check(length(" + FIELD_VALUE_STRING_1000 + ") = 1000)"
            + ", " +    FIELD_VALUE_STRING_LT_100   + " text "      + "check(length(" + FIELD_VALUE_STRING_LT_100 + ") < 100)"
            + " );";
}

CHECK無しテーブル

CodeSampleData.java
public class CodeSampleData extends SampleData {
    public static final String CREATE_TABLE = ""
            + "create table " + TABLE_NAME + " ( "
            +           FIELD_ID                    + " integer primary key autoincrement "
            + ", " +    FIELD_VALUE_INT             + " integer "
            + ", " +    FIELD_VALUE_LONG            + " integer "
            + ", " +    FIELD_VALUE_BOOL            + " integer "
            + ", " +    FIELD_VALUE_STRING_8        + " text "
            + ", " +    FIELD_VALUE_STRING_100      + " text "
            + ", " +    FIELD_VALUE_STRING_1000     + " text "
            + ", " +    FIELD_VALUE_STRING_LT_100   + " text "
            + " );";
}

親クラス

SampleData.java
public class SampleData {
    public static final String TABLE_NAME = "tab";

    public static final String FIELD_ID = "id";
    public static final String FIELD_VALUE_INT = "VALUE_INT";
    public static final String FIELD_VALUE_LONG = "VALUE_LONG";
    public static final String FIELD_VALUE_BOOL = "VALUE_BOOL";
    public static final String FIELD_VALUE_STRING_8 = "STRING_8";
    public static final String FIELD_VALUE_STRING_100 = "STRING_100";
    public static final String FIELD_VALUE_STRING_1000 = "STRING_1000";
    public static final String FIELD_VALUE_STRING_LT_100 = "STRING_LT_100";
}

確認方法

それぞれのテーブルに対し、条件に適合するデータでINSERTを実行する。
INSERT回数を100回、1000回、10000回とし、それぞれ10度繰り返して平均時間を算出。

CHECK有り : CHECK有りテーブルを利用し、Java側での検証無し。
CHECK無し : CHECK無しテーブルを利用し、Java側で同等の検証有り。

以下、確認結果はミリ秒。

確認結果

100回

回数 CHECK有り CHECK無し
1 71 91
2 108 82
3 71 56
4 66 77
5 102 81
6 69 57
7 97 91
8 99 82
9 66 59
10 77 85
平均 82.6 76.1

1000回

回数 CHECK有り CHECK無し
1 531 624
2 505 509
3 539 476
4 537 454
5 531 455
6 535 510
7 550 505
8 538 484
9 547 454
10 505 474
平均 531.8 494.5

10000回

回数 CHECK有り CHECK無し
1 4832 4814
2 4819 4473
3 4798 4563
4 4857 5030
5 4824 4421
6 5314 4303
7 5257 4614
8 4989 4446
9 4927 4545
10 4855 4306
平均 4947.2 4551.5

まとめ

すべてにおいて、CHECK無しの方がCHECK有りの92%程度の時間となりました。
スパハカ先輩のお言葉通り、SQLに検証ロジックを入れると性能が落ちるのは確かなようです。

ただ、今回の検証では8%程度の劣化なので、扱うデータ量が少なく、一回のトランザクションで何レコードも扱わないのであれば、SQLに検証を入れていても問題にならないと思います。
少しの差ですが、記述するコード量も減るのではないかと。

一方、大量のデータを一度に扱う場合は、多少といっても差が大きくなってくるので、Java側での検証実装にしなければいけないでしょう。

後は、今回はあまりまじめにやっていないのですが、検証に失敗するデータがを扱う可能性が高い場合は、Java側の検証ではじいた方が性能は良くなるはずなので、そことの兼ね合いも出てくるのかな、と思います。

8
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
8