The question may be long but the problem is actually simple. I have 3 models: List, Appearance and Movie. A List has many Movies through an Appearance, and they should be sorted by the attribute rank of the joins model. So what indexes should I be using? This is how my models currently look:
# Models
class Movie < ActiveRecord::Base
has_many :appearances, :dependent => :destroy
has_many :lists, :through => :appearances
end
class Appearance < ActiveRecord::Base
belongs_to :list
belongs_to :movie
end
class List < ActiveRecord::Base
has_many :appearances, :dependent => :destroy
has_many :movies, :through => :appearances
def self.find_complete(id)
List.includes({:appearances => :movie}).where("appearances.rank IS NOT NULL").order("appearances.rank ASC").find(id)
end
end
And here are the indexes I already have. Do I need a composite index? Or just an index by rank?
# Tables
class CreateAppearances < ActiveRecord::Migration
def change
create_table :appearances do |t|
t.integer :list_id, :null => false
t.integer :movie_id, :null => false
t.integer :rank
end
add_index :appearances, :list_id
add_index :appearances, :movie_id
end
end
Finally, is there any way to refactor that find_complete List method? Like using a default_scope? Don’t forget that a rank may be null.
ActiveRecord is doing two queries.
and
In both cases what you need is an index with both lists.id and appearances.rank. Some databases will create indexes on multiple tables. I also don’t know if your database will be smart enough to use an index on appearances.list_id and appearances.rank, but that is worth a try.
If that doesn’t help, at least index :rank, so the database might be able to avoid the sort.