By default all memory addresses are within DS. Exceptions are the destination addresses of STOSx/MOVSx and CMPSx where ES is used (*1). DS can be replaced by any other segment register in all instructions by adding a segment override prefix.
So with the exception of ES when it comes to string destination segment any segment can be used (overwritten) at cost of an additional instruction byte. Which segment register to be used when leaving the default is rather arbitrary.
The introduction of FS/GS eased the need to reload segment registers.
Adding one segment (FS) eased A=B+C type operations where each of the components resides in a separate segment, like when doing large amounts of data (tables), without constant reloading of segment registers. After all, each load needs not only to load all segment information, but also runs necessary privilege checks. It still requires reloading of DS after such sections.
Adding a two (FS&GS) even removed that restriction, allowing a program to hold three arbitrary data segments in addition to Code, Programm Data and Stack.
Fire at Will
*1 - And then there are all addressing modes with BP and SP,as they are calculated with SS as base value - after all, BP is the stack frame pointer.