Пожалуйста, порекомендуйте лучший вариант для массового удаления

Я использую PostgreSQL 8.1.4. У меня 3 таблицы: одна из них - ядро ​​(table1), другие - иждивенцы (table2, table3). Я вставил 70000 записей в таблицу 1 и соответствующие связанные записи в других 2 таблицах. Поскольку я использовал CASCADE, я смог удалить связанные записи, используя DELETE FROM table1; Он отлично работает, когда записи минимальны в моей текущей версии PostgreSQL. Когда у меня огромный объем записей, он пытается удалить все, но нет признаков успеха удаления в течение многих часов! Принимая во внимание, что массовый импорт, происходит через несколько минут. Я хочу сделать массовое удаление в разумные минуты. Я также попробовал TRUNCATE. Например, TRUNCATE table3, table2, table1; Однако никаких изменений в производительности. Это займет больше времени и никаких признаков завершения! Из сети у меня было несколько вариантов, например, удаление всех ограничений, а затем воссоздание же было бы неплохо. Но, кажется, что запрос не был успешно запущен над "table1", когда он загружал больше данных! Пожалуйста, порекомендуйте мне лучшие решения для удаления всех записей за считанные минуты.

CREATE TABLE table1(
        t1_id   SERIAL PRIMARY KEY,
        disp_name       TEXT NOT NULL DEFAULT '',
        last_updated TIMESTAMP NOT NULL DEFAULT current_timestamp,
        UNIQUE(disp_name)
    ) WITHOUT OIDS;

CREATE UNIQUE INDEX disp_name_index on table1(upper(disp_name));

CREATE TABLE table2 (
        t2_id           SERIAL PRIMARY KEY,
        t1_id   INTEGER REFERENCES table1 ON DELETE CASCADE,
        type    TEXT
    ) WITHOUT OIDS;

CREATE TABLE table3 (
        t3_id           SERIAL PRIMARY KEY,
        t1_id   INTEGER REFERENCES table1 ON DELETE CASCADE,
        config_key      TEXT,
        config_value    TEXT
    ) WITHOUT OIDS;

С уважением, Шив.

Ответ 1

Вы можете создать индекс в столбцах дочерних таблиц, которые ссылаются на родительскую таблицу:

в таблице2 создайте индекс в столбце t1_id

в таблице3 создайте индекс в столбце t1_id

который должен немного ускорить процесс.

И/или не беспокоиться о on delete cascade, выполните процедуру удаления, которая удаляет сначала из дочерних таблиц, а затем из родительской таблицы, это может быть быстрее, чем позволить postgresql сделать это за вас.

Ответ 2

В SQL оператор TRUNCATE TABLE представляет собой язык определения данных (DDL), которая отмечает экстенты таблицы для освобождения (пустой для повторного использования). Результат этой операции быстро удаляет все данные из таблицы, обычно обход целого числа целостности обеспечивающих соблюдение механизмов. http://en.wikipedia.org/wiki/Truncate_(SQL)

Итак, усечение должно быть очень быстрым. В вашем случае, похоже, что у вас есть транзакция, которая не совершена и не отменена. В этом случае ваша транзакция удаления никогда не завершится.

Чтобы решить эту проблему, вы должны проверить свои активные транзакции в своей базе данных. Самый простой способ (по крайней мере, под SQL Server, он работает) - написать "ROLLBACK COMMIT"; в окно запроса и выполнить его. Если он выполняется без выброса ошибки, это означает, что на самом деле была активная транзакция. Если активной транзакции не осталось, это приведет к ошибке.

Ответ 3

Я бы поспорил, что вы пропустите некоторые индексы в базе данных тоже.

Если вы выпустите команду delete из консоли psql, просто нажмите Ctrl-C - транзакция будет прервана, и psql должен сообщить вам, какой запрос выполнялся, когда вы его прервали.

Затем используйте EXPLAIN, чтобы проверить, почему запрос занимает очень много времени.

Недавно у меня была аналогичная ситуация, и добавление индекса помогло решить проблему.