Cleanup / Prune Unreferenced Data in Dimension Tables
(Normally, I would say "don't bother".  But I see that your Dim table is nearly as big as the Fact table.  Hmmmm...  Perhaps it was unwise to even have the Dim table??  Think about that.)

For building the Used table (and assuming a Trigger handles incoming Inserts):

From the Fact table, build a list of useful values (Used).  Do this one chunk at a time, say, 1000 rows, as determined by the PRIMARY KEY.  This list goes into an extra table, Used.  One transaction per chunk.  De-dup and add a PK.  See my comments on chunking.

Now, walk through the Dim table, perhaps only 100 rows at a time, and do a multi-table delete, using LEFT JOIN Used ... WHERE ... IS NULL to determine what is not needed.

Be cautious -- the DELETE and the TRIGGER may step on each other.  That is, there may be deadlocks necessitating re-execution.  But 100 rows at a time should keep that at a nice balance between minimizing deadlocks and maximizing speed.  One transaction per chunk.

Yes, it will take time -- both for the discovery of Used and for the DELETEs.  But it should not matter.  Everything else is humming along, with only very rare and brief interference.

I guess the TRIGGER would need to insert into Used when a row is inserted into Dim.