Одно примечание: ON DELETE CASCADE плохо работает с массовыми операциями.Причина в том, что это делается как триггер.Следовательно, с алгоритмической точки зрения это выглядит так:
for row in delete_set:
for dependent row in (scan for referencing rows):
delete dependent row
Если вы удаляете 800000 строк в родительской таблице, это переводит в 800000 отдельных сканирований удаления в зависимых таблицах.Даже в вашем лучшем случае с индексами, пригодными для использования, 800000 отдельных сканирований индекса будут намного медленнее, чем одно последовательное сканирование.
Лучший способ сделать это - использовать записываемое общее табличное выражение версии 9.1 или выше или простосделать отдельные операторы удаления в той же транзакции.Что-то вроде:
WITH rows_to_delete (id) AS (
SELECT id FROM mytable WHERE where_condition
),
deleted_rows (id) AS (
DELETE FROM referencing_table WHERE mytable_id IN (select id FROM rows_to_delete)
RETURNING mytable_id
),
DELETE FROM mytable WHERE id IN (select id FROM deleted_rows);
Это сводится к чему-то вроде, алгоритмически:
сканирование строк для удаления как delete_set для зависимых при сканировании строк, зависимых от удаления: удаление зависимых для to_delete при сканированиистроки, на которые ссылаются удаленные зависимости: delete to_delete
Избавление от принудительного сканирования вложенных циклов значительно ускорит процесс.