Ouvi dizer que SELECT *
geralmente é uma prática ruim usar ao escrever comandos SQL, porque é mais eficiente para as SELECT
colunas que você precisa especificamente.
Se eu precisar de 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 nesse caso? Eu acho SELECT *
que seria mais ideal internamente se você realmente precisar de todos os dados, mas estou dizendo isso sem um entendimento real do banco de dados.
Estou curioso para saber qual é a melhor prática neste caso.
ATUALIZAÇÃO: Eu provavelmente deveria especificar que a única situação em que eu realmente gostaria de fazer isso SELECT *
é quando seleciono dados de uma tabela em que sei que todas as colunas sempre precisam ser recuperadas, mesmo quando novas colunas são adicionadas.
Dadas as respostas que eu vi no entanto, isso ainda parece uma péssima idéia e SELECT *
nunca deve ser usado por muito mais razões técnicas do que eu já pensei.
Respostas:
Um motivo pelo qual a seleção de colunas específicas é melhor é que aumenta a probabilidade de o SQL Server acessar os dados dos índices em vez de consultar os dados da tabela.
Aqui está um post que escrevi sobre o assunto: A verdadeira razão pela qual as consultas selecionadas são uma cobertura ruim do índice
Também é menos frágil alterar, pois qualquer código que consome os dados terá a mesma estrutura de dados, independentemente das alterações feitas no esquema da tabela no futuro.
fonte
vs
all_column_names) enquanto temos milhares de linhas e executamos SELECT com índice (na cláusula WHERE) ??Dada a sua especificação de que você está selecionando todas as colunas, há pouca diferença no momento . Perceba, no entanto, que os esquemas do banco de dados mudam. Se você usar,
SELECT *
adicionará novas colunas à tabela, mesmo que com toda a 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 descartar isso como um custo menor, mas saiba que as colunas que você não precisa ainda devem ser:
O item 1 tem muitos custos ocultos, incluindo a eliminação de algum índice de cobertura em potencial, causando carregamentos da página de dados (e debulha do cache do servidor), incorrendo em bloqueios de linha / página / tabela que, de outra forma, poderiam ser evitados.
Compare isso com a economia potencial de especificar as colunas e uma
*
e a única economia potencial é:Para o item 1, a realidade é que você adicionará / alterará o código para usar qualquer nova coluna que possa adicionar de qualquer maneira, portanto é uma lavagem.
Para o item 2, a diferença raramente é suficiente para levá-lo a um tamanho ou número de pacotes de rede diferente. Se você chegar ao ponto em que o tempo de transmissão da instrução SQL é o problema predominante, provavelmente precisará reduzir a taxa de instruções primeiro.
Para o item 3, NÃO há economia, pois a expansão do
*
mesmo deve ocorrer de qualquer maneira, o que significa consultar o esquema da tabela (s) de qualquer maneira. Realisticamente, a listagem das colunas incorrerá no mesmo custo, pois elas precisam ser validadas com relação ao esquema. Em outras palavras, esta é uma lavagem completa.Para o item 4, quando você especifica colunas específicas, o cache do plano de consulta pode ficar maior, mas apenas se você estiver lidando com diferentes conjuntos de colunas (que não é o que você especificou). Nesse caso, você deseja entradas de cache diferentes porque deseja planos diferentes, conforme necessário.
Portanto, tudo se resume, por causa da maneira como você especificou a pergunta, à resiliência do problema diante de eventuais modificações de esquema. Se você estiver gravando esse esquema na ROM (acontece), 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 que podem afetar muito a consulta .
Meu conselho é que você SEMPRE SELECIONE colunas específicas . Lembre-se de que você é bom no que faz repetidas vezes; portanto, adquira o hábito de fazer o que é 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 validade / validade e outras coisas semelhantes que são adicionadas pelos DBAs para problemas sistemáticos de conformidade. Outra fonte de alterações ocultas são as desnormalizações para desempenho em outras partes do sistema ou nos campos definidos pelo usuário.
fonte
Você deve selecionar apenas as colunas necessárias. Mesmo se você precisar de todas as colunas, ainda é melhor listar os nomes das colunas para que o servidor sql não precise consultar colunas na tabela do sistema.
Além disso, seu aplicativo pode ser interrompido se alguém adicionar colunas à tabela. Seu programa também receberá colunas que 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 recursos de rede.
fonte
Há quatro grandes razões para que isso
select *
seja ruim:A razão prática mais significativa é que ele força o usuário a saber magicamente a ordem na qual as colunas serão retornadas. É melhor ser explícito, o que também protege você contra a alteração da tabela, que segue muito bem ...
Se um nome de coluna que você está usando for alterado, é melhor identificá-lo mais cedo (no momento da chamada SQL) do que quando você estiver tentando usar a coluna que não existe mais (ou teve seu nome alterado etc.) )
A listagem dos nomes das colunas torna seu código muito mais auto-documentado e, portanto, provavelmente mais legível.
Se você estiver transferindo por uma rede (ou mesmo se não estiver), as colunas que você não precisa são apenas desperdício.
fonte
*
em um conjunto de nomes.)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.
fonte
A especificação dos nomes das colunas é definitivamente mais rápida - para o servidor. Mas se
então é melhor ficar com SELECT *. Em nossa estrutura, o uso intenso de SELECT * nos permite introduzir um novo campo de conteúdo gerenciado por site em uma tabela, oferecendo todos os benefícios do CMS (controle de versão, fluxo de trabalho / aprovações etc.), enquanto apenas tocamos o código de uma vez. alguns pontos, em vez de algumas dezenas.
Eu sei que os gurus do banco de dados 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 ajusto de acordo o que economizo e o que desperdiço.
fonte
SELECT * é uma prática ruim, mesmo que a consulta não seja enviada por uma rede.
Obviamente, tudo isso não importa muito para um sistema pequeno e simples.
fonte
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 usar TODAS as colunas, SELECT com parâmetros explícitos ainda será o preferido. Qualquer diferença de velocidade será basicamente imperceptível e quase em tempo constante. Um dia seu esquema será alterado, e este é um bom seguro para evitar problemas devido a isso.
fonte
Muitas boas razões respondidas aqui até agora, aqui está outra que não foi mencionada.
Nomear explicitamente as colunas ajudará na manutenção no futuro. Em algum momento, você fará alterações ou solução de problemas e se perguntará "onde diabos é essa coluna usada".
Se você tiver os nomes listados explicitamente, encontrar todas as referências a essa coluna - através de todos os seus procedimentos armazenados, visualizações etc. - é simples. Apenas despeje um script CREATE para o seu esquema de banco de dados e pesquise por texto nele.
fonte
Definindo definitivamente as colunas, porque o SQL Server não precisará fazer uma pesquisa nas colunas para obtê-las. Se você definir as colunas, o SQL poderá ignorar essa etapa.
fonte
É sempre melhor especificar as colunas necessárias, se você pensar uma vez, o SQL não precisará pensar em "wtf is *" toda vez que você consultar. Além disso, alguém mais tarde pode adicionar colunas à tabela que você realmente não precisa na sua consulta e, nesse caso, você será melhor especificando todas as suas colunas.
fonte
O problema com "select *" é a possibilidade de trazer dados que você realmente não precisa. Durante a consulta real ao banco de dados, as colunas selecionadas não são realmente adicionadas ao cálculo. O que é realmente "pesado" é o transporte de dados de volta ao seu cliente, e qualquer coluna que você realmente não precisa está apenas desperdiçando largura de banda da rede e aumentando o tempo que você está esperando pela consulta retornar.
Mesmo se você usar todas as colunas trazidas de um "select * ...", isso é apenas por enquanto. Se, no futuro, você alterar o layout da tabela / exibição e adicionar mais colunas, você começará a selecioná-las, mesmo que não precise delas.
Outro ponto em que uma instrução "select *" é inválida está na criação da exibição. Se você criar uma visualização usando "select *" e posteriormente adicionar colunas à sua tabela, a definição da visualização e os dados retornados não corresponderão e será necessário recompilar suas visualizações para que funcionem novamente.
Sei que escrever um "select *" é tentador, porque realmente não gosto de especificar manualmente todos os campos das minhas consultas, mas quando o sistema começar a evoluir, você verá que vale a pena gastar esse tempo extra / esforço na especificação dos campos, em vez de gastar muito mais tempo e esforço removendo erros em suas visualizações ou otimizando seu aplicativo.
fonte
Embora listar explicitamente as colunas seja bom para o desempenho, não fique louco.
Portanto, se você usar todos os dados, tente SELECT * por simplicidade (imagine ter muitas colunas e fazer uma consulta JOIN ... pode ficar horrível). Então - meça. Compare com a consulta com nomes de colunas listados explicitamente.
Não especule sobre desempenho, meça-o!
A listagem explícita ajuda mais quando você tem alguma coluna contendo big data (como o corpo de uma postagem ou artigo) e não precisa disso em uma consulta específica. Então, se você não retorná-lo na sua resposta, o servidor de banco de dados 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.
fonte
Você realmente deve selecionar apenas os campos necessários e apenas o número necessário, ou seja,
Fora do banco de dados, as consultas dinâmicas correm o risco de ataques de injeção e dados malformados. Normalmente, você contorna isso usando procedimentos armazenados ou consultas parametrizadas. Além disso (embora não seja realmente um problema), o servidor precisa gerar um plano de execução sempre que uma consulta dinâmica é executada.
fonte
A seleção é igualmente eficiente (em termos de velocidade) se você usar * ou colunas.
A diferença é sobre memória, não velocidade. Ao selecionar várias colunas, o SQL Server deve alocar espaço de memória para atender à consulta, incluindo todos os dados de todas as colunas solicitadas, mesmo se você estiver usando apenas uma delas.
O que importa em termos de desempenho é o plano de execução, que por sua vez depende muito da cláusula WHERE e do número de JOIN, OUTER JOIN, etc ...
Para sua pergunta, use SELECT *. Se você precisar de todas as colunas, não há diferença de desempenho.
fonte
NÃO é mais rápido usar nomes de campos 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, portanto, isso também é um absurdo.
E é possível (embora improvável) que você precise obter todos os campos usando * porque ainda não sabe quais campos existem (pense na estrutura de banco de dados muito dinâmica).
Outra desvantagem do uso de nomes de campo explícitos é que, se houver muitos deles e forem longos, isso dificulta a leitura do código e / ou do log de consultas.
Portanto, a regra deve ser: se você precisar de todos os campos, use *, se precisar de apenas um subconjunto, nomeie-os explicitamente.
fonte
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, a cláusula ORDER), pois o número de linhas pode ser enorme (por exemplo, dezenas de milhões de linhas).
fonte
A nomeação de cada coluna que você espera obter no seu aplicativo também garante que ele não seja interrompido se alguém alterar a tabela, desde que suas colunas ainda estejam presentes (em qualquer ordem).
fonte
Depende da versão do seu servidor de banco de dados, mas as versões modernas do SQL podem armazenar em cache o plano de qualquer maneira. Eu diria que vá com o que for mais sustentável com o seu código de acesso a dados.
fonte
Um dos motivos é a melhor prática para especificar exatamente quais colunas você deseja, devido a possíveis alterações 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 for mais rápido, vou recorrer aos outros por sua experiência.
fonte
Como na maioria dos problemas, isso depende do que você deseja alcançar. Se você deseja criar uma grade de banco de dados que permita todas as colunas em qualquer tabela, "Selecionar *" é a resposta. No entanto, se você precisar apenas de determinadas colunas e a adição ou exclusão de colunas da consulta for feita com pouca frequência, especifique-as individualmente.
Também depende da quantidade de dados que você deseja transferir do servidor. Se uma das colunas for definida como memorando, gráfico, blob etc. e você não precisar dessa coluna, é melhor não usar "Selecionar *" ou obterá um monte de dados que não precisa quer e seu desempenho pode sofrer.
fonte
Para adicionar o que todo mundo já disse, se todas as suas colunas que você selecionar estão incluídas em um índice, seu conjunto de resultados será extraído do índice em vez de procurar dados adicionais do SQL.
fonte
SELECT * é necessário se você deseja obter metadados, como o número de colunas.
fonte
O que todos acima disseram, mais:
Se você está buscando um código legível e sustentável, faça algo como:
SELECIONE foo, bar FROM widgets;
é instantaneamente legível e mostra a intenção. Se você ligar, sabe o que está recebendo de volta. Se os widgets tiverem apenas colunas foo e barra, selecionar * significa que você ainda precisa pensar no que está recebendo de volta, confirme se o pedido foi mapeado corretamente etc. No entanto, se os widgets tiverem mais colunas, mas você estiver interessado apenas em foo e bar, seu código fica confuso quando você solicita um curinga e depois usa apenas parte do que é retornado.
fonte
E lembre-se, se você tiver uma junção interna por definição, não precisará de todas as colunas, pois os dados nas colunas de junção serão repetidos.
Não é como listar colunas no servidor SQl é difícil ou até demorado. Basta arrastá-los do navegador de objetos (você pode obter tudo de uma só vez arrastando as colunas da palavra). Colocar um impacto permanente no desempenho do seu sistema (porque isso pode reduzir o uso de índices e o envio de dados desnecessários pela rede é caro) e aumenta a probabilidade de que você tenha problemas inesperados à medida que o banco de dados muda (algumas vezes, são adicionadas colunas que você não deseja que o usuário veja, por exemplo) apenas para poupar menos de um minuto do tempo de desenvolvimento, é míope e pouco profissional.
fonte
Em termos de desempenho, vi comentários de que ambos são iguais. mas aspecto da usabilidade, existem alguns + e 's
Quando você usa um (selecione *) em uma consulta e se alguém altera a tabela e adiciona novos campos que não precisam da consulta anterior, isso é uma sobrecarga desnecessária. E se o campo recém-adicionado for um blob ou um campo de imagem ??? o tempo de resposta da sua consulta será muito lento.
Por outro lado, se você usar a (selecione col1, col2, ..) e se a tabela for alterada e adicionar novos campos e se esses campos forem necessários no conjunto de resultados, você sempre precisará editar sua consulta de seleção após a alteração da tabela.
Mas sugiro sempre usar select col1, col2, ... nas suas consultas e alterar a consulta se a tabela for alterada mais tarde ...
fonte
Defina absolutamente as colunas que você deseja SELECIONAR sempre. Não há razão para não fazê-lo e a melhoria do desempenho vale a pena.
Eles nunca deveriam ter dado a opção de "SELECT *"
fonte
Se você precisar de todas as colunas, use SELECT *, mas lembre-se de que a ordem pode mudar, portanto, quando você estiver consumindo os resultados, acesse-os por nome e não por índice.
Eu ignoraria os comentários sobre como * precisa ir para a lista - as chances de analisar e validar colunas nomeadas são iguais ao tempo de processamento, se não mais. Não otimize prematuramente ;-)
fonte
Em termos de eficiência de execução, não conheço nenhuma diferença significativa. Mas, para a eficiência dos programadores, eu escreveria os nomes dos campos porque
fonte
ei, seja prático. use select * ao prototipar e selecione colunas específicas ao implementar e implantar. da perspectiva do plano de execução, ambos são relativamente idênticos nos sistemas modernos. no entanto, selecionar colunas específicas limita a quantidade de dados que devem ser recuperados do disco, armazenados na memória e enviados pela rede.
em última análise, o melhor plano é selecionar colunas específicas.
fonte