Muitas vezes, precisamos escrever queries pesadas para realizar determinadas buscas no banco de dados e a ajuda de um framework como o Ruby on Rails é sempre bem vinda. Contudo, se você quer tirar melhor proveito do framework e otimizar consultas pesadas, precisa entender o que acontece por baixo dos panos. Pensando nisso, vou mostrar algumas técnicas do Rails para otimizar a performance das suas queries e consequentemente melhorar o tempo de resposta do seu sistema.
Otimizar acesso ao banco
Sempre que executamos uma query no banco de dados, o Rails abre uma ActiveRecord::Relation. Por isso, é importante se esforçar para que tudo aconteça dentro de uma única query, evitando assim que o Rails abra mais de uma relation. A melhor maneira de desenvolver isso é utilizando scope com subqueries.
Utilizando scope
O scope funciona perfeitamente para manter tudo na mesma relation, com ele é possível concatenar quantas queries você precisar. Veja nesse simples exemplo.
class Student < ActiveRecord::Base scope :from_school, -> (school_id) { where(school_id: school_id) } scope :active, -> { where(status: :active) } def self.search(filters) students = all students = students.from_school(filters[:school_id]) if filters[:school_id] students = students.active if filters[:active] students end end
Subqueries
Uma query pode ser mais complexa que outra, quando por exemplo for necessário utilizar joins.
class Library < ActiveRecord::Base scope :active, -> { where(status: :active) } end class Book < ActiveRecord::Base belongs_to :library scope :from_library_active, -> { joins(:library) .where(libraries: { id: Library.select(:id).active } ) } end
Nesse caso foi utilizado o método select, retornando só o campo necessário e fazendo uma query bem leve, alem disso realiza uma subquery na mesma relation.
Próximo capítulo…
Esse foi o primeiro post sobre consultas ao banco de dados com rails, espero ter ajudado com essas dicas para otimizar suas queries. Existem outras coisas bem interessantes no Rails 4 que vou mostrar em um próximo capítulo.