I may not be the right person to answer this. Some of your points seem a little odd.
4000 records is not huge for Crystal
I would try a while loop around your dataset and dump the results to the console and see how long that takes.
I would setup SQL profiler to see what queries are being sent to the SQL server. With only 4000 records an index will not even help, unless the tables are much larger and the dataset contains only 4000 records.
You may want to think about moving your business logic to SQL views verses .Net. It is possible that your dataset is being filled with the results of 1000s of SQL statements. It may be possible to replace this with a single join.
Let SQL sever do the heaving lifting, not .net