java - 尝试提高 Sqlite 中批量插入的速度。

标签 java android sqlite

我有一个databaseHelper类,其中有以下功能:

public SQLiteDatabase returnDB(){

        return DBHelper.getWritableDatabase(); 
    }

在我的主类中(异步任务 - onPreExecute):

            dbHelper = new DBAdapter(getApplicationContext());
            dbHelper.open(); 

            mDb = dbHelper.returnDB(); 
            mDb.beginTransaction();

在 doInBackground 中,我处理查询如下:

dbHelper.insert(dateToInsert, CONTACT_NAME, String.valueOf(days), String.valueOf(hou), CONTACT_IMAGE_URI, String.valueOf(min),String.valueOf(mon), String.valueOf(secon), CONTACT_ID, String.valueOf(weeks), String.valueOf(years));

然后在onPostExecute中:

mDb.endTransaction();
dbHelper.close();

但是,当我尝试在执行异步任务后立即将值提取到 ListView 中时,出现数据库锁定错误。下面是 LogCat:

02-08 14:40:06.587: E/SQLiteLog(6394): (5) database is locked
02-08 14:40:06.588: D/SQLiteConnection(6394): executeForString took 2505ms - failed, sql="PRAGMA journal_mode", exception="database is locked (code 5): , while compiling: PRAGMA journal_mode"
02-08 14:40:06.602: E/SQLiteDatabase(6394): Failed to open database '/data/data/com.exa.birthdayrem/databases/Bdr'.
02-08 14:40:06.602: E/SQLiteDatabase(6394): android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5): , while compiling: PRAGMA journal_mode
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:882)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteConnection.executeForString(SQLiteConnection.java:627)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteConnection.setJournalMode(SQLiteConnection.java:313)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteConnection.setWalModeFromConfiguration(SQLiteConnection.java:287)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:215)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:860)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:221)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:224)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at com.exa.birthdayrem.DBAdapter.returnDB(DBAdapter.java:156)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at com.exa.birthdayrem.LoaderClass$MagicCall.onPostExecute(LoaderClass.java:457)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at com.exa.birthdayrem.LoaderClass$MagicCall.onPostExecute(LoaderClass.java:1)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.os.AsyncTask.finish(AsyncTask.java:631)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.os.AsyncTask.access$600(AsyncTask.java:177)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.os.Handler.dispatchMessage(Handler.java:99)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.os.Looper.loop(Looper.java:153)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at android.app.ActivityThread.main(ActivityThread.java:5000)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at java.lang.reflect.Method.invokeNative(Native Method)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at java.lang.reflect.Method.invoke(Method.java:511)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:821)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:584)
02-08 14:40:06.602: E/SQLiteDatabase(6394):     at dalvik.system.NativeStart.main(Native Method)

我这样做对吗?但我没有看到太多的性能提升?

最佳答案

以下是如何在 DatabaseHelper 中处理事务的示例。您需要确保 Helper 仅创建一次,例如通过使其成为单例。为了同时获得多个读取器的更好性能,您可以将 ReentrantLock 替换为 ReadWriteLock。

DbHelper helper = new DbHelper();

private void DoSimpleInsert()
{
    helper.InsertA(items);
}

private void DoComplexInsert()
{
    helper.BeginTransaction();
    helper.InsertA(items);
    helper.InsertB(items);
    helper.EndTransaction();
}

public class DbHelper
{
    private SQLiteDatabase db;
    private boolean isExpliciteTransaction;
    private ReentrantLock lock = new ReentrantLock();

    public void BeginTransaction()
    {
        isExpliciteTransaction = true;
        db.beginTransaction();
    }

    public void EndTransaction()
    {
        isExpliciteTransaction = false;
        db.endTransaction();
    }

    public void InsertA(ClassA[] items)
    {
        lock.lock();
        try
        {
            if (!isExpliciteTransaction)
            {
                db.beginTransaction();
            }

            // Do the inserts here

            if (!isExpliciteTransaction)
            {
                db.endTransaction();
            }
        }
        finally
        {
            lock.unlock();
        }
    }

    public void InsertB(ClassB[] items)
    {
        lock.lock();
        try
        {
            if (!isExpliciteTransaction)
            {
                db.beginTransaction();
            }

            // Do the inserts here

            if (!isExpliciteTransaction)
            {
                db.endTransaction();
            }
        }
        finally
        {
            lock.unlock();
        }
    }
}

关于java - 尝试提高 Sqlite 中批量插入的速度。,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21644132/

相关文章:

java - 插入后无法从 SQLite 中找到列

java - 什么以及如何将 Java Swing 概念与云相关?

java - GIWS 在构建类时终止进程

java - ArrayList 中的对象

java - 2 个不同订阅的消息顺序

Android WebView : Should shouldInterceptRequest be triggered by XmlHttpRequest

android - SQLite FTS 表上的普通 SELECT

android - 旋转后防止EditText聚焦

java - 通过 Android 套接字发送和接收字节两个问题 :

cocoa - 修改通过核心数据映射的 sqlite 数据库会引发错误 : uncaught exception of class 'NSCFString'