在进行数据库操作时,不可避免的问题是批量操作如何保证速度。有关这个问题我做了一组测试,下边直接上代码。
方式一:
long start = SystemClock.elapsedRealtime();
Log.i(TAG, "testInsert: 开始");
for (int i = 0; i < 9999; i++) {
Student student = new Student("" + i, 16 + i % 10);
DBHelper.getInstance().insertStudent(student);
}
Log.i(TAG, "testInsert: " + (SystemClock.elapsedRealtime() - start));
测试结果:
I/MainActivity: testInsert: 开始
I/MainActivity: testInsert: 13184
方式二:
long start = SystemClock.elapsedRealtime();
Log.i(TAG, "testInsert: 开始");
DBHelper.getInstance().getDb().beginTransaction();
for (int i = 0; i < 9999; i++) {
Student student = new Student("刘" + i, 16 + i % 10);
DBHelper.getInstance().insertStudent(student);
}
DBHelper.getInstance().getDb().setTransactionSuccessful();
DBHelper.getInstance().getDb().endTransaction();
Log.i(TAG, "testInsert: " + (SystemClock.elapsedRealtime() - start));
测试结果:
I/MainActivity: testInsert: 开始
I/MainActivity: testInsert: 366
测试表明开启事务的速度反而更快。
原因:
android.database.sqlite.SQLiteSession的类注释:
* <h2>Transactions</h2>
* <p>
<!--两种事务,隐式事务和显式事务-->
* There are two kinds of transaction: implicit transactions and explicit
* transactions.
* </p><p>
<!--重点-->
<!--重点-->
<!--重点-->
<!--当数据库操作没有显式事务时,会自动添加一个隐式事务,这个隐式事务只持续本次操作,然后会立刻结束,如果操作成功,就会提交事务-->
* An implicit transaction is created whenever a database operation is requested
* and there is no explicit transaction currently in progress. An implicit transaction
* only lasts for the duration of the database operation in question and then it
* is ended. If the database operation was successful, then its changes are committed.
* </p><p>
* An explicit transaction is started by calling {@link #beginTransaction} and
* specifying the desired transaction mode. Once an explicit transaction has begun,
* all subsequent database operations will be performed as part of that transaction.
* To end an explicit transaction, first call {@link #setTransactionSuccessful} if the
* transaction was successful, then call {@link #end}. If the transaction was
* marked successful, its changes will be committed, otherwise they will be rolled back.
* </p><p>
* Explicit transactions can also be nested. A nested explicit transaction is
* started with {@link #beginTransaction}, marked successful with
* {@link #setTransactionSuccessful}and ended with {@link #endTransaction}.
* If any nested transaction is not marked successful, then the entire transaction
* including all of its nested transactions will be rolled back
* when the outermost transaction is ended.
* </p><p>
* To improve concurrency, an explicit transaction can be yielded by calling
* {@link #yieldTransaction}. If there is contention for use of the database,
* then yielding ends the current transaction, commits its changes, releases the
* database connection for use by another session for a little while, and starts a
* new transaction with the same properties as the original one.
* Changes committed by {@link #yieldTransaction} cannot be rolled back.
* </p><p>
* When a transaction is started, the client can provide a {@link SQLiteTransactionListener}
* to listen for notifications of transaction-related events.
* </p><p>
* Recommended usage:
* <code><pre>
* // First, begin the transaction.
* session.beginTransaction(SQLiteSession.TRANSACTION_MODE_DEFERRED, 0);
* try {
* // Then do stuff...
* session.execute("INSERT INTO ...", null, 0);
*
* // As the very last step before ending the transaction, mark it successful.
* session.setTransactionSuccessful();
* } finally {
* // Finally, end the transaction.
* // This statement will commit the transaction if it was marked successful or
* // roll it back otherwise.
* session.endTransaction();
* }
* </pre></code>
* </p>
重点在于,如果没有开启显式事务,数据库会为每次操作添加一个默认的隐式事务。