FTS数据库优化(Android)原理与应用详解(2)

来源:互联网 发布:linux目录空间不足 编辑:程序博客网 时间:2024/05/21 17:27
3.在Android上FTS优化效果如何?——Android官方demo性能评测

接下来的问题就是FTS的优化效果如何了。先在Android官方demo的基础上做一些测试。demo中数据库是一个英文字典,单词条目998。Android/SQLite数据库本身的性能已经足够强悍,在这个量级下显然看不出差异。将数据规模扩大5000倍,即将998条数据循环插入数据库5000次:4990000。这个数据库规模已经远超牛津大辞典,据说牛津大辞典第二版一共有25万英文单词。与FTS PK的是一般的数据库表,同样只有两个字段。创建数据库代码:

        private static final String FTS_TABLE_CREATE =                    "CREATE VIRTUAL TABLE " + FTS_VIRTUAL_TABLE +                    " USING fts3 (" +                    KEY_WORD + ", " +                    KEY_DEFINITION + ");";        private static final String NO_FTS_TABLE_CREATE =                "CREATE TABLE " + NO_FTS_VIRTUAL_TABLE +                        " (" +                        KEY_WORD + " TEXT, " +                        KEY_DEFINITION + " TEXT);";        @Override        public void onCreate(SQLiteDatabase db) {            Log.i(TAG, "DictionaryOpenHelper.onCreate()");            mDatabase = db;            if (fts) {                mDatabase.execSQL(FTS_TABLE_CREATE);                loadDictionary();            } else {                mDatabase.execSQL(NO_FTS_TABLE_CREATE);                loadDictionary2();            }        }

loadDictionary()/loadDictionary2()分别将4990000条数据插入到FTS virtual table和一般table。再看一下query的逻辑,MATCH vs LIKE:

    /**     * Returns a Cursor over all words that match the given query     *     * @param query The string to search for     * @param columns The columns to include, if null then all are included     * @return Cursor over all words that match, or null if none found.     */    public Cursor getWordMatches(String query, String[] columns) {        if (TextUtils.isEmpty(query)) {            Log.i(TAG, "getWordMatches() : query is empty. return null.");            return null;        }        if (fts) {            String selection = KEY_WORD + " MATCH ?";            String[] selectionArgs = new String[]{query + "*"};            return query(selection, selectionArgs, columns);        } else {            String selection = KEY_WORD + " LIKE ?";            String[] selectionArgs = new String[]{query + "%"};            return query(selection, selectionArgs, columns);        }    }

先比对一下数据库的大小(db文件):

fts virtual table:647M

一般table:364.2M

可以看到FTS会造成数据库文件明显的膨胀。

再来比对一下数据库查询速度。因为不同的手机硬件配置不同,所以速度的绝对值无意义,只在相同的数据集合上做同样的query,耗时对比。

查询关键字FTS DB普通 DBa5645ms4396msb2678ms3931msg2749ms3874mscons(consumer前半部分)2003ms3938msconsumer(完整单词)165ms3807msprof(profile前半部分)998ms3880msprofile(完整单词)163ms3804ms

可以看到,整体上优化效果还是很明显的。相对比,发现

(1)query"a"的时候,FTS表现不佳,之后有明显优势。从结果集数量上看,"a"召回结果最多,"b""g"次之。

(2)就FTS的优势而言,单个字母<部分单词<整个单词,整个单词的query就已经有巨大的优势了。

但这对于普通DB并不公平,普通DB没有创建索引,增加索引再看看:

查询关键字FTS DB普通 DB普通DB+Indexa5645ms4396ms4232msb2678ms3931ms3892msg2749ms3874ms3864mscons(consumer前半部分)2003ms3938ms3903msconsumer(完整单词)165ms3807ms3799msprof(profile前半部分)998ms3880ms3862msprofile(完整单词)163ms3804ms3798ms

看到在这个测试数据集,普通DB+index提升不大。

那么引出一些问题:

(1)为什么FTS会有上述表现?

(2)普通DB的index为什么有上述表现?

本文接下来会先探究一下FTS。普通DB会再其他文章中继续研究。



0 0