Utilizar o (select * ) é uma operação custosa ?
Este post tem o intuito de tirar algumas dúvidas que possam vir a surgir no dia a dia, porém não procuramos entender sobre, pois tem coisas mais importantes que precisam ser resolvidas no dia a dia.
Bom, primeiro é preciso entender o que esse select * significa, quando utilizamos o * numa busca no banco, iremos trazer todas as colunas em cada row. A primeira resposta que eu posso responder é: depende. Mas por que?
Isso vai depender do resto da busca, mas vamos dizer que não foi feito nenhum join e não temos tantos registros, ainda assim isso tem um impacto relativo na busca. Para explicar melhor como funciona isso, é preciso entender um nível abaixo da abstração do banco. Mas basicamente, quanto mais joins, mais colunas, mais trabalho para o banco e vamos explicar o por que abaixo.
O banco armazena os dados no disco e para isso, o mesmo não armazena os dados na estrutura que conhecemos como varchar, text, int etc, mas sim em binário, para que seja mais compacto, dessa forma, podemos dizer que qualquer busca que fazemos, passa por uma serialização e deserialização interna para os tipos conhecidos do banco. Mas ainda assim, essa não é a operação mais custosa, o que é ainda pior é trafegar estes dados na rede utilizando JSON ou XML, como texto, após trafegar isso, ao chegar na sua aplicação, tem que acontecer mais uma serialização e deserialização, do tipo de dados conhecido do banco para as estrutura de dados conhecidas na sua aplicação, então aí temos mais um custo para nem sequer enviarmos isso para o cliente ou pior, enviarmos porém o mesmo nem ao menos visualizar esta informação.
Ainda tem uma diferença dependendo de como é baseado o banco, se é verticalmente ou horizontalmente, os bancos que são baseados horizontalmente guardam todas as informações da row sequencialmente, enquanto os verticais não, ou seja, se o seu banco é baseado em colunas, terá um impacto ainda maior.

Perceba que na implementação de um banco baseado em coluna ou verticalmente, será feito o acesso a cada coluna e em seguida uma busca procurando o campo equivalente.
Conclusão
É uma boa prática buscarmos apenas o que vamos utilizar devido esse aumento de pacote na comunicação entre o servidor e o banco, além do trabalho de serialização e deserialização no banco e na aplicação, resultando numa diminuição da latência nas queries devido a menos trabalho, você pode responder múltiplas queries do que se estivesse fazendo um trabalho que não vai usar. Dito tudo isso é por isso que muitas vezes matamos a performance da nossa aplicação quando utilizamos frameworks ORM (Object-relational mapping - Mapeamento Objeto Relacional), isso se dá porque muitas vezes não utilizamos lazy load para as tabelas filhas e também ainda que utilizemos, muita das vezes são feitos joins desnecessários e é claro que isso terá um impacto. Imagine que além de todo esse trabalho de trazer todos os atributos, você ainda está fazendo joins desnecessários que não vai vir a utilizar.