Я использую SQLite 3.7.2 в Windows. Моя база данных используется для хранения данных журнала, которые генерируются 24/7. Схема в основном:
CREATE TABLE log_message(id INTEGER PRIMARY KEY AUTOINCREMENT, process_id INTEGER, text TEXT);
CREATE TABLE process(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT);
Поле log_message.process_id
отображается на process.id
, таким образом, каждое сообщение журнала связывается с процессом, из которого оно исходит.
Теперь, рано или поздно, база данных становится слишком большой, и я хотел бы удалить самые старые записи (те, которые имеют самые низкие значения log_message.id
), пока база данных снова не упадет до заданного размера (скажем, 1 ГБ). Для этого я сейчас делаю
PRAGMA page_count;
PRAGMA page_size;
после каждых нескольких сообщений журнала, чтобы получить размер базы данных. Если он превышает мой лимит, я просто удаляю часть (сейчас: 100 сообщений) сообщений журнала, как это:
BEGIN TRANSACTION;
DELETE FROM log_message WHERE id IN (SELECT id FROM log_message LIMIT 100);
DELETE FROM process WHERE id IN (SELECT id FROM PROCESS EXCEPT SELECT process_id FROM log_message);
COMMIT;
VACUUM;
Последний оператор DELETE
удаляет все записи без ссылок из таблицы process
. Я повторяю этот процесс, пока размер файла снова не станет приемлемым.
Это связано как минимум с двумя проблемами:
- Подход к удалению 100 сообщений журнала является довольно случайным; Я сделал это число на основе нескольких экспериментов. Я хотел бы знать количество записей, которые я должен удалить заранее.
- Повторные вызовы VACUUM могут занимать довольно много времени (домашняя страница SQLite сообщает, что VACUUM может занимать до полсекунды на МБ в Linux, я думаю, в Windows это будет происходить не быстрее).
У кого-нибудь есть другие предложения, как это сделать?