Интересно, как быстрее всего выполнить такую задачу в PostgreSQL. Меня интересуют максимально быстрые решения.
Я нашел себе такое решение для MySQL, оно работает намного быстрее, чем просто усечение таблиц по одной. Но в любом случае, меня интересуют самые быстрые решения и для MySQL. Посмотрите мой результат здесь, конечно, только для MySQL: https://github.com/bmabey/database_cleaner/issues/126
У меня есть следующие предположения:
- У меня 30-100 столов. Пусть будет 30.
- Половина столов пустует.
- Каждая непустая таблица имеет, скажем, не более 100 строк. Под этим я подразумеваю, что таблицы НЕ большие.
Мне нужна дополнительная возможность исключить из этой процедуры 2, 5 или N таблиц.
Я не могу! использовать транзакции.
Мне нужна самая быстрая стратегия очистки для такого случая, работающая на PostgreSQL как 8, так и 9.
Я вижу следующие подходы:
Сократите каждую таблицу. Я думаю, что это слишком медленно, особенно для пустых таблиц.
Проверять каждую таблицу на пустоту более быстрым способом, а затем, если она пуста, сбросить ее столбец уникального идентификатора (аналог AUTO_INCREMENT в MySQL) в исходное состояние (1), т.е. восстановить его last_value из последовательности обратно в 1, иначе запустить truncate в теме.
Я использую код Ruby для перебора всех таблиц, вызывая приведенный ниже код для каждой из них, я попытался настроить код SQL для каждой таблицы, например:
DO $$DECLARE r record;
BEGIN
somehow_captured = SELECT last_value from #{table}_id_seq
IF (somehow_captured == 1) THEN
== restore initial unique identifier column value here ==
END
IF (somehow_captured > 1) THEN
TRUNCATE TABLE #{table};
END IF;
END$$;
Манипулируя этим кодом в различных аспектах, я не мог заставить его работать, потому что не знаком с функциями и блоками (и переменными) PostgreSQL.
Также я предполагаю, что EXISTS(SELECT something FROM TABLE) можно было бы каким-то образом использовать для хорошей работы в качестве одного из блоков «процедуры проверки», из которого должна состоять процедура очистки, но я этого не сделал.
Я был бы признателен за любые подсказки о том, как эту процедуру можно выполнить нативным способом PostgreSQL.
ОБНОВИТЬ:
Все это мне нужно для запуска модульных и интеграционных тестов для проектов Ruby или Ruby on Rails. Каждый тест должен иметь чистую БД перед запуском или выполнять очистку после себя (т.н. разрыв). Транзакции — это очень хорошо, но они становятся непригодными для использования при тестировании определенных веб-драйверов, в моем случае необходимо переключиться на стратегию усечения. После того, как я обновил это со ссылкой на RoR, пожалуйста, не размещайте здесь ответы на тему «Очевидно, вам нужен DatabaseCleaner для PG» и так далее и тому подобное.
ОБНОВЛЕНИЕ 2:
Описанная здесь стратегия недавно была объединена с DatabaseCleaner, https://github.com/bmabey/database_cleaner как Опция :pre_count (см. README).
fsync
,full_page_writes
и RAM-диск. - person Erwin Brandstetter   schedule 16.07.2012