【问题标题】:Proper way to clear Realm table/database?清除领域表/数据库的正确方法?
【发布时间】:2014-10-08 10:39:39
【问题描述】:

我有一个具有大约 30 个字段的领域对象,在添加和删除几个对象之后,领域似乎占用了相当多的空间。分配空间的大小似乎呈指数级增长:

10*(添加 100 + 全部删除)= 4 mb 数据

15*(添加 100 + 全部删除)= 33 mb 数据

20*(添加 100 + 全部删除)= 91 mb 数据

25*(添加 100 + 全部删除)= 179 mb 数据

此时 data\data\app_folder\files\default.realm 中的文件本身为 200 mb。

现在这个严重的问题可能是因为我没有正确地做某事。在每次插入之前我都会这样做

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();
    }

有什么想法吗?

【问题讨论】:

  • 这发生在什么版本的 Realm 上?
  • 70.1 .. 你可能还想检查主页上的链接,因为它下载了一个名为“latest”的无扩展名文件(我看到你发布了 71.0,但除了主页下载部分 idk从哪里下载)
  • 哦,我看到安装 71.0 更简单
  • 谢谢。现在应该修复“最新”错误。你能用 0.71.0 复制这个问题吗?
  • 244kb 后 10*(100 插入 + 全部清除)7 mb 后 15 33 mb 后 20 91mb 后 25

标签: java android realm


【解决方案1】:

我做了一个简单的方法来在发生迁移异常时删除领域数据库文件(用于开发)。 它还返回一个新的领域实例以防止出现任何问题。

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.
        }
    }
}

【讨论】:

    【解决方案2】:

    我尝试使用小型模型类(一个字符串,一个整数)进行复制,但没有成功。

    您在模型中使用链接和/或链接列表吗?我可以看看吗?

    其中一个原因可能是您有一个具有 RealmListdogs 字段的 Person 类。 当您删除 Person 类型的所有元素时,Dogs 现在保留在数据库中。

    编辑:在您提供数据后,我尝试了一些虚拟数据:

    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
    

    【讨论】:

    • 它代表 reddit 提交:pastebin.com/b8mPTKam 并且如果任何字段为空,则 copysubmission 会处理这种情况,因为我曾经有过类似的异常,我无法插入空 pastebin.com/ur6f7jXW
    • 当时可能对插入 null 有误。 :)
    • 批量交易确实有帮助,20*100 后 1.5 mb,40*100 后 2.9,60*100 后 3.7 mb,80*100 交易后 4.1mb。 100*100 后保持 4.1mb。我不知道为什么做很多小交易最终会导致如此大的泄漏而不是一个大交易,但它现在有效,我很满意,这样做也是更好的做法。
    • 另外,您不需要在实用程序方法中检查原语是否为 null。还有一个问题:这一切都发生在一个或多个线程上吗?
    • 是的,我想这样做,我不知道我从哪里得到这个“不要插入 null”:) 现在我有一个大交易,我创建了 100 个新领域对象并将它们提交到最后,所有这些都发生在单个 asynctasks doInBackground 中。以前的版本也在这个异步任务中
    【解决方案3】:

    从 Realm 数据库中删除所有对象:

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

    【讨论】:

      【解决方案4】:

      您应该删除领域文件。在您第一次使用 Realm 之前,不会创建任何文件。这就是你想要的:

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

      确保没有使用任何领域实例。

      【讨论】:

      • 这个答案已经过时了。
      • 那么,localhost,那你的答案是什么?
      • Realm.getDefaultInstance().deleteAll();
      【解决方案5】:

      好的旧东西,但无论如何。我现在开始在 android 中使用 Realm,我还在检查它 但是对于过去使用 OO 数据库的经验 由于可以取消交易,您执行的交易越多,您留下的足迹就越大,为了取消状态的副本必须存在但您正在提交正确,根据我的经验,问题是某些数据库不会丢弃交易权提交后离开,但这是幕后的东西(我无法证实这一点,只是谈论我以前在其他 OO 数据库中的经验,您可以在其中配置这些设置)

      我在这两个代码中注意到的另一件事是没有关闭实例 所以(也推测)可能每个提交事务的领域都无法获得 GC

      再次只是推测 希望对你有帮助

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-11-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多