I would have expected postgresql to "share" a preliminary sort on c1 that would then be useful to reduce the work on all window functions but it doesn't.
The plan shown does share - the output of one sort goes into another. Subsequent sorts still have to happen but they should be faster as the first field is already grouped. Doesn’t change the plan though.
I even created an index on c1 hoping that postgresql would be able to use it in order to minimize the cost of the sorts but I couldn't make it use it.
Use it how? You are still evaluating 250k groups so doing anything piece-wise seems like an expected loss compared to sequential scan.
David J.