Sequential scan with large sub-query filter "never" ends
Your queries are slow because they in fact do a lot. In your

explain analyze
    select * from bubu where id not in
    (select bubu_id from kuku limit 33554431);


example, the database is fetching up to 33,554,431 rows in undefined order from kuku, doing another scan on bubu to select rows that are not among the fetched 33m+ rows, and then finally fetching and returning rows that fit such a condition.

If you wanna do

delete from bubu where id not in
(select bubu_id from kuku)


then your options are:


Just run it and wait.
Do it in chunks:


Fetch all the IDs that you are going to compare against into a separate table:

CREATE TABLE temp_bubu_ids AS SELECT bubu_id FROM kuku;

Fetch 1000 or so IDs from the IDs table, delete them and then delete rows from bubu that match your condition:

WITH deleted_ids AS (
    DELETE FROM temp_bubu_ids

    -- DELETE doesn't support LIMIT
    WHERE ctid IN (
        SELECT ctid
        FROM temp_bubu_ids
        LIMIT 1000
    )
    RETURNING id
)
DELETE FROM bubu
WHERE id NOT IN (
    SELECT id
    FROM deleted_ids
)

Rinse and repeat until all the appropriate rows get deleted.