Как удалить неиспользуемые последовательности?

Мы используем PostgreSQL. Мое требование - удалить неиспользуемые последовательности из моей базы данных. Например, если я создам любую таблицу через свое приложение, будет создана одна последовательность, но при удалении таблицы мы не удаляем и последовательность. Если вы хотите создать ту же таблицу, создается другая последовательность.

Пример: таблица: file; автоматически созданная последовательность для id столбца: file_id_seq

Когда я удаляю таблицу file и снова создаю ее с тем же именем, создается новая последовательность (т.е. file_id_seq1). Таким образом, я накопил огромное количество неиспользуемых последовательностей в базе данных моего приложения.

Как удалить эти неиспользуемые последовательности?


person user1023877    schedule 25.11.2011    source источник


Ответы (4)


Во-первых, последовательность, созданная автоматически для последовательного столбца, удаляется автоматически при удалении столбца (или таблицы, в которой он находится). Проблема, которую вы описываете, не должна существовать изначально. Только очень старые версии PostgreSQL этого не делали. 7.4 или старше?

Решение проблемы:

Этот запрос сгенерирует команды DDL для удаления всех несвязанных последовательностей в базе данных, в которой он выполняется:

SELECT string_agg('DROP SEQUENCE ' || c.oid::regclass, '; ') || ';' AS ddl
FROM   pg_class       c
LEFT   JOIN pg_depend d ON d.refobjid = c.oid
                       AND d.deptype <> 'i'
WHERE  c.relkind = 'S'
AND    d.refobjid IS NULL;

Приведение к regclass в c.oid::regclass автоматически уточняет имена последовательностей, где это необходимо, в соответствии с текущим search_path. Видеть:

Результат:

DROP SEQUENCE foo_id_seq;
DROP SEQUENCE bar_id_seq;
...

Выполните результат, чтобы удалить все последовательности, не связанные с последовательным столбцом (или любым другим столбцом). Изучите значение столбцов и таблиц здесь.

Осторожно! Это не означает, что эти последовательности не используются в других случаях. Существует ряд вариантов использования, когда последовательности создаются как автономные объекты. Например, если вы хотите, чтобы несколько столбцов использовали одну последовательность. Вы должны точно знать, что делаете.

Однако таким образом нельзя удалять последовательности, привязанные к столбцу serial. Таким образом, операция безопасна в этом отношении.

DROP SEQUENCE test_id_seq

Результат:

ERROR:  cannot drop sequence test_id_seq because other objects depend on it
DETAIL:  default for table test column id depends on sequence test_id_seq
HINT:  Use DROP ... CASCADE to drop the dependent objects too.
person Erwin Brandstetter    schedule 25.11.2011
comment
То, что я делаю, такое же, как ваше решение. Это правильный путь или нет, я не знаю. Я получаю все последовательности. затем сохраняется в файле .sql, затем я запускаю файл. код: - person user1023877; 26.11.2011
comment
@ user1023877: Это пытается удалить все последовательности. Что должно потерпеть неудачу, если существует какая-либо связанная последовательность. - person Erwin Brandstetter; 26.11.2011
comment
так что это не правильное решение, поэтому я перейду к другому решению. Спасибо. - person user1023877; 28.11.2011
comment
да, я перейду к другому решению, которое означает только ваше решение. Спасибо. - person user1023877; 28.11.2011
comment
Я использую postgres 9.3.4, и последовательность таблицы НЕ удаляется для меня, когда таблица удаляется. Мне все еще приходится удалять последовательность вручную. - person Amalgovinus; 23.01.2016
comment
@Amalgovinus: тогда последовательность не принадлежит столбцу PK, как это было бы при создании с псевдотипом serial. См.: stackoverflow.com/a/24659884/939860 или stackoverflow.com/a/10002134/939860 и - person Erwin Brandstetter; 23.01.2016
comment
Вы правы, моя проблема заключалась в том, что мне не хватало PK в поле последовательности. - person Amalgovinus; 24.01.2016
comment
@Amalgovinus: я уверен, что прав, но ПК здесь ни при чем. :) Важным моментом здесь является право собственности. - person Erwin Brandstetter; 24.01.2016
comment
Просто сообщаю, что эта проблема может возникнуть в Postgres 8.4, но не каждый раз для меня. Может, это баг, может, кто-то что-то напутал в моей базе данных, я не знаю. - person Felipe Andrade; 07.10.2016
comment
@SteveGlick: Спасибо за ваше редактирование. Вы были правы насчет добавления схемы. Я просто заменил его более элегантным кодом. - person Erwin Brandstetter; 19.04.2017

Если вы используете pgAdmin, вы можете выбрать последовательность и проверить вкладку «зависит от». Он перечислит любой объект, который зависит от последовательности.

Другой способ — ПОПЫТАТЬСЯ удалить последовательность. Если на нее ссылается таблица, pgAdmin выдаст ошибку, говорящую о том, что что-то зависит от этой последовательности. Если вы можете удалить последовательность без каких-либо ошибок, зависимости нет.

Обязательно протестируйте это где-нибудь.

person DrColossos    schedule 25.11.2011
comment
Но слишком сложно отбрасывать все последовательности одну за другой вручную. - person user1023877; 25.11.2011
comment
@user1023877 user1023877 вам следует написать скрипт, который делает что-то подобное. Вы можете прочитать системный каталог, чтобы увидеть зависимости, но писать что-то подобное тоже может быть утомительно. Короче говоря: я не думаю, что для такой задачи есть простой способ. - person DrColossos; 25.11.2011
comment
Хорошо, спасибо. не могли бы вы сослаться на какие-либо ссылки, которые предоставят информацию о том, как написать сценарий? - person user1023877; 25.11.2011
comment
Попробуйте официальные документы и информацию для системный каталог - person DrColossos; 25.11.2011
comment
Спасибо. Я пройду через это. - person user1023877; 25.11.2011

Что я делаю, так это сначала я получил все последовательности, а затем сохранил этот результат в файл, затем я запускаю файл в psql: ниже содержимое было сохранено с именем файла del_seq_all.sql, а затем список последовательностей в test1.sql . я не знаю, это правильное решение или нет. Но результат приходит, как и ожидалось.

\o d:/test1.sql
SELECT 'drop sequence ' || c.relname || ';' FROM pg_class c WHERE
(c.relkind = 'S');
\o

\i d:/test1.sql
person user1023877    schedule 26.11.2011

Действуйте с осторожностью, "удалить последовательность имя_последовательности_здесь" успешно удалит последовательность, даже если она прикреплена как значение по умолчанию nextval() столбца таблицы. Кажется, здесь есть некоторый разрыв, особенно если последовательность была создана отдельно. Я также ищу идеальный лайнер для очистки 100% неиспользуемых последовательностей.

person soyayix    schedule 12.02.2014