Seu exemplo com firstnames e lastnames é interessante. O que isso adiciona à imagem? Qual o valor que tem para colocar firstnames em uma tabela separada? Se você pegar todas as pessoas com o nome "Marc", o que você tem então? Isso significa alguma coisa? E se você pegar todas as pessoas com sobrenome "Smith" - todas elas pertencem a uma família ou clã ou raça ou nacionalidade? Todos moram na mesma cidade? Provavelmente não!
Se ter o nome "Smith" significa que você tem cabelos castanhos, olhos azuis e geralmente se veste de estilo cowboy, faria sentido. Uma analogia possível aqui é: se o item é um produto do tipo TV, provavelmente tem um controle remoto, precisa de um cabo de alimentação, etc.
Se os nomes tivessem 1 MB de tamanho, faria sentido usar um id. Isso economizaria muito armazenamento duplicado. Mas com nomes normais, não faz muita diferença, enquanto resulta em mais complexidade. O banco de dados não é apenas mais complexo, mas o código que se conecta ao banco de dados também é mais complexo e, como não há nenhum benefício, é melhor evitá-lo.
Como não há nada significativo ou útil conectado ao primeiro nome ou sobrenome, não o coloque em uma tabela separada.
Você menciona em um comentário que pode salvar 240KB quando 20k pessoas tiverem o mesmo nome. Isso na maioria das vezes não é uma grande defesa. É claro que há situações em que isso faz sentido, mas no mundo moderno com muito espaço em disco, economizar 1 MB de dados é totalmente irrelevante.
Quando você menciona os dados salvos, eu me pergunto se vai custar desempenho ou não. Eu não tenho idéia, mas se estamos falando de números e isso é o Facebook e nós consultamos milhões de nomes por dia, eu me pergunto o que será mais eficiente, porque isso significa uma junção extra. Isso deve ser testado e, com base nesse teste, você decide.
Se você tiver muitas consultas ou espaço muito limitado, verá que usar uma tabela extra economiza o dia - faça isso!