Qual é mais rápido / melhor? SELECT * ou SELECT column1, colum2, column3, etc

Ouvi dizer que SELECT * é geralmente uma prática ruim para usar ao escrever comandos SQL, porque é mais eficiente para as colunas SELECT que você precisa especificamente.

Se eu precisar SELECT todas as colunas de uma tabela, devo usar

 SELECT * FROM TABLE 

ou

 SELECT column1, colum2, column3, etc. FROM TABLE 

A eficiência realmente importa neste caso? Eu acho que o SELECT * seria mais ideal internamente se você realmente precisasse de todos os dados, mas estou dizendo isso sem uma compreensão real do database.

Estou curioso para saber qual é a melhor prática neste caso.

UPDATE: Eu provavelmente deveria especificar que a única situação onde eu realmente gostaria de fazer um SELECT * é quando eu estou selecionando dados de uma tabela onde eu sei que todas as colunas sempre precisarão ser recuperadas, mesmo quando novas colunas forem adicionadas.

Dadas as respostas que eu vi no entanto, isso ainda parece ser uma má idéia e SELECT * nunca deve ser usado por razões muito mais técnicas que eu nunca pensei.

Um motivo pelo qual a seleção de colunas específicas é melhor é que aumenta a probabilidade de que o SQL Server possa acessar os dados de índices em vez de consultar os dados da tabela.

Aqui está uma postagem que eu escrevi sobre isso: A verdadeira razão para selecionar consultas é uma má cobertura de índice

Também é menos frágil mudar, já que qualquer código que consuma os dados estará recebendo a mesma estrutura de dados, independentemente das alterações feitas no esquema da tabela no futuro.

Dada a sua especificação de que você está selecionando todas as colunas, há pouca diferença neste momento . Perceba, no entanto, que os esquemas do database mudam. Se você usar SELECT * obterá novas colunas adicionadas à tabela, embora, com toda probabilidade, seu código não esteja preparado para usar ou apresentar esses novos dados. Isso significa que você está expondo seu sistema a alterações inesperadas de desempenho e funcionalidade.

Você pode estar disposto a descartar isso como um custo menor, mas perceba que as colunas que você não precisa ainda devem ser:

  1. Leia do database
  2. Enviado pela rede
  3. Marshalled em seu processo
  4. (para tecnologias do tipo ADO) Salvas em uma tabela de dados na memory
  5. Ignorado e descartado / colecionado de lixo

O item nº 1 tem muitos custos ocultos, incluindo a eliminação de algum índice de cobertura em potencial, causando carregamentos de página de dados (e espelhamento de cache do servidor), incorrendo em travas de linha / página / tabela que poderiam ser evitadas.

Equilibre isso em relação à economia potencial de especificar as colunas em relação a * e a única economia potencial é:

  1. O programador não precisa revisitar o SQL para adicionar colunas
  2. O transporte de rede do SQL é menor / mais rápido
  3. Tempo de análise / validação da consulta do SQL Server
  4. Cache de plano de consulta do SQL Server

Para o item 1, a realidade é que você vai adicionar / alterar o código para usar qualquer nova coluna que você possa adicionar de qualquer maneira, então é uma lavagem.

Para o item 2, a diferença raramente é suficiente para empurrá-lo para um tamanho de pacote ou número diferente de pacotes de rede. Se você chegar ao ponto em que o tempo de transmissão da instrução SQL é o problema predominante, provavelmente será necessário reduzir a taxa de instruções primeiro.

Para o item 3, NÃO há economia, pois a expansão do * deve acontecer de qualquer maneira, o que significa consultar o esquema da tabela de qualquer maneira. Realisticamente, listar as colunas terá o mesmo custo, porque elas precisam ser validadas no esquema. Em outras palavras, isso é uma lavagem completa.

Para o item 4, quando você especifica colunas específicas, o cache do plano de consulta pode ficar maior, mas somente se você estiver lidando com diferentes conjuntos de colunas (que não é o que você especificou). Nesse caso, você deseja inputs de cache diferentes porque deseja planos diferentes, conforme necessário.

Então, tudo isso se resume, devido à forma como você especificou a questão, à resiliência do problema em face de eventuais modificações de esquema. Se você está gravando este esquema na ROM (isso acontece), então um * é perfeitamente aceitável.

No entanto, minha orientação geral é que você deve selecionar apenas as colunas necessárias, o que significa que às vezes parecerá que você está pedindo todas elas, mas os DBAs e a evolução do esquema significam que algumas novas colunas podem aparecer, o que pode afetar muito a consulta .

Meu conselho é que você deve SELECIONAR SEMPRE as colunas específicas . Lembre-se de que você fica bom no que você faz mais e mais, então apenas tenha o hábito de fazer o certo.

Se você está se perguntando por que um esquema pode mudar sem alterar o código, pense em termos de log de auditoria, datas de expiração / efetivas e outras coisas semelhantes que são adicionadas pelos DBAs para problemas sistemáticos de conformidade. Outra fonte de alterações dissimuladas é desnormalização de desempenho em outro lugar no sistema ou campos definidos pelo usuário.

Você deve selecionar apenas as colunas necessárias. Mesmo se você precisar de todas as colunas, é melhor listar os nomes das colunas para que o sql server não precise consultar as colunas do sistema.

Além disso, seu aplicativo pode quebrar se alguém adicionar colunas à tabela. Seu programa receberá colunas que também não esperava e talvez não saiba como processá-las.

Além disso, se a tabela tiver uma coluna binária, a consulta será muito mais lenta e usará mais resources de rede.

Existem quatro grandes razões pelas quais select * é uma coisa ruim:

  1. A razão prática mais significativa é que força o usuário a saber magicamente a ordem em que as colunas serão retornadas. É melhor ser explícito, o que também protege você contra a mudança de tabela, que segue muito bem em …

  2. Se um nome de coluna que você está usando mudar, é melhor pegá-lo no início (no ponto da chamada SQL) em vez de quando você está tentando usar a coluna que não existe mais (ou teve seu nome alterado, etc. )

  3. Listar os nomes das colunas torna o seu código muito mais auto-documentado e, portanto, provavelmente mais legível.

  4. Se você estiver transferindo através de uma rede (ou mesmo se não estiver), as colunas de que você não precisa são apenas desperdício.

Especificar a lista de colunas geralmente é a melhor opção, pois seu aplicativo não será afetado se alguém adicionar / inserir uma coluna na tabela.

SELECT * é uma má prática, mesmo que a consulta não seja enviada através de uma rede.

  1. Selecionar mais dados do que você precisa torna a consulta menos eficiente – o servidor precisa ler e transferir dados extras, por isso leva tempo e gera carga desnecessária no sistema (não apenas na rede, como outros mencionaram, mas também em disco, CPU etc. ). Além disso, o servidor não consegue otimizar a consulta da melhor maneira possível (por exemplo, usar o índice de cobertura da consulta).
  2. Depois de algum tempo, a estrutura da sua tabela pode mudar, portanto SELECT * retornará um conjunto diferente de colunas. Assim, seu aplicativo pode obter um dataset de estrutura inesperada e interromper em algum lugar downstream. Declarar explicitamente as colunas garante que você obtenha um dataset de estrutura conhecida ou obtenha um erro claro no nível do database (como ‘coluna não encontrada’).

Claro, tudo isso não importa muito para um sistema pequeno e simples.

Em termos de desempenho, o SELECT com colunas específicas pode ser mais rápido (não é necessário ler todos os dados). Se sua consulta realmente usa TODAS as colunas, SELECT com parâmetros explícitos ainda é o preferido. Qualquer diferença de velocidade será basicamente imperceptível e próxima do tempo constante. Um dia, seu esquema mudará, e isso é um bom seguro para evitar problemas devido a isso.

Especificar os nomes das colunas é definitivamente mais rápido – para o servidor. Mas se

  1. o desempenho não é um grande problema (por exemplo, este é um database de conteúdo do site com centenas, talvez milhares – mas não milhões – de linhas em cada tabela); E
  2. seu trabalho é criar muitos aplicativos pequenos e semelhantes (por exemplo, sites gerenciados por conteúdo voltados ao público) usando uma estrutura comum, em vez de criar um aplicativo único e complexo; E
  3. a flexibilidade é importante (muita customização do esquema do database para cada site);

então é melhor ficar com o SELECT *. Em nossa estrutura, o uso pesado de SELECT * nos permite introduzir um novo campo de conteúdo gerenciado de website em uma tabela, fornecendo todos os benefícios do CMS (version control, stream de trabalho / aprovações, etc.), enquanto tocamos apenas o código alguns pontos, em vez de dezenas de pontos.

Eu sei que os gurus do DB vão me odiar por isso – vá em frente, vote em mim – mas no meu mundo, o tempo do desenvolvedor é escasso e os ciclos de CPU são abundantes, então eu ajustei o que eu conservo e o que desperdiço.

Você deve selecionar apenas os campos de que precisa e apenas o número necessário, ou seja,

 SELECT Field1, Field2 FROM SomeTable WHERE --(constraints) 

Fora do database, as consultas dinâmicas correm o risco de ataques de injeção e dados malformados. Normalmente você contorna isso usando stored procedures ou consultas parametrizadas. Além disso (embora não seja um grande problema), o servidor precisa gerar um plano de execução toda vez que uma consulta dinâmica é executada.

Muitas boas razões respondidas aqui até agora, aqui está outra que não foi mencionada.

A indicação explícita das colunas ajudará você na manutenção. Em algum momento, você estará fazendo alterações ou solucionando problemas e perguntando “onde diabos está essa coluna usada”.

Se você tiver os nomes listados explicitamente, encontrar todas as referências a essa coluna – por meio de todos os seus stored procedures, visualizações etc. – é simples. Apenas despeje um script CREATE para o seu esquema DB, e procure por ele.

definitivamente definindo as colunas, porque o SQL Server não terá que fazer uma pesquisa nas colunas para puxá-las. Se você definir as colunas, o SQL poderá pular essa etapa.

É sempre melhor especificar as colunas que você precisa, se você pensar uma vez, o SQL não precisa pensar “wtf is *” toda vez que você consultar. Além disso, alguém poderá adicionar colunas à tabela que você realmente não precisa em sua consulta e, nesse caso, será melhor especificar todas as suas colunas.

O problema com “select *” é a possibilidade de trazer dados que você realmente não precisa. Durante a consulta real do database, as colunas selecionadas não são realmente adicionadas ao cálculo. O que é realmente “pesado” é o transporte de dados de volta para o seu cliente, e qualquer coluna que você realmente não precisa é apenas desperdiçar largura de banda de rede e adicionar o tempo que você espera que a consulta retorne.

Mesmo se você usar todas as colunas trazidas de um “select * …”, é só por enquanto. Se, no futuro, você alterar o layout de tabela / visualização e adicionar mais colunas, você começará a trazê-las em seus seleções, mesmo que não precise delas.

Outro ponto em que uma instrução “select *” é ruim é na criação da view. Se você criar uma visualização usando “selecionar *” e depois adicionar colunas à sua tabela, a definição da exibição e os dados retornados não corresponderão e você precisará recompilar suas visualizações para que elas funcionem novamente.

Eu sei que escrever um “select *” é tentador, porque eu realmente não gosto de especificar manualmente todos os campos em minhas consultas, mas quando o seu sistema começa a evoluir, você verá que vale a pena gastar esse tempo extra / esforço em especificar os campos em vez de gastar muito mais tempo e esforço para remover erros em suas visualizações ou otimizar seu aplicativo.

Select é igualmente eficiente (em termos de velocidade) se você usar * ou colunas.

A diferença é sobre memory, não velocidade. Quando você seleciona várias colunas, o SQL Server deve alocar espaço de memory para servir a consulta, incluindo todos os dados de todas as colunas que você solicitou, mesmo se estiver usando apenas uma delas.

O que importa em termos de desempenho é o plano de execução, que por sua vez depende muito da sua cláusula WHERE e do número de JOIN, OUTER JOIN, etc …

Para sua pergunta, basta usar SELECT *. Se você precisar de todas as colunas, não há diferença de desempenho.

Embora listar colunas explicitamente seja bom para o desempenho, não fique maluco.

Então, se você usar todos os dados, tente SELECT * para simplificar (imagine ter muitas colunas e fazer uma consulta JOIN … pode ficar horrível). Então – meça. Compare com a consulta com nomes de coluna listados explicitamente.

Não especule sobre desempenho, meça!

Listagem explícita ajuda mais quando você tem alguma coluna contendo dados grandes (como o corpo de um post ou artigo), e não precisa disso em determinada consulta. Então, ao não retorná-lo em sua resposta, o servidor de database pode economizar tempo, largura de banda e taxa de transferência de disco. O resultado da sua consulta também será menor, o que é bom para qualquer cache de consulta.

NÃO é mais rápido usar nomes de campo explícitos versus *, se e somente se, você precisa obter os dados para todos os campos.

Seu software cliente não deve depender da ordem dos campos retornados, o que também é um absurdo.

E é possível (embora improvável) que você precise obter todos os campos usando * porque você ainda não sabe quais campos existem (pense na estrutura dinâmica do database).

Outra desvantagem do uso de nomes de campos explícitos é que, se houver muitos deles e forem longos, isso dificultará a leitura do código e / ou do log de consulta.

Portanto, a regra deve ser: se você precisar de todos os campos, use *, se precisar apenas de um subconjunto, nomeie-os explicitamente.

O resultado é muito grande. É lento para gerar e enviar o resultado do mecanismo SQL para o cliente.

O lado do cliente, sendo um ambiente de programação genérico, não é e não deve ser projetado para filtrar e processar os resultados (por exemplo, a cláusula WHERE, cláusula ORDER), pois o número de linhas pode ser enorme (por exemplo, dezenas de milhões de linhas).

Dar nome a cada coluna que você espera obter em seu aplicativo também garante que seu aplicativo não será quebrado se alguém alterar a tabela, desde que suas colunas ainda estejam presentes (em qualquer ordem).

Depende da versão do seu servidor de database, mas as versões modernas do SQL podem armazenar o plano em cache de qualquer maneira. Eu diria que vá com o que é mais sustentável com o seu código de access a dados.

Uma das razões é a melhor prática para soletrar exatamente quais colunas você quer é por causa de possíveis mudanças futuras na estrutura da tabela.

Se você estiver lendo dados manualmente usando uma abordagem baseada em índice para preencher uma estrutura de dados com os resultados de sua consulta, no futuro, quando você adicionar / remover uma coluna, terá dores de cabeça tentando descobrir o que deu errado.

Quanto ao que é mais rápido, eu vou adiar para os outros por sua expertise.

Como a maioria dos problemas, depende do que você deseja alcançar. Se você quiser criar uma grade db que permita todas as colunas em qualquer tabela, então “Select *” é a resposta. No entanto, se você precisar apenas de determinadas colunas e adicionar ou excluir colunas da consulta for feito com pouca freqüência, especifique-as individualmente.

Também depende da quantidade de dados que você deseja transferir do servidor. Se uma das colunas é definida como memo, gráfico, blob, etc. e você não precisa dessa coluna, é melhor não usar “Select *” ou obterá muitos dados que não quer e seu desempenho pode sofrer.

Para adicionar ao que todos disseram, se todas as colunas selecionadas estiverem incluídas em um índice, o conjunto de resultados será extraído do índice, em vez de procurar dados adicionais do SQL.

SELECT * é necessário se alguém quiser obter metadados como o número de colunas.

O que todos acima disseram, mais:

Se você está se esforçando para obter código de fácil leitura, fazendo algo como:

SELECIONE foo, barra FROM widgets;

é instantaneamente legível e mostra intenção. Se você fizer essa binding, sabe o que está recebendo de volta. Se widgets tem apenas foo e bar colunas, em seguida, selecionando * significa que você ainda tem que pensar sobre o que você está recebendo de volta, confirme se o pedido está mapeado corretamente, etc No entanto, se widgets tem mais colunas, mas você está interessado apenas em foo e bar, seu código fica confuso quando você consulta um caractere curinga e usa apenas um pouco do que é retornado.

E lembre-se se você tem uma junit interna, por definição, não precisa de todas as colunas, pois os dados nas colunas de junit são repetidos.

Não é como listar colunas no servidor SQl é difícil ou até mesmo demorado. Basta arrastá-los do navegador de objects (você pode obter tudo de uma vez, arrastando a partir das colunas de palavras). Para colocar um desempenho permanente em seu sistema (porque isso pode reduzir o uso de índices e porque o envio desnecessário de dados pela rede é caro) e torna mais provável que você tenha problemas inesperados à medida que o database muda (às vezes são adicionadas colunas você não quer que o usuário veja, por exemplo) apenas para economizar menos de um minuto de tempo de desenvolvimento é míope e não profissional.

Absolutamente defina as colunas que você deseja selecionar todas as vezes. Não há razão para isso e a melhoria de desempenho vale a pena.

Eles nunca deveriam ter dado a opção de “SELECT *”

Se você precisar de todas as colunas, basta usar SELECT *, mas lembre-se de que a ordem pode mudar, assim, quando você estiver consumindo os resultados, acesse-os pelo nome e não pelo índice.

Eu ignoraria comentários sobre como * precisa ir buscar a lista – as chances são de analisar e validar colunas nomeadas é igual ao tempo de processamento, se não mais. Não otimize prematuramente 😉

Em termos de eficiência de execução, não tenho conhecimento de nenhuma diferença significativa. Mas para a eficiência dos programadores eu escreveria os nomes dos campos porque

  • Você conhece o pedido se precisar indexar por número ou se seu driver se comportar de maneira engraçada em valores blob e você precisar de um pedido definido
  • Você só lê os campos de que precisa, se precisar adicionar mais campos
  • Você recebe um erro sql se errar ou renomear um campo, e não um valor vazio de um conjunto de registros / linha
  • Você pode ler melhor o que está acontecendo.

Ei, seja prático. use select * ao criar protótipos e selecione colunas específicas ao implementar e implantar. a partir de uma perspectiva de plano de execução, ambos são relativamente idênticos em sistemas modernos. no entanto, a seleção de colunas específicas limita a quantidade de dados que devem ser recuperados do disco, armazenados na memory e enviados pela rede.

Em última análise, o melhor plano é selecionar colunas específicas.

Também mantenha as mudanças em mente. Hoje, Select * seleciona apenas as colunas que você precisa, mas amanhã também pode selecionar essa coluna varbinary (MAX) que acabei de adicionar sem avisar, e agora você também está recuperando todos os 3.18 Gigabytes de dados binários que não estavam na mesa ontem.