Тебе все ответили, тут два варианта - создавать в базе inmemory таблицу с одной колонкой и без индексов, и на ее основе уже делать DELETE FROM A WHERE A.id NOT IN (SELECT id FROM B);
Либо написать скрипт, который выгрузит все id из базы, сравнит их (пока чисел не миллионы, это вообще не проблема) и сформирует список id которые нужно удалить (если всего 10к то их будет всего 3к), когда на десяток строк в любом языке программирования. Так как удаляются конкретные id то такой запрос будет работать быстрее чем delete where not in и возможно быстрее использования временной таблицы. Особых ограничений на количество id в where id in (...) я не нашел, если они есть то это проблема драйвера подключения к бд.
Есть еще третий вариант, который потребует изменения всего проекта, но заложит неплохие возможности. В базе данных нужно определить флаг - deleted (boolean), который устанавливать true если запись нужно удалить, это может быть дополнительное поле в каждой таблице где это имеет смысл, либо отдельная таблица (это эффективнее, если удаленные записи долго не нужно хранить) с единственным полем id, куда будут складываться идентификаторы записей на удаление. Естественно все запросы проекта нужно будет модифицировать с учетом этого поля/таблицы, чтобы пропускались записи, помеченные на удаление. Реальное же удаление проводить в момент наименьшей нагрузки на сервер или по другому критерию (например удаленные записи можно хранить для использования, к примеру отчетности). У метода есть подводные камни - например уникальные индексы/ограничения на другие поля нужно так же переделывать на сдвоенные с флагом удаленности, чтобы допускались записи с тем же значением что и удаленные.