JAVAでSQLiteを使う(glassfish)

WEBサービスで使う機械学習のモデルを実現するためにJAVAのヒープを使うっていう話もあったが、
メモリに頼ったやり方だとモデルが巨大化していった時にスケールしにくいし、ユーザ0のうちから金がかかるのは微妙。
なので、SQLite+ヒープのキャッシュで賄う方向性について模索中。


■ 環境構築
glassfishを使う場合、管理コンソールでの特別な設定は不要。
たぶんあれはプールしたいときに必要。でも、たしかどっかの記事でSQLiteではコネクションをPoolする意味ないみたいなのを読んだ気がする。

jarはここから最新のを落として、
xerial / sqlite-jdbc / Downloads — Bitbucket
以下の3箇所に配置。たぶん全部は必要ない。おいたらGlassfishのdomain再起動が必要。
・src/lib/以下
・略glassfish-4.1/glassfish/lib/
・略glassfish-4.1/glassfish/domains/domain1/lib/
古いjarバージョンだと、readonlyモードに切り替えられなくてハマった。
それと、複数の異なるバージョンを同じディレクトリに置かないほうがいい。


pom.xml

<dependency>
            <groupId>sqlite-jdbc-3.8.10.1.jar</groupId>
            <artifactId>sqlite-jdbc-3.8.10.1.jar</artifactId>
            <version>3.8.10.1</version>
            <scope>system</scope>
            <systemPath>${basedir}/src/lib/sqlite-jdbc-3.8.10.1.jar</systemPath>
        </dependency>

■ 実験
main.java

            Class.forName("org.sqlite.JDBC");
            SQLiteConfig config = new SQLiteConfig();
            config.setReadOnly(true);
            conn = DriverManager.getConnection("jdbc:SQLite:" + DB_PATH, config.toProperties());
            // check
            System.out.println("readonly:" + conn.isReadOnly());

            // test
            //...時間のかかるSQL文

同時に読み込みできるかtest

ab -n 2 -c 2 http://localhost:8080/TEST/rest/test

readOnlyモードが無効だった時はコンソールに「[SQLITE_BUSY] The database file is locked (database is locked) 」がでていたが、うまくいくと2つ以上のアクセスを同時にさばくことができた。



ーー
次に1つのスレッドがINSERTする中で、複数のREAD ONLYな処理を捌けるのかを確かめてみる.
非ReadOnlyモードで1秒間に2回INSERTを行い続ける中で、別のスレッドで数十秒レベルのSELECTをReadOnlyモードで行い続けた。
その結果、SELECT文の時間が1.5倍くらいになったものの、ロックエラーはでることはなくなった。