How to store data on the blockchain and query it?

Yes! global state seems the best way to track the highest bid.

That is a bit trickier! 20.000 bids would rule out the use of global state to track everything, so I think you would have to use the indexer with one of 2 approaches:

  1. Store the information in user local storage and query it through the indexer, as you mention above

  2. Iterate through the actual transactions sent to the contract with the indexer, looking for new bids

The difference in runtime will come from: reading from user local state (1) as opposed to parsing transactions of a certain address (2). If I had to guess, I would expect the second approach to be faster! But, you should always test!