Programadores Precisam Aprender SQL!

De uns tempos para cá, tenho vistos muitos códigos bizarros acontecendo no mundo dos ORMs, que eventualmente me deixaram pensando: será que ORMs estão fazendo-nos esquecer como se faz SQLs?

No mundo Ruby/Rails, virou quase uma regra não-escrita que escrever SQLs na mão é errado. Quanto mais pudermos aproveitar o ActiveRecord (e algumas mágicas que ele faz por nós), melhor. Isso acaba trazendo algumas coisas bem esquisitas, tal como achar que 90% dos códigos nunca vão precisar de “OR” (e maior, menor, diferente, etc), já que a API do ActiveRecord não suporta isso, ou algumas outras práticas meio estranhas. Do outro lado, temos por exemplo o framework “Play!”, de Scala, que faz o extremo oposto: não usa nenhum ORM, e todas as queries SQL passam a ser feitas na mão…

O ponto é que quando temos um ORM, parece que abusamos dele e esquecemos que nem tudo é um “SELECT * FROM <table> WHERE <attribute> = <value>”. Por exemplo, no código abaixo:

users = User.all
users.each do |user|
  puts &quot;User #{user.name} has #{user.addresses.count} addresses&quot;
end

Temos o famoso caso do “N+1”: 1 busca para achar N usuários, e a partir daí “N” buscas para achar a contagem de endereços. O problema é que muita gente acha que apenas um “User.include(:addresses)” resolve o problema, quando na verdade não resolve: o “include” vai trazer todos os endereços, mas a contagem (se o Rails optar por usar “count”) vai continuar sendo feita em banco, ou então (se o Rails optar por não usar “count”) será feita em Ruby, e teremos trazido registros a mais do banco de dados sem necessidade. A solução, nesse caso, é usar um comando SQL mesmo:

users = User.all
num_addresses = Address.join(:user).group('user.id').count
users.each do |user|
  puts &quot;User #{user.name} has #{num_addresses[user.id]} addresses&quot;
end

Ok, mas SQL é difícil, chato, e é mais fácil fazer as coisas em Ruby, certo? Bom, sim e não. É mais fácil fazer os comandos em Ruby (ou na linguagem que você escolher) puramente por “costume”. Estamos acostumados a fazer a sequencia: buscamos uma lista, tratamos a lista, exibimos a lista. SQL não trabalha com “listas”, mas com “conjuntos”. E é isso que vamos ver a seguir:
(more…)