How fast something feels depends on the absolute objective time the operation takes and a perception component, which is more subjective and can be slightly manipulated.
Some methods to consider:
- Can your data be displayed in layers (e.g. showing only hotels on the map, only restaurants, etc.)? If so, load one layer at a time and load the rest on demand or prefetching in the background.
- Any chance you can show a default view that can be precached (as a tutorial perhaps) and then allow the user to get to the "real" data?
- Try to be more descriptive and break down the process rather than just a global progress bar ("fetching initial results"; "calculating layout"; "validating locations"...)
- Provide useful animations (zoom in from the globe to the area in question?)
- If the wait time is horrible suggest the user leave the tab open and be notified via a sound, an email, etc. (this is if you cannot go below several minutes)
Firstly - optimise the size of your data and your indexes. 29000 rows is a small dataset for a well indexed database to handle - suggest you read up on covering indexes: http://en.m.wikipedia.org/wiki/Database_index#Covering_index
The next stage is to consider that it makes zero sense to present 29000 icons to a user. Take a leaf out of Google's book and start by aggregating closely located data points on different scales. As the user zooms or drills in use Ajax to load another level of detail. This can be readily pre-computed and stored in the DB.
These two techniques should remove the need for the user waiting too long or any sort of loading progress bar.
In order to save on the load time on every page load you can use html5 to persistently store your json responses client side. You then check if the json you are about to request is already in the persistent store and only load it from the server if it isn't. You will need some way for the server to flush the cache on a future page load though for if the dataset has changed. There are more sophisticated cache schemes that could be used but I suggest you worry about the basics first. BUT DON'T DO ANY CACHING UNTIL EVERYTHING ELSE IS WORKING... Google "premature optimisation" to learn why.
You may also try to:
Group your data by location for different zoom levels, i.e. show a single icon for several items at abstract zoom level 0 and draw items separately on a zoom level 1. Caching data for lower zoom levels will give you a nice boost.
Fetch data from the server by small chunks and render this chunks data to the user: it will let user to see some info while download is in progress (you may also show "total load progress" somewhere on the screen)
And, as others are mentioned already, optimize your data access by caching and on data write (i.e. add indices, group on data write and not read, etc)