Android-приложение перестает отвечать на запросы SQLCipher
Я только что изменил свою базу данных с SQLite на SQLCipher. И мое приложение стало невероятно медленным. Чтобы сделать щелчок мышью, нужны годы. Я изучил и выяснил эти две возможные причины:
Не открывайте и не закрывайте соединения повторно, так как получение ключей очень дорого по своему замыслу. Частое открытие / закрытие соединения с базой данных (например, для каждого запроса) является очень распространенной причиной проблем с производительностью, которые обычно могут быть легко решены с помощью одноэлементного соединения с базой данных.
Используйте транзакции, чтобы обернуть операции вставки / обновления / удаления. Если не выполнено в области транзакции, каждая операция будет происходить в пределах ее собственной транзакции, которая замедляет вещи на несколько порядков.
Что касается первого пункта, может кто-нибудь объяснить, что это значит, открывая и закрывая соединения повторно. Я думаю, что я использую SQLiteDatabase db = this.getWritableDatabase("secure_key);
для каждого запроса это проблема. Любой пример того, как я могу использовать класс соединения с одноэлементной базой данных для этого, очень поможет.
Что касается второго пункта, как я могу использовать обертку для упомянутых запросов и будет ли она полезна?
1 ответ
В отношении пункта 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
, setTransactionSuccessfull
а также endTransaction
применяются только один раз.
Ниже приведен пример, который обслуживает вложения:-
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);
}
}
}
Выше может быть вызвано индивидуально, но если удалить магазин, то он может быть вызван несколько раз, и в этом случае он будет вызван, если **intransaction ** имеет значение true (так что beginTransaction
, setTransactionSuccessful
а также endTransaction
будет пропущен и оставлен на усмотрение родителей).
Что касается полезности, вы будете использовать транзакции, только если выполняете несколько действий вместе.