Android Sqlite优化

部分内容来自网络。

1,建表优化

拆分数据表,可以通过外键等方式尽量减少数据条目。

2,建立索引

关于数据库索引的原理为什么建立索引可以加快查询速度请看 http://kb.cnblogs.com/page/45712/

建立索引的语句

1
CREATE INDEX index_name ON table_name;

创建单例索引

1
CREATE INDEX index_name ON table_name (column_name);

索引会额外增加空间,另外对插入,更新,删除等操作因为需要更新索引,所以反而导致性能问题。

  

3,显式使用事务


在Android中,无论是使用SQLiteDatabase的insert,delete等方法还是execSQL都开启了事务,来确保每一次操作都具有原子性,使得结果要么是操作之后的正确结果,要么是操作之前的结果。

然而事务的实现是依赖于名为rollback journal文件,借助这个临时文件来完成原子操作和回滚功能。既然属于文件,就符合Unix的文件范型(Open-Read/Write-Close),因而对于批量的修改操作会出现反复打开文件读写再关闭的操作。然而好在,我们可以显式使用事务,将批量的数据库更新带来的journal文件打开关闭降低到1次。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private void insertWithTransaction(SQLiteDatabase db) {
int count = 0;
ContentValues values = new ContentValues();
try {
db.beginTransaction();
while (count++ < 100) {
values.put(TableDefine.COLUMN_INSERT_TIME, System.currentTimeMillis());
db.insert(TableDefine.TABLE_RECORD, null, values);
}
db.setTransactionSuccessful();
} catch (Exception e) {
e.printStackTrace();
} finally {
db.endTransaction();
}
}

4,编译sql语句

Android封装了ContentValues,但是查看源码可以看到,ContentValues在最终执行时也会编译SQL语句,也就是批量操作时,使用ContentValues时会导致多次编译sql语句,所以对于一些批量插入的情况可以用SQLiteStatement,提前编译。

比如下面这样

1
2
3
4
5
6
7
8
9
10
11
12
private void insertWithPreCompiledStatement(SQLiteDatabase db) {
String sql = "INSERT INTO " + TableDefine.TABLE_RECORD + "( " +
TableDefine.COLUMN_INSERT_TIME + ") VALUES(?)";
SQLiteStatement statement = db.compileStatement(sql);
int count = 0;
while (count < 100) {
count++;
statement.clearBindings();
statement.bindLong(1, System.currentTimeMillis());
statement.executeInsert();
}
}

5,Sqlite语句优化

因为sqlite实现原理问题,有些sql查询可以优化

比如在sqlite中between,or,like等语句不能使用索引,另外一些常见的sql优化,比如嵌套查询时,通常是先查出一个表,再在这个表的基础上做二次查询,此时因为新查出来的表没有建立索引,所以会比较慢,可以尽量展开为对已有索引的查询。sqlite官方有文档说明,请看The SQLite Query Planner

6,其他

调整ContentValues容量

SQLiteDatabase提供了方便的ContentValues简化了我们处理列名与值的映射,ContentValues内部采用了HashMap来存储Key-Value数据,ContentValues的初始容量是8,如果当添加的数据超过8之前,则会进行双倍扩容操作,因此建议对ContentValues填入的内容进行估量,设置合理的初始化容量,减少不必要的内部扩容操作。

减少查询的数据量,按需查询

getColumnIndex耗时问题,可以直接编码数据库的列数,尽量少用getColumnInex

使用异步