A essência da citação de não otimizar prematuramente é optar por um código simples e direto e, em seguida, usar um criador de perfil para apontar os pontos de acesso, que você poderá otimizar para ser eficiente.
Quando você usa select *, torna-se impossível criar um perfil, portanto, não está escrevendo um código claro e direto e vai contra o espírito da citação. select *
é um anti-padrão.
Portanto, selecionar colunas não é uma otimização prematura. Algumas coisas em cima da minha cabeça ....
- Se você especificar colunas em uma instrução SQL, o mecanismo de execução SQL causará erro se essa coluna for removida da tabela e a consulta for executada.
- Você pode verificar com mais facilidade o código onde essa coluna está sendo usada.
- Você sempre deve escrever consultas para trazer de volta a menor quantidade de informações.
- Como outros mencionam, se você usa acesso à coluna ordinal, nunca deve usar select *
- Se sua instrução SQL ingressar em tabelas, selecione * fornece todas as colunas de todas as tabelas na associação
O corolário é que, usando select *
...
- As colunas usadas pelo aplicativo são opacas
- Os DBAs e seus criadores de perfil de consulta não conseguem ajudar no desempenho ruim do aplicativo
- O código é mais quebradiço quando ocorrem alterações
- Seu banco de dados e sua rede estão sofrendo porque estão recuperando muitos dados (E / S)
- As otimizações do mecanismo de banco de dados são mínimas, pois você recupera todos os dados independentemente (lógico).
Escrever o SQL correto é tão fácil quanto escrever Select *
. Portanto, a pessoa preguiçosa real escreve SQL apropriado porque não deseja revisitar o código e tenta se lembrar do que estava fazendo quando o fez. Eles não querem explicar aos DBAs sobre todo o código. Eles não querem explicar aos seus clientes por que o aplicativo é executado como um cachorro.
Se o seu código depender de as colunas estarem em uma ordem específica, ele será interrompido quando houver alterações na tabela. Além disso, você pode estar buscando demais na tabela ao selecionar *, especialmente se houver um campo binário na tabela.
Só porque você está usando todas as colunas agora, isso não significa que alguém não irá adicionar uma coluna extra à tabela.
Ele também adiciona sobrecarga ao cache de execução do plano, pois precisa buscar os metadados sobre a tabela para saber em que colunas estão *.
fonte
Um dos principais motivos é que, se você adicionar / remover colunas da sua tabela, qualquer consulta / procedimento que esteja fazendo uma chamada SELECT * agora estará recebendo mais ou menos colunas de dados do que o esperado.
fonte
De uma maneira indireta, você está violando a regra da modularidade sobre o uso de digitação estrita sempre que possível. Explícito é quase universalmente melhor.
Mesmo que agora você precise de todas as colunas da tabela, mais poderá ser adicionado posteriormente, que será retirado toda vez que você executar a consulta e poderá prejudicar o desempenho. Dói o desempenho porque
Quando usar, selecione *
Quando você NECESSITAM explicitamente de todas as colunas da tabela, em vez de precisar de todas as colunas da tabela EXISTENTES NO MOMENTO EM QUE VOCÊ ESCREVEU A CONSULTA. Por exemplo, se estivesse escrevendo um aplicativo de gerenciamento de banco de dados que precisava exibir todo o conteúdo da tabela (o que quer que fosse), você poderia usar essa abordagem.
fonte
SELECT *
seria quando você estiver fazendo consultas de teste usando o cliente db.Há algumas razões:
Nota: eu escolhi INTEGER no exemplo acima porque eles têm um tamanho fixo de 4 bytes.
fonte
Se seu aplicativo obtiver dados com SELECT * e a estrutura da tabela no banco de dados for alterada (digamos, uma coluna foi removida), seu aplicativo falhará em todos os locais aos quais você referenciar o campo ausente. Se você incluir todas as colunas na sua consulta, seu aplicativo entrará no (espero) um lugar onde você obtém os dados inicialmente, facilitando a correção.
Dito isto, há várias situações em que SELECT * é desejável. Uma é uma situação que encontro o tempo todo, em que preciso replicar uma tabela inteira em outro banco de dados (como o SQL Server para o DB2, por exemplo). Outro é um aplicativo escrito para exibir tabelas genericamente (ou seja, sem o conhecimento de qualquer tabela específica).
fonte
Na verdade, notei um comportamento estranho quando usei os
select *
modos de exibição no SQL Server 2005.Execute a seguinte consulta e você verá o que quero dizer.
Compare os resultados das duas últimas instruções de seleção. Acredito que o que você verá é o resultado do Select * referenciando colunas por índice, em vez de nome.
Se você reconstruir a exibição, ela funcionará bem novamente.
EDITAR
Eu adicionei uma pergunta separada, * "selecione * da tabela" vs "selecione colA, colB, etc. da tabela" comportamento interessante no SQL Server 2005 * para analisar esse comportamento com mais detalhes.
fonte
Você pode juntar duas tabelas e usar a coluna A da segunda tabela. Se você adicionar posteriormente a coluna A à primeira tabela (com o mesmo nome, mas com um significado diferente), provavelmente obterá os valores da primeira tabela e não da segunda como anteriormente. Isso não acontecerá se você especificar explicitamente as colunas que deseja selecionar.
É claro que especificar as colunas às vezes também causa bugs se você esquecer de adicionar as novas colunas a cada cláusula de seleção. Se a nova coluna não for necessária toda vez que a consulta for executada, poderá levar algum tempo até que o erro seja notado.
fonte
Entendo aonde você está indo com relação à otimização prematura, mas isso realmente só chega a um ponto. A intenção é evitar a otimização desnecessária no início. Suas tabelas não são indexadas? Você usaria o nvarchar (4000) para armazenar um código postal?
Como outros já apontaram, existem outros pontos positivos para especificar cada coluna que você pretende usar na consulta (como a capacidade de manutenção).
fonte
Quando você está especificando colunas, também está se atando a um conjunto específico de colunas e se tornando menos flexível, fazendo Feuerstein rolar, bem, onde quer que esteja. Apenas um pensamento.
fonte
SELECT * nem sempre é mau. Ao menos na minha opinião. Eu o uso frequentemente para consultas dinâmicas que retornam uma tabela inteira, além de alguns campos computados.
Por exemplo, eu quero calcular geometrias geográficas de uma tabela "normal", que é uma tabela sem nenhum campo de geometria, mas com campos que contêm coordenadas. Eu uso o postgresql e sua extensão espacial postgis. Mas o princípio se aplica a muitos outros casos.
Um exemplo:
uma tabela de locais, com coordenadas armazenadas nos campos rotulados x, y, z:
CREATE TABLE coloca (place_id número inteiro, x numérico (10, 3), y numérico (10, 3), z numérico (10, 3), descrição varchar);
vamos alimentá-lo com alguns valores de exemplo:
INSERT INTO places (place_id, x, y, z, description) VALORES
(1, 2.295, 48.863, 64, 'Paris, Place de l \' Étoile '),
(2, 2.945, 48.858, 40,' Paris, Tour Eiffel '),
(3, 0,373, 43,958, 90,' Condom, Cathédrale St-Pierre ');
Quero poder mapear o conteúdo desta tabela, usando algum cliente GIS. A maneira normal é adicionar um campo de geometria à tabela e construir a geometria, com base nas coordenadas. Mas eu preferiria obter uma consulta dinâmica: dessa maneira, quando altero as coordenadas (correções, mais precisão etc.), os objetos mapeados realmente se movem dinamicamente. Então, aqui está a consulta com o SELECT * :
CRIAR OU SUBSTITUIR VISUALIZAR places_points AS
SELECT *,
GeomFromewkt ('SRID = 4326; POINT (' || x || '' || y || '' || z || ')')
FROM places;
Consulte o postgis, para uso da função GeomFromewkt ().
Aqui está o resultado:
SELECT * FROM lugares_pontos;
A coluna mais à direita agora pode ser usada por qualquer programa GIS para mapear corretamente os pontos.
Eu gostaria que a definição do VIEW pudesse ser mantida "como está", com o *, mas hélas não é o caso: é assim que é armazenado internamente pelo postgresql:
SELECT places.place_id, places.x, places.y, places.z, places.description, geomfromewkt (((((((('(SRID = 4326; POINT (' :: text || places.x) || '): : texto) || locais.y) || '' :: texto) || locais.z) || ')' :: texto) AS geomfromewkt FROM locais;
fonte
Mesmo se você usar todas as colunas, mas abordar a matriz de linhas pelo índice numérico, você terá problemas se adicionar outra linha posteriormente.
Então, basicamente, é uma questão de manutenção! Se você não usar o seletor *, não precisará se preocupar com suas consultas.
fonte
Selecionar apenas as colunas necessárias mantém o conjunto de dados na memória menor e, portanto, mantém seu aplicativo mais rápido.
Além disso, muitas ferramentas (por exemplo, procedimentos armazenados) também armazenam em cache os planos de execução de consultas. Se você adicionar ou remover mais tarde uma coluna (particularmente fácil se você estiver selecionando uma visualização), a ferramenta geralmente apresentará erros quando não obtiver os resultados esperados.
fonte
Isso torna seu código mais ambíguo e mais difícil de manter; porque você está adicionando dados extras não utilizados ao domínio e não está claro qual você pretendeu ou não. (Também sugere que você pode não saber ou se importar.)
fonte
Para responder sua pergunta diretamente: Não use "SELECT *" quando isso tornar seu código mais frágil às alterações nas tabelas subjacentes. Seu código deve ser quebrado somente quando uma alteração for feita na tabela que afeta diretamente os requisitos do seu programa.
Seu aplicativo deve tirar proveito da camada de abstração que o acesso relacional fornece.
fonte
Eu não uso SELECT * simplesmente porque é bom ver e saber quais campos estou recuperando.
fonte
Geralmente é ruim usar 'select *' dentro das visualizações porque você será forçado a recompilar a visualização no caso de uma alteração na coluna da tabela. Alterando as colunas da tabela subjacente de uma visualização, você receberá um erro para colunas inexistentes até voltar e recompilar.
fonte
Tudo bem quando você está fazendo,
exists(select * ...)
pois nunca é expandido. Caso contrário, é realmente útil apenas ao explorar tabelas com instruções de seleção temporárias ou se você tiver um CTE definido acima e desejar todas as colunas sem digitá-las novamente.fonte
Apenas para adicionar uma coisa que ninguém mais mencionou.
Select *
retorna todas as colunas, alguém pode adicionar uma coluna posteriormente que você não deseja necessariamente que os usuários possam ver, como quem atualizou os dados pela última vez ou um carimbo de data / hora ou anotações de que somente os gerentes devem ver nem todos os usuários etc.Além disso, ao adicionar uma coluna, o impacto no código existente deve ser revisado e considerado para ver se são necessárias alterações com base nas informações armazenadas na coluna. Ao usar
select *
, essa revisão geralmente é ignorada porque o desenvolvedor assume que nada irá quebrar. E, de fato, nada pode parecer explicitamente quebrar, mas as consultas agora podem começar a retornar a coisa errada. Só porque nada interrompe explicitamente, não significa que não devam ter havido alterações nas consultas.fonte
porque "select *" desperdiçará memória quando você não precisar de todos os campos. Mas, para o servidor sql, o desempenho deles é o mesmo.
fonte