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 будет пропущен и оставлен на усмотрение родителей).

Что касается полезности, вы будете использовать транзакции, только если выполняете несколько действий вместе.

Другие вопросы по тегам