Как запустить сборщик мусора, чтобы уменьшить размер базы данных? - PullRequest
2 голосов
/ 19 июня 2019

Мы используем Xodus для проекта удаленного исследования, чтобы сохранить временные данные перед отправкой их в централизованную базу данных. Таким образом, у нас есть несколько магазинов, которые могут расти или уменьшаться в зависимости от среды (трафик, сетевое подключение и т. Д.). Благодаря сборщику мусора мы ожидали увидеть уменьшение размера файла базы данных, но на данный момент оно только увеличилось.

Мы попробовали несколько конфигураций сборщика мусора, чтобы запускать его как можно чаще. Например, у нас есть:

    conf.setGcFileMinAge(1);
    conf.setGcFilesInterval(1);
    conf.setGcMinUtilization(1);

Без видимых эффектов ...

После того, как хранилище было очищено, мы ожидали увидеть уменьшение или удаление файлов .xd, но база данных продолжает расти и расти.

РЕДАКТИРОВАТЬ: Я пытаюсь увидеть эффекты GC с более простым кодом, как показано ниже:

        Environment exodus = Environments.newInstance(dbPath);

        final Transaction xtxn = exodus.beginExclusiveTransaction();
        Store store = exodus.openStore("testStore", StoreConfig.WITHOUT_DUPLICATES, xtxn);
        xtxn.commit();

        Thread.sleep(10 * 1000); // Wait to do actions after first  background cleaning cycle

        // Fill store, then clear it
        exodus.executeInExclusiveTransaction(tx -> {
            for(int i = 1; i <= 1000000; i++) {
                store.putRight(tx, LongBinding.longToEntry(i), StringBinding.stringToEntry(dbPath));
            }
        });
        clearStore(exodus, store);

        exodus.gc();
        Thread.sleep(5 * 60 * 1000); // Wait to see GC doing the work

    boolean clearStore(final Environment exodus, final Store store) {
        Transaction tx = exodus.beginExclusiveTransaction();
        try(Cursor cursor = store.openCursor(tx)) {
            boolean success = true;
            while(cursor.getNext() && success) {
                success &= cursor.deleteCurrent();
            }
            if(success) {
                tx.commit();
                return true;
            } else {
                log.warn("failed to delete entry {}", cursor.getKey());
                tx.abort();
                return false;
            }


        } catch(Exception e) {
            tx.abort();
            return false;
        }
    }

Если я удаляю первый "сон", сборщик мусора выполняет свою работу, размер файла базы данных уменьшается, как и ожидалось, все в порядке. Но если я сохраню первый «сон», сборщик мусора, кажется, никогда не будет вызван. Это похоже на первый цикл очистки фона, но не следующие ... В этом примере я сохраняю конфигурацию по умолчанию.

1 Ответ

1 голос
/ 19 июня 2019

Существует метод Environment.gc().Javadoc для этого метода выглядит следующим образом:

Говорит, что среда должна ускорить работу сборщика мусора в фоновой базе данных.Вызов этого метода не имеет немедленных последствий, таких как освобождение дискового пространства, удаление определенных файлов и т. Д.

Я бы не рекомендовал изменять настройки GC по умолчанию.EnvironmentConfig.setGcMinUtilization() может использоваться, чтобы сохранить базу данных более компактной, чем это было бы по умолчанию, или уменьшить загрузку GC (например, параллельно с пакетными обновлениями).В основном, более высокое минимальное использование (меньше допустимого свободного места) приводит к более высокой загрузке GC.

GC очищает файл базы данных по файлам, выбирая файлы с наименьшим использованием в первую очередь.Когда файл очищается, он не удаляется немедленно, должны выполняться два условия:

  1. Должна пройти задержка, настроенная на EnvironmentConfig.getGcFilesDeletionDelay().По умолчанию это 5 секунд.
  2. Любая транзакция (даже доступная только для чтения), созданная до момента очистки файла, должна быть завершена (зафиксирована или прервана).
...