Правильный способ очистки таблицы/базы данных Realm?

У меня есть объект realm с ~ 30 полями, после добавления и удаления нескольких объектов кажется, что область занимает довольно много места. Размер выделенного пространства, по-видимому, растет несколько экспоненциально:

10 * (добавить 100 + удалить все) = 4 мб данных

15 * (добавить 100 + удалить все) = 33 мб данных

20 * (добавить 100 + удалить все) = 91 мб Данные

25 * (добавить 100 + удалить все) = 179 мб данных

image

Сам файл в data\data\app_folder\files\default.realm составляет 200 мб в этот момент.

Теперь эта серьезная проблема может быть вызвана тем, что я не делаю что-то должным образом. Перед каждой установкой я делаю

Realm realm = Realm.getInstance(context);

realm.beginTransaction();
realm.where(RealmSubmission.class).findAll().clear();
// if i use realm.allObjects(RealmSubmission.class).clear(); the leak is even bigger, i get to 170mb Data with 20*(add 100 + remove all) even though both calls do the same by looking at their semantics.
realm.commitTransaction();

Добавление элементов в область выглядит следующим образом:

    for (Submission submission : submissionList){
        realm.beginTransaction();

        RealmSubmission realmSubmission = realm.createObject(RealmSubmission.class);
        RealmObjectUtils.copySubmission(realmSubmission, submission);

        realm.commitTransaction();
    }

Любые идеи?

Ответы

Ответ 1

Я попытался реплицировать небольшой класс модели (один String, один int) без успеха.

Используете ли вы ссылки и/или списки ссылок в своей модели? Могу я взглянуть на него?

Одна из причин может быть в том случае, если у вас есть класс Person, у которого есть поле RealmListdogs. Когда вы удаляете все элементы типа Person, Собаки теперь сохраняются в базе данных.

EDIT: после того, как вы предоставили данные, которые я пробовал, используя немного фиктивных данных:

Realm.deleteRealmFile(this);
Realm realm = Realm.getInstance(this);
File realmFile = new File(this.getFilesDir(), "default.realm");

long tic = System.currentTimeMillis();
for (int i = 0; i < 25; i++) {
    for (int j = 0; j < 100; j++) {
        realm.beginTransaction();
        TestObject testObject = realm.createObject(TestObject.class);
        testObject.setApprovedBy("Approver_" + j);
        testObject.setAuthor("Author_" + j);
        testObject.setBannedBy("Banner_" + j);
        testObject.setClicked(j % 2 == 0);
        testObject.setCommentCount(j);
        testObject.setCreated(System.currentTimeMillis());
        testObject.setCreatedUTC(j*7);
        testObject.setEdited(j % 3 == 0);
        realm.commitTransaction();
    }
    realm.beginTransaction();
    realm.where(TestObject.class).findAll().clear();
    realm.commitTransaction();
    Log.i(TAG, "Size: " + realmFile.length());
}
long toc = System.currentTimeMillis();
Log.i(TAG, "Time: " + (toc - tic));

Но я все еще не могу воспроизвести:

10-08 14:39:01.579  29233-29233/myapp.realm.io.sizeleak I/REALMTEST﹕ Size: 24576
10-08 14:39:01.999  29233-29233/myapp.realm.io.sizeleak I/REALMTEST﹕ Size: 24576
10-08 14:39:02.409  29233-29233/myapp.realm.io.sizeleak I/REALMTEST﹕ Size: 24576
10-08 14:39:02.809  29233-29233/myapp.realm.io.sizeleak I/REALMTEST﹕ Size: 24576
10-08 14:39:03.209  29233-29233/myapp.realm.io.sizeleak I/REALMTEST﹕ Size: 24576
10-08 14:39:03.649  29233-29233/myapp.realm.io.sizeleak I/REALMTEST﹕ Size: 49152
10-08 14:39:04.049  29233-29233/myapp.realm.io.sizeleak I/REALMTEST﹕ Size: 49152
10-08 14:39:04.449  29233-29233/myapp.realm.io.sizeleak I/REALMTEST﹕ Size: 49152
10-08 14:39:04.839  29233-29233/myapp.realm.io.sizeleak I/REALMTEST﹕ Size: 49152
10-08 14:39:05.329  29233-29233/myapp.realm.io.sizeleak I/REALMTEST﹕ Size: 49152
10-08 14:39:05.709  29233-29233/myapp.realm.io.sizeleak I/REALMTEST﹕ Size: 49152
10-08 14:39:06.259  29233-29233/myapp.realm.io.sizeleak I/REALMTEST﹕ Size: 49152
10-08 14:39:06.689  29233-29233/myapp.realm.io.sizeleak I/REALMTEST﹕ Size: 49152
10-08 14:39:07.109  29233-29233/myapp.realm.io.sizeleak I/REALMTEST﹕ Size: 49152
10-08 14:39:07.589  29233-29233/myapp.realm.io.sizeleak I/REALMTEST﹕ Size: 49152
10-08 14:39:08.019  29233-29233/myapp.realm.io.sizeleak I/REALMTEST﹕ Size: 49152
10-08 14:39:09.129  29233-29233/myapp.realm.io.sizeleak I/REALMTEST﹕ Size: 49152
10-08 14:39:09.729  29233-29233/myapp.realm.io.sizeleak I/REALMTEST﹕ Size: 49152
10-08 14:39:10.169  29233-29233/myapp.realm.io.sizeleak I/REALMTEST﹕ Size: 49152
10-08 14:39:10.669  29233-29233/myapp.realm.io.sizeleak I/REALMTEST﹕ Size: 49152
10-08 14:39:11.049  29233-29233/myapp.realm.io.sizeleak I/REALMTEST﹕ Size: 49152
10-08 14:39:11.449  29233-29233/myapp.realm.io.sizeleak I/REALMTEST﹕ Size: 49152
10-08 14:39:11.849  29233-29233/myapp.realm.io.sizeleak I/REALMTEST﹕ Size: 49152
10-08 14:39:12.269  29233-29233/myapp.realm.io.sizeleak I/REALMTEST﹕ Size: 49152
10-08 14:39:12.269  29233-29233/myapp.realm.io.sizeleak I/REALMTEST﹕ Time: 11265

Ожидается удвоение размера из-за фрагментации, но я все еще не вижу ничего, что могло бы предложить ваш опыт.

Время очень велико из-за большого количества транзакций. Объединение их вместе значительно увеличило бы производительность:

10-08 14:45:25.009  31593-31593/myapp.realm.io.sizeleak I/REALMTEST﹕ Time: 408

Ответ 2

Я сделал простой метод для удаления файла базы данных области, когда возникает исключение миграции (для dev). Он также возвращает новый экземпляр области, чтобы предотвратить любую проблему.

public Realm buildDatabase(){
    RealmConfiguration realmConfiguration = new RealmConfiguration.Builder(this).build();

    try {
        return Realm.getInstance(realmConfiguration);
    } catch (RealmMigrationNeededException e){
        try {
            Realm.deleteRealm(realmConfiguration);
            //Realm file has been deleted.
            return Realm.getInstance(realmConfiguration);
        } catch (Exception ex){
            throw ex;
            //No Realm file to remove.
        }
    }
}

Ответ 3

Удалить все объекты из базы данных Realm:

realm.executeTransaction(new Realm.Transaction() {
    @Override
    public void execute(Realm realm) {
        realm.deleteAll();
    }
});

Ответ 4

Вы должны удалить файл Realm. До первого использования Realm не создается файл. Это то, что вы хотите:

try {
  Realm.deleteRealmFile(context);
  //Realm file has been deleted.
} catch (Exception ex){
  ex.printStackTrace();
  //No Realm file to remove.
}

Убедитесь, что экземпляр области не используется.

Ответ 5

Хорошо, но все равно. Я начал использовать Realm в Android сейчас, и я все еще проверяю его но для прошлых опытов с использованием баз данных OO так как транзакции можно отменить, чем больше транзакций, чем больше занимаемая площадь, вы оставите, чтобы отменить копию состояния должно существовать, но вы правы, то, по моему опыту, проблема заключается в том, что некоторые базы данных не отбрасывают права на транзакции (я не могу подтвердить это, просто говорю о предыдущих опытах, которые у меня были с другими базами данных OO, где вы можете настроить эти настройки)

еще одна вещь, которую я заметил в обоих кодах, заключается в том, что никто не закрывает экземпляр и поэтому (также спекулируя), может быть, область каждой транзакционной транзакции не может получить GC

снова просто спекулирует надеюсь, что это поможет