AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 69361
Accepted
Piers Karsenbarg
Piers Karsenbarg
Asked: 2014-07-01 06:07:35 +0800 CST2014-07-01 06:07:35 +0800 CST 2014-07-01 06:07:35 +0800 CST

O select * ainda é um grande problema no SQL Server 2012?

  • 772

Antigamente, era considerado um grande não-não a fazer select * from tableou select count(*) from tablepor causa do desempenho atingido.

Esse ainda é o caso em versões posteriores do SQL Server (estou usando 2012, mas acho que a pergunta se aplica a 2008 - 2014)?

Edit: Como as pessoas parecem estar me criticando um pouco aqui, estou olhando para isso de um ponto de vista acadêmico/referente, não se é a coisa "certa" a fazer (o que obviamente não é)

sql-server sql-server-2012
  • 8 8 respostas
  • 11868 Views

8 respostas

  • Voted
  1. Best Answer
    RLF
    2014-07-01T06:20:57+08:002014-07-01T06:20:57+08:00

    Se você SELECT COUNT(*) FROM TABLEretornar apenas uma linha (a contagem), é relativamente leve e é o caminho para obter esse dado.

    E SELECT *não é um não-não físico, pois é legal e permitido.

    No entanto, o problema SELECT *é que você pode causar muito mais movimentação de dados. Você opera em todas as colunas da tabela. Se você SELECTincluir apenas algumas colunas, poderá obter sua resposta de um índice ou índices, o que reduz a E/S e também o impacto no cache do servidor.

    Portanto, sim , não é recomendado como prática geral porque é um desperdício de seus recursos.

    O único benefício real SELECT *é não digitar todos os nomes das colunas. Mas a partir do SSMS você pode arrastar e soltar para obter os nomes das colunas em sua consulta e excluir aquelas de que não precisa.

    Uma analogia: se alguém usa SELECT *quando não precisa de todas as colunas, também usaria SELECTsem WHERE(ou alguma outra cláusula limitante) quando não precisa de todas as linhas?

    • 50
  2. Stuart Blackler
    2014-07-01T11:16:22+08:002014-07-01T11:16:22+08:00

    Além da resposta já fornecida, acho que vale a pena apontar que os desenvolvedores costumam ser muito preguiçosos ao trabalhar com ORMs modernos, como o Entity Framework. Enquanto os DBAs tentam ao máximo evitar SELECT *, os desenvolvedores geralmente escrevem o equivalente semanticamente, por exemplo, em c# Linq:

    var someVariable = db.MyTable.Where(entity => entity.FirstName == "User").ToList();
    

    Em essência, isso resultaria no seguinte:

    SELECT * FROM MyTable WHERE FirstName = 'User'
    

    Há também uma sobrecarga adicional que ainda não foi coberta. Esses são os recursos necessários para processar cada coluna em cada linha para o objeto relevante. Além disso, para cada objeto mantido na memória, esse objeto deve ser limpo. Se você selecionar apenas as colunas necessárias, poderá economizar facilmente mais de 100 MB de RAM. Embora não seja uma quantia enorme por conta própria, é o efeito cumulativo da coleta de lixo, etc., que é o custo do lado do cliente.

    Então, sim, pelo menos para mim, é e sempre será um grande não. Também precisamos educar sobre os custos "ocultos" de fazer isso mais também.

    Termo aditivo

    Aqui está uma amostra de puxar apenas os dados que você precisa, conforme solicitado nos comentários:

    var someVariable = db.MyTable.Where(entity => entity.FirstName == "User")
                                 .Select(entity => new { entity.FirstName, entity.LastNight });
    
    • 24
  3. Greenstone Walker
    2014-07-01T15:09:57+08:002014-07-01T15:09:57+08:00

    Desempenho: uma consulta com SELECT * provavelmente nunca será uma consulta de cobertura ( Explicação de conversa simples, Explicação de estouro de pilha ).

    À prova de futuro: sua consulta pode retornar todas as sete colunas hoje, mas se alguém adicionar cinco colunas no próximo ano, em um ano sua consulta retornará doze colunas, desperdiçando E/S e CPU.

    Indexação: se você deseja que suas exibições e funções com valor de tabela participem da indexação no SQL Server, essas exibições e funções devem ser criadas com schemabinding, que proíbe o uso de SELECT *.

    Prática recomendada : nunca use SELECT *em código de produção.

    Para subconsultas, prefiro WHERE EXISTS ( SELECT 1 FROM … ).

    Edit : Para abordar o comentário de Craig Young abaixo, usar "SELECT 1" em uma subconsulta não é uma "'otimização" - é para que eu possa ficar na frente da minha turma e dizer "não use SELECT *, sem exceções! "

    A única exceção em que consigo pensar é onde o cliente está fazendo algum tipo de operação de tabela dinâmica e requer todas as colunas presentes e futuras.

    Posso aceitar uma exceção envolvendo CTEs e tabelas derivadas, embora queira ver os planos de execução.

    Observe que considero COUNT(*)uma exceção a isso porque é um uso sintático diferente de "*".

    • 13
  4. RBarryYoung
    2014-07-01T13:28:59+08:002014-07-01T13:28:59+08:00

    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 em Views (*), em subconsultas, em cláusulas EXIST, em CTEs, nem em SELECT COUNT(*)..etc., etc. Observe que isso provavelmente também é verdade para Oracle, 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 por que (e por que ainda pode ser um problema em um SELECT de nível superior), é útil entender por que sempre foi um problema, porque usar SELECT *..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 no disco quanto na rede.

    O que é menos óbvio é que isso também restringe quais índices e planos de consulta um otimizador SQL pode usar, porque ele sabe que deve retornar todas as colunas de dados. Se ele pudesse saber com antecedência que você deseja apenas determinadas colunas, geralmente poderá usar planos de consulta mais eficientes, aproveitando os índices que possuem apenas essas colunas. Felizmente, há uma maneira de saber disso com antecedência, que é você especificar explicitamente as colunas que deseja na lista de colunas. Mas quando você usa "*", você está abrindo mão disso 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 cada coluna, mas quase sempre é menor em comparação com essas duas coisas: o disco extra significativo e a largura de banda de rede necessária para 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 SQL Optimizers incorporaram com sucesso um recurso chamado "Otimização de coluna", 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 inferiores/internos 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 *..no topo, então, mais uma vez, deve assumir que você deseja TODAS as colunas e, portanto, não pode empregar otimizações de coluna de forma eficaz.

    (* -- observe que há um problema de ligação menor e diferente nas exibições *em que nem sempre registram a alteração nas listas de colunas quando "*" é usado. Existem outras maneiras de resolver isso e isso não afeta o desempenho.)

    • 10
  5. Jon of All Trades
    2014-07-03T05:15:10+08:002014-07-03T05:15:10+08:00

    Há mais um pequeno motivo para não usar SELECT *: se a ordem das colunas retornadas mudar, seu aplicativo irá quebrar... se você tiver sorte. Caso contrário, você terá um bug sutil que pode passar despercebido por muito tempo. A ordem dos campos em uma tabela é um detalhe de implementação que nunca deve ser considerado pelos aplicativos, pois a única vez que fica visível é se você usar um arquivo SELECT *.

    • 5
  6. CharlieHorse
    2014-07-02T06:50:58+08:002014-07-02T06:50:58+08:00

    É fisicamente e problemático usar select * from table, no entanto, é uma má ideia. Por quê?

    Em primeiro lugar, você descobrirá que está retornando colunas desnecessárias (recursos pesados).

    Em segundo lugar, levará mais tempo em uma tabela grande do que nomear as colunas porque, quando você seleciona *, na verdade está selecionando os nomes das colunas do banco de dados e dizendo "me dê os dados associados às colunas que têm nomes nesta 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 torna as coisas mais difíceis para o desenvolvedor. Com que frequência você precisa alternar do SSMS para o VS para obter todos os nomes das colunas?

    Em quarto lugar, é um sinal de programação preguiçosa e não acho que nenhum desenvolvedor queira essa reputação.

    • 3
  7. Mark Ross
    2014-07-02T15:29:48+08:002014-07-02T15:29:48+08:00

    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 você esperava quando 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á examinando valores de campo para os quais não foi escrito. Resumindo, o código de produção SEMPRE deve especificar os campos a serem retornados no arquivo SELECT.

    Dito isso, tenho menos problema quando o Select *faz parte de uma EXISTScláusula, pois tudo o que vai 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 sobre isso. PODE ser um pouco menos eficiente codificar Select *do que codificar 'Selecionar 1' em uma EXISTScláusula, mas não acho que haja perigo de corrupção de dados, de qualquer maneira.

    • 3
  8. UnhandledExcepSean
    2014-07-03T07:09:01+08:002014-07-03T07:09:01+08:00

    Muitas respostas por que select *está errado, então cobrirei quando achar que está certo ou pelo menos OK.

    1) Em um EXISTS, o conteúdo da parte SELECT da query é ignorado, então você pode até escrever SELECT 1/0e não vai dar erro. EXISTSapenas verifica se alguns dados retornariam e retorna um booleano com base nisso.

    IF EXISTS(
        SELECT * FROM Table WHERE X=@Y
    )
    

    2) Isso pode iniciar uma tempestade de fogo, mas gosto de usar select *gatilhos em minha tabela de histórico. Por select *, evita que a tabela principal obtenha uma nova coluna sem adicionar a coluna à tabela de histórico, bem como por erros imediatos ao inserir/atualizar/excluir na tabela principal. Isso evitou várias vezes que os desenvolvedores adicionassem colunas e se esquecessem de adicioná-las à tabela de histórico.

    • 2

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve