No SQL Server 2012 (ou qualquer versão a partir de 2005), o uso SELECT *...
é apenas um possível problema de desempenho na instrução SELECT de nível superior de uma consulta.
Portanto, NÃO é um problema nas Views (*), nas subconsultas, nas cláusulas EXIST, nas CTEs, nem nas SELECT COUNT(*)..
etc., etc. Observe que isso provavelmente também é verdade para Oracle e DB2, e talvez PostGres (não tenho certeza) , mas é muito provável que ainda seja um problema em muitos casos para o MySql.
Para entender o porquê (e por que ainda pode ser um problema em um SELECT de nível superior), é útil entender por que houve um problema, porque usar SELECT *..
significa significa " retornar TODAS as colunas ". Em geral, isso retornará muito mais dados do que você realmente deseja, o que obviamente pode resultar em muito mais IO, tanto em disco quanto em rede.
O que é menos óbvio é que isso também restringe os índices e planos de consulta que um otimizador de SQL pode usar, porque sabe que, em última análise, deve retornar todas as colunas de dados. Se você souber antecipadamente que deseja apenas determinadas colunas, geralmente poderá usar planos de consulta mais eficientes aproveitando os índices que possuem apenas essas colunas. Felizmente, existe uma maneira de saber isso com antecedência, que é para você especificar explicitamente as colunas que deseja na lista de colunas. Mas quando você usa "*", está renunciando a isso em favor de "apenas me dê tudo, vou descobrir o que preciso".
Sim, também há uso adicional de CPU e memória para processar todas as colunas, mas é quase sempre menor em comparação com essas duas coisas: a significativa largura de banda extra de disco e rede necessária para as colunas que você não precisa, e ter que usar menos plano de consulta otimizado porque precisa incluir todas as colunas.
Então o que mudou? Basicamente, os Otimizadores de SQL incorporaram com êxito um recurso chamado "Otimização de Colunas", o que significa apenas que agora eles podem descobrir nas subconsultas de nível inferior se você realmente usará uma coluna nos níveis superiores da consulta.
O resultado disso é que não importa mais se você usar 'SELECT * ..' nos níveis inferior / interno de uma consulta. Em vez disso, o que realmente importa é o que está na lista de colunas do SELECT de nível superior. A menos que você use SELECT *..
na parte superior, ela deve assumir novamente que você deseja TODAS as colunas e, portanto, não pode empregar otimizações de coluna efetivamente.
(* - observe que há um problema de ligação menor e diferente no Views, *
onde eles nem sempre registram as alterações nas listas de colunas quando "*" é usado. Existem outras maneiras de resolver isso e isso não afeta o desempenho.)
É fisicamente e problematicamente permitido o uso
select * from table
, no entanto, é uma má ideia. Por quê?Primeiro de tudo, você descobrirá que está retornando colunas que não precisa (recursos pesados).
Em segundo lugar, demorará mais tempo em uma tabela grande do que nomear as colunas porque, quando você seleciona *, na verdade você seleciona os nomes das colunas no banco de dados e diz "me dê os dados que estão associados às colunas que têm nomes nessa outra lista . " Embora isso seja rápido para o programador, imagine fazer essa pesquisa no computador de um banco que pode ter literalmente centenas de milhares de pesquisas em um minuto.
Em terceiro lugar, fazer isso realmente torna mais difícil para o desenvolvedor. Com que frequência você precisa alternar entre SSMS e VS para obter todos os nomes de colunas?
Em quarto lugar, é um sinal de programação preguiçosa e não acho que qualquer desenvolvedor queira essa reputação.
fonte
Pode ser um problema se você colocar o
Select * ...
código em um programa, porque, como apontado anteriormente, o banco de dados pode mudar com o tempo e ter mais colunas do que o esperado quando você escreveu a consulta. Isso pode levar à falha do programa (na melhor das hipóteses) ou o programa pode seguir seu caminho alegre e corromper alguns dados, porque está analisando valores de campo que não foram escritos para manipular. Em resumo, o código de produção SEMPRE deve especificar os campos a serem retornados noSELECT
.Dito isso, tenho menos problemas quando
Select *
faz parte de umaEXISTS
cláusula, pois tudo o que será retornado ao programa é um booleano indicando o sucesso ou falha do select. Outros podem discordar dessa posição e eu respeito a opinião deles. PODE ser um pouco menos eficiente para codificarSelect *
do que para codificar 'Selecionar 1' em umaEXISTS
cláusula, mas não acho que exista perigo de corrupção de dados, de qualquer maneira.fonte
Muitas respostas
select *
estão erradas, por isso abordarei quando achar que está certo ou pelo menos OK.1) Em EXISTS, o conteúdo da parte SELECT da consulta é ignorado, para que você possa escrever
SELECT 1/0
e não cometerá erros.EXISTS
apenas verifica se alguns dados retornariam e retornariam um booleano com base nisso.2) Isso pode iniciar uma tempestade de fogo, mas eu gosto de usar
select *
os gatilhos da minha tabela de histórico. Porselect *
isso, evita que a tabela principal obtenha uma nova coluna sem adicionar a coluna à tabela de histórico e também gera um erro imediatamente quando inserido / atualizado / excluído na tabela principal. Isso evitou várias vezes em que os desenvolvedores adicionaram colunas e esqueceram de adicioná-lo à tabela de histórico.fonte
SELECT 1
porque, obviamente, notifica futuros mantenedores de código sobre sua intenção. Não é um requisito , mas se eu o vejo... WHERE EXISTS (SELECT 1 ...)
, obviamente, se anuncia como um teste da verdade.SELECT 1
base no mito de que o desempenho seria melhor do queSELECT *
. No entanto, ambas as opções são perfeitamente aceitáveis. Não há diferença no desempenho devido à maneira como o otimizador lida com EXISTS. Nem qualquer diferença na legibilidade por causa da palavra "EXISTE" que anuncia claramente um teste da verdade.Column8
à tabela principal esquecendo a tabela de histórico. O desenvolvedor escreve um monte de código realted na coluna 8. Em seguida, ele adicionaColumn9
à tabela principal; Desta vez, lembrando-se de adicionar também à história. Mais tarde, ao testar, ele percebe que esqueceu de adicionarColumn9
ao histórico (graças à sua técnica de detecção de erros) e prontamente o adiciona. Agora, o gatilho parece funcionar, mas os dados nas colunas 8 e 9 estão misturados no histórico. : S