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…)

Otimizando com Javascript

Inicialmente, o nome desse post era pra ser: “otimizar ou escalar?”, mas acabei optando por este outro nome. Afinal, a postagem é sobre como foi otimizado, então…

Há algum tempo, aqui em meu trabalho, sofríamos com um sistema meio problemático: o sistema em questão é um sistema montado para que alunos possam escolher disciplinas, e é feito em duas fases. Nosso problema específico era com a segunda fase: um aluno só pode escolher uma disciplina desde que ela possua vagas, e como há certas disciplinas que muitas pessoas querem, isso vira uma corrida contra o tempo: praticamente metade da universidade acessando o sistema ao mesmo tempo, para conseguir sua vaga, e o sistema demorando muito tempo para completar cada requisição, enfileirando requisições, e um tempo absurdo para atender cada uma…

Enfim, foi jogado mais poder de processamento, mas para cada um processador que acrescentávamos, entravam mais quinheitos alunos, e cerca de cem disciplinas. Claramente, não haveria load-balancer que aguentasse, nem máquina que pudesse aceitar. Estudamos uma base não-relacional, diversas soluções, até chegar em uma: processar a página no cliente.
(more…)