Un approccio a problemi come questo può essere quello di farlo in blocchi più piccoli.
DELETE FROM "contacts"
WHERE "contacts"."id" IN (
SELECT id
FROM contacts
LEFT OUTER JOIN members ON members.contact_id = contacts.id
WHERE members.id IS NULL
AND id >= 1 AND id < 1000
);
DELETE FROM "contacts"
WHERE "contacts"."id" IN (
SELECT id
FROM contacts
LEFT OUTER JOIN members ON members.contact_id = contacts.id
WHERE members.id IS NULL
AND id >= 1001 AND id < 2000
);
Sciacquare, ripetere. Sperimenta con diverse dimensioni dei blocchi per trovarne uno ottimale per il tuo set di dati, che utilizzi il minor numero di query, mantenendole tutte in memoria.
Naturalmente, vorresti scrivere questo script, possibilmente in plpgsql o in qualsiasi linguaggio di scripting tu preferisca.