1

我刚刚将数据库从SQLite更改为SQLCipher。我的应用程序变得令人难以置信的缓慢。它需要很长的时间来采取点击行动。 我研究,发现这些可能有两个原因:Android应用程序停止响应SQLCipher

  • 不要反复打开和关闭连接,密钥推导是非常昂贵的,由设计。频繁地打开/关闭数据库连接(例如,对于每个查询)是性能问题的一个常见原因,通常可以使用单例数据库连接轻松解决。

  • 使用事务来包装插入/更新/删除操作。除非在事务处理范围内执行,否则每个操作都会发生在它自己的事务中,这会使事情减慢几个数量级。

关于第一点,有人可以解释一下,反复打开和关闭连接意味着什么。我想我使用SQLiteDatabase db = this.getWritableDatabase("secure_key);为每个查询是问题。任何关于如何使用单例数据库连接类的例子都是非常有帮助的。

关于第二点,如何使用包装器提供的查询,它会有用吗?

回答

0

关于点1)DBHelper内的以下代码创建了单例连接(注意,我只关闭主活动的onDestroy方法中的数据库)。

/** 
* Instantiates a new Db helper. 
* 
* @param context the context 
*/ 
DBHelper(Context context) { 
    super(context, DBConstants.DATABASE_NAME, null, 1); 
} 

private static DBHelper instance; 

/** 
* Gets helper. 
* 
* @param context the context 
* @return the helper 
*/ 
static synchronized DBHelper getHelper(Context context) { 
    if(instance == null) { 
     instance = new DBHelper(context); 
    } 
    return instance; 
} 

和您使用以下方法来得到你的帮助: -

dbhelper = DBHelper.getHelper(context); 
    db = dbhelper.getWritableDatabase(); 

关于2使用,db.beginTransaction();开始交易,db.setTransactionSuccessful();将其标记为成功进行数据库更改后( 这是交易应用所必需的,否则,结束交易将有效抵消应用)和db.endTransaction();的任何更改以完成交易。 请注意,事务不会嵌套,因此在嵌套事务时,您必须添加代码,以便beginTransaction,setTransactionSuccessfullendTransaction仅应用一次。

后续是迎合了嵌套的例子: -

void deleteAisle(long aisleid, boolean intransaction) { 

    if (doesAisleExist(aisleid)) { 
     if (!intransaction) { 
      db.beginTransaction(); 
     } 

     String whereargs[] = {Long.toString(aisleid)}; 
     // Delete ProductUsage rows that have Aisle as a parent 
     pudeletes = db.delete(
       DBProductusageTableConstants.PRODUCTUSAGE_TABLE, 
       DBProductusageTableConstants.PRODUCTUSAGE_AISLEREF_COL + 
         " = ?", 
       whereargs 
     ); 

     // More done here but removed for brevity (including deletion of the Aisle) 

     if (!intransaction) { 
      db.setTransactionSuccessful(); 
      db.endTransaction(); 
      msg = "DB Transacion SET and ENDED for Aisle ID=" + Long.toString(aisleid); 

     } 
    } 
} 

以上可以单独调用,但如果要删除一个店,然后它可以被多次调用,在这种情况下,将带*号被称为*事务**是真实的(所以beginTransaction,setTransactionSuccessfulendTransaction将被跳过,并由父母完成)。

至于实用性,如果一起执行多个操作,则只能使用事务。