Por que SELECT * seria magnitudes mais rápidas que SELECT foo?

28

Considere uma tabela de valores e hashes, assim:

+------------+----------+------+-----+---------+----------------+
| Field      | Type     | Null | Key | Default | Extra          |
+------------+----------+------+-----+---------+----------------+
| id         | int(11)  | NO   | PRI | NULL    | auto_increment |
| val        | char(9)  | NO   |     | NULL    |                |
| val_hashed | char(50) | YES  |     | NULL    |                |
+------------+----------+------+-----+---------+----------------+

A consulta a seguir termina em 0,00 segundos:

SELECT * FROM hashes ORDER BY 1 DESC LIMIT 1;

No entanto, esta consulta leva 3 minutos e 17 segundos:

SELECT val FROM hashes ORDER BY 1 DESC LIMIT 1;

Vejo que, enquanto a consulta está sendo executada, a lista de processos a mostra como status Sorting result. A situação é completamente reproduzível. Observe que há outro processo executando INSERToperações na tabela continuamente.

Por que a consulta mais específica levaria mais tempo para ser executada do que a *consulta? Sempre acreditei que as *consultas deveriam ser evitadas especificamente por razões de desempenho.

dotancohen
fonte
7
As primeiras instruções provavelmente usam o índice de chave primária idpara encontrar a primeira linha. O segundo precisa classificar o resultado completo na valcoluna (não indexada) .
A_horse_with_no_name 27/07
8
A ORDER BY NUMBERsintaxe é propensa a erros.
usr
2
Adicionando ao seu último comentário, SELECT *combinado com um índice de coluna em, ORDER BYestá ofuscando qual coluna está sendo classificada - outro motivo para evitar *s ...
lc.
@lc., o que você quer dizer?
Pacerier
@ Pacerier Quero dizer, o *não é explícito. Dizer "me dê todas as colunas e classifique pela terceira" é tão determinístico quanto dizer "vá ao supermercado e me diga quantos semáforos você passou"
lc.

Respostas:

33

A frase ORDER BY 1refere-se a diferentes colunas; no primeiro será id, no segundo val. Como idé a chave, ela será indexada e order byserá uma quantidade trivial de trabalho. Para order by val, no entanto, o sistema precisará recuperar todas as linhas, classificar a tabela completa vale escolher apenas uma dessas linhas.

Altere as duas consultas para order by ide acho que seus tempos de execução serão quase idênticos.

Michael Green
fonte
3
Às vezes, as perguntas mais complicadas são aquelas que estão nos encarando. Obrigado Michael!
dotancohen
7

A diferença de desempenho em sua consulta é bem explicada por MG. Vou abordar isso:

Sempre acreditei que * as consultas devem ser evitadas especificamente por razões de desempenho.

select *não possui penalidades particulares por si só, é problemático quando usado indevidamente. Em uma consulta de tabela única, funciona muito bem. agora junte essa tabela a outra com 20 colunas e depois adicione junções a outras 5 tabelas com muitas colunas cada. Agora é um problema. O mesmo acontece com as pessoas que ensinam band-aid amplo "nunca fazem X" sem explicar o porquê.

Paulo
fonte
3
SELECT *pode ser um problema mesmo para uma consulta de tabela única. Por exemplo, SELECT * FROM hashes ORDER BY val;provavelmente fará uma varredura completa da tabela e, em seguida, uma classificação SELECT val FROM hashes ORDER BY val;fará apenas uma varredura completa do índice e nenhuma classificação (supondo que exista um índice em val). Portanto, nunca é demais selecionar apenas os resultados que precisamos.
ypercubeᵀᴹ
Eu suponho que você já viu isso? sqlblog.com/blogs/aaron_bertrand/archive/2009/10/10/…
Max Vernon
@ypercube, isso ocorre mesmo se o nosso select(*)for usado apenas como uma sub- seleção? Como é uma seleção incorporada, o MySQL não seria inteligente o suficiente para descobrir as colunas reais que precisam ser selecionadas?
Pacerier
O @Pacerier mysql optimizer possui diferentes níveis de "inteligência", dependendo da versão que você está usando. Em geral, era bastante estúpido em subconsultas aninhadas; portanto, o que você puder para ajudá-lo, era bom.
precisa saber é o seguinte
@ypercube, Ah, se é tão inteligente quanto o pgsql.
Pacerier 9/04