No Unix/Linux SE, um especialista amigável explicou que o que você vê é a maneira correta de classificar o Unicode. Basicamente, o padrão está tentando classificar:
di Silva Fred di Silva Fred
di Silva John diSilva Fred
diSilva Fred disílva Fred
diSilva John -> di Silva John
disílva Fred diSilva John
disílva John disílva John
Agora, se os espaços fossem tão importantes quanto as letras, a classificação não poderia separar as várias grafias idênticas de Fred e John. Então, o que acontece é que ele primeiro classifica sem espaços. Em seguida, em uma segunda passagem, as strings iguais sem espaços em branco são classificadas. (Esta é uma simplificação, o algoritmo real parece bastante complexo, atribuindo vários níveis de precedência a espaços em branco, acentos e caracteres não imprimíveis.)
Você pode ignorar o agrupamento Unicode definindo:
export LC_ALL=C
Ou no Postgres, lançando para matriz de bytes para classificação:
order by name::bytea
Ou (da resposta de Kiln) especificando o
C
agrupamento:order by name collate "C"
Ou alterando o agrupamento padrão da coluna:
alter table products alter column name type text collate "C";