日期:2014-05-16 浏览次数:20367 次
?
?Android OS中的DatabaseUtils.InsertHelper类提供的方法能够提高对sqlite数据库的insert速度 。但是,有关其使用的文档说明或者例子很少。希望这篇文章能有助于帮你揭开其神秘的面纱。
?????
我们经常有在SqliteOpenHelper的onCreate方法里面批量进行insert操作的情况,所以这个例子参照这种情景【已有隐式事务】
(批量处理意味着包含了有事务处理,我们知道,使用事务对程序的performance有影响,下面会有介绍)
假设onCreate方法如下:
private class DatabaseHelper extends SQLiteOpenHelper { @Override public void onCreate(SQLiteDatabase db) { ContentValues values = new ContentValues(); while (moreRowsToInsert) { // ... create the data for this row (not shown) ... // Add the data for each column values.put( "Greek" , greekData); values.put( "Ionic" , ionicData); // ... values.put( "Roman" , romanData); // Insert the row into the database. db.insert( "columnTable" , null , values); } } //... }?
?
使用DatabaseUtils.InsertHelper,则代码如下:
import android.database.DatabaseUtils.InsertHelper;
//...
private class DatabaseHelper extends SQLiteOpenHelper {
@Override
public void onCreate(SQLiteDatabase db) {
// Create a single InsertHelper to handle this set of insertions.
InsertHelper ih = new InsertHelper(db, "columnTable");
// Get the numeric indexes for each of the columns that we're updating
final int greekColumn = ih.getColumnIndex("Greek");
final int ionicColumn = ih.getColumnIndex("Ionic");
//...
final int romanColumn = ih.getColumnIndex("Roman");
while (moreRowsToInsert) {
// ... Create the data for this row (not shown) ...
// Get the InsertHelper ready to insert a single row
ih.prepareForInsert();
// Add the data for each column
ih.bind(greekColumn, greekData);
ih.bind(ionicColumn, ionicData);
//...
ih.bind(romanColumn, romanData);
// Insert the row into the database.
ih.execute();
}
}
//...
}
?
???? 由以上代码可以看出,InsertHelper的使用比SQLiteDatabase.insert稍微复杂一点。最主要的区别是使用InertHelper时,
在使用adding("binding")添加对应列数据之前调用iH.prrepareForInsert()方法,并且需要对应列的index,
这个index值是通过循环里面调用ih.getColumnIndex()而获得。用DatabaseUtils.InsertHelper替换SQLiteDatabase.insert之后的代码,效率提升上大致相当于每秒95行和每秒525行数据插入速度。
?? 实际上InsrtHelper并没有做什么神奇的事情,它只是预编译语句的包装类,并且你自已也可以通过?????????????????
SQLiteDatabase.compileStatement来实现,很多人应该知道InsertHelper使用起来很容易
其他提高insert速度的方法
除此之外,通过对以下两个方面的优化,可以让插入速度提高到900行每秒,当然,这些技巧的使用是否有效和你的程序也有很大关系
1.不要绑定空列
在我的程序,至少有50%的列是空值。碰到空值列,就不调用ih.bind()方法对它进行绑定,就我的程序而言,当列值为null或者空的字符串是,
有将近30%的性能提升
2.临时关闭sqlitedatabase的同步锁检查功能
我在SQLiteOpenHelper.onCreate的方法中load数据库,在此期间,假如只有一个线程访问databaser,那么就不需要sqlite进行同步访问检查
所以,调用SQLiteDatabase.setLockingEnabled(false)
暂时将锁检查关闭。这个措施可以有35%的速度提升
public void onCreate(SQLiteDatabase db) {
//...
try
{
// *Temporarily* (have I emphasized that enough?) disable
// thread locking in the database. Be sure to re-enable locking
// within a finally block.
db.setLockingEnabled(false );
// ... load the database ...
}
finally
{
db.setLockingEnabled(true );
}
?
事务和性能
很多人都知道显式使用事务控制的好处。??
然而,SQLiteOpenHelper在调用其回调函数(onCreate,onUpgrade,onOpen)之前已经创建了一个事务,因此,在这几个方法里面
没有必要显式声明一个事务控制(SQLiteOpenHelper默认事务已成功提交,除非方法里抛出exception)
如果insert操作不在SQLiteOpenHelper的上述回调方法中,那么你就可以使用显式的事务控制声明,主要使用的API有以下几个: