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 mostra como status Sorting result
. A situação é completamente reproduzível. Observe que há outro processo realizando INSERT
operaçõ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 devem ser evitadas especificamente por motivos de desempenho.
A frase
ORDER BY 1
refere-se a diferentes colunas; no primeiro seráid
, no segundoval
. Comoid
é a chave, ela será indexada eorder by
será uma quantidade trivial de trabalho. Paraorder by val
, no entanto, o sistema terá que recuperar todas as linhas, classificar a tabela completa porval
, e então escolher apenas uma dessas linhas.Altere ambas as consultas para
order by id
e acho que seus tempos de execução serão quase idênticos.A diferença de desempenho na sua consulta é bem explicada pelo MG. Eu vou abordar isso:
select *
não acarreta penalidades particulares por si só, é problemático quando mal utilizado. Em uma consulta de tabela única, funciona muito bem. agora junte essa tabela a outra com 20 colunas e depois adicione junções a 5 outras tabelas com muitas colunas cada. AGORA é um problema. O mesmo acontece com as pessoas que ensinam "nunca faça X" amplo e esfarrapado sem explicar o porquê.