One of the major principles of storing data on the blockchain is to make it as small as possible. By reducing data storage, you save gas for users (not always true, but most often).
However, when you store as simple of data as possible on the blockchain, it makes it hard to build certain features. Here's an example: "Blockchain, tell me how many dogs there are that have Molten skin?"
Well we could do this in a few ways. The first and simplest would be to have a function on the blockchain that loops through every Dog on the blockchain and checks if skin color = Molten. But this means we're doing 9,999 loops every time and what happens when we have more complex questions like: "How many Dogs were Boomed after August 23rd from a level 1 and a level 3 that ended up with Silver skin"
The second is to store extra data on the blockchain. We could have a list of all Molten dogs in a separate list. Every time a Molten dog is minted or burned, we update that list. But now we have duplicates. We have the list of all dogs, the list of all Molten dogs, the list of all Blue dogs... lots of copies. And we're wasting people's gas!
This is where The Graph shines.
We wrote some code that watches the Dogs Unchained contract. Every time something interesting happens (like a Boom or a Mint), our code reads through all the things that happened (which traits were minted, which were burned, who were the parents, etc.) and stores them in a traditional database, hosted and supported by The Graph.
Now, instead of storing all that info on the Blockchain as duplicates, we derive the information from the blockchain. The Graph has no information that the blockchain doesn't already have. All that data comes FROM the blockchain. But it turns it into a much more readable and queriable format.
So I can ask The Graph: "How many unique users own a Dog with Silver skin that has one ancestor with at least level 3?" And it knows!
Try it here: https://thegraph.com/legacy-explorer/subgraph/dogsunchained/dogs-unchained