The Merkle trie allows us to more efficiently hold the data of previous blocks. In summary, data which is shared between blocks is not copied, but simply shares a reference to how to access the data in the database.
As data nodes are no longer present in any of the historical blocks, we prune them, removing them from the database.
I touch on this in my storage deep dive: https://www.shawntabrizi.com/substrate/substrate-storage-deep-dive/
You will see in the image below, only data which is new or changed is added to the database, where as most of the data remains untouched. Eventually, old data which is no longer referenced by a block is cleaned up. For an archive node, pruning never occurs since we store all historical blocks.