Добавочный вакуум sqlite удаляет только одну свободную страницу - PullRequest
0 голосов
/ 12 декабря 2018

Я изменил значение auto_vacuum PRAGMA моей базы данных sqlite на INCREMENTAL.Когда я запускаю PRAGMA incremental_vacuum; через приложение «DB Browser for SQlite», оно освобождает все страницы в free_list.Но когда я выполняю ту же инструкцию, используя любую библиотеку SQLite в C # (например, Microsoft.Data.SQLite), она освобождает только одну страницу из free_list

. Я проверил это, получив число в текущем free_list, запустивPRAGMA freelist_count до и после выполнения оператора PRAGMA incremental_vacuum.

Также я попытался передать различные параметры в incremental_vacuum pragma, например, PRAGMA incremental_vacuum(100), но он все равно освободит только одну страницу.

Пожалуйста, дайтемне, если что я здесь делаю неправильно.

Заранее спасибо!

1 Ответ

0 голосов
/ 02 июня 2019

Это происходит, если игнорировать результат из sqlite3_step().Если он возвращает SQLITE_ROW, код не может действовать, как если бы он возвратил SQLITE_DONE.Нужно продолжать вызывать sqlite3_step() до тех пор, пока запрос не будет выполнен: прагма или нет, запрос - это запрос, и он не будет выполнен, пока, ну, ну, SQLITE_DONE :).Это происходит, чтобы удалить одну страницу за раз:

bool do_incremental_vacuum(sqlite3 *db) {
   sqlite3_stmt *stmt = nullptr;
   auto rc = sqlite3_prepare_v2(db, "pragma freelist_count;", -1, &stmt);
   if (rc != SQLITE_OK) return false;
   rc = sqlite3_step(stmt);
   if (rc != SQLITE_DONE && rc != SQLITE_ROW) return false;
   auto freelist_count = sqlite3_column_int64(stmt, 0);
   rc = sqlite3_errcode(db);
   if (rc != SQLITE_OK && rc != SQLITE_DONE && rc != SQLITE_ROW) return false;
   std::cout << "There are " << freelist_count << " pages in the free list." << std::endl;

   rc = sqlite3_prepare_v2(db, "pragma incremental_vacuum;", -1, &stmt, nullptr);
   uint64_t pages = 0;
   if (rc != SQLITE_OK) return false;
   do {
      rc = sqlite3_step(stmt);
      if (rc == SQLITE_ROW) ++ pages;
   } while (rc == SQLITE_ROW);
   if (rc != SQLITE_DONE) return false;

   std::cout << "Freed " << pages << " pages" << std::endl;
   return true;
}
...