5

With the below relationship in mind:

class Style < ActiveRecord::Base
  has_many :stylefeatures, :dependent => :destroy
  has_many :features, :through => :stylefeatures
end

class Stylefeature < ActiveRecord::Base
  belongs_to :style
  belongs_to :feature
end

class Feature < ActiveRecord::Base
  has_many :stylefeatures, :dependent => :destroy
  has_many :styles, :through => :stylefeatures
end

How would I most efficiently add indexes to speed up this method in the Style model:

  def has_feature? (arg)
    self.features.where(:name=>arg).exists?
  end
Abram
  • 39,950
  • 26
  • 134
  • 184

3 Answers3

7
class AddIndexesToStyleFeatures < ActiveRecord::Migration
  def self.up
    add_index :stylefeatures , [:style_id , :feature_id] , :unique => true
    add_index :features , :name    # check your data before making this unique
  end

  def self.down
    drop_index :features , :name
    drop_index :stylefeatures, [:style_id , :feature_id]
  end
end

You might want to make the :name index on the :features class unique, but beware of this catch:

If you have records which can contain NULL / nil fields which are part of the index, then don't use unique indexes. => check your data first

If during deletion of features it could happen that a StyleFeatures entry gets a nil reference (instead of being deleted altogether), then having a unique index will also cause problems for that table.

Make sure to double-check on how your particular database handles indexes when querying on null values.

See: Rails uniqueness constraint and matching db unique index for null column

and: How to create a unique index on a NULL column?

Tilo
  • 33,354
  • 5
  • 79
  • 106
  • see comment in my answer – Tilo Sep 20 '13 at 22:23
  • As it turns out I already have this in my schema add_index "stylefeatures", ["feature_id"], :name => "index_stylefeatures_on_feature_id" add_index "stylefeatures", ["style_id"], :name => "index_stylefeatures_on_style_id" – Abram Sep 20 '13 at 22:26
  • I will drop the index and re-add it. – Abram Sep 20 '13 at 22:27
2

I'd recomend adding a unique index on stylefeatures style_id and feature_id (as an array) and a unique index on features.name.

Almaron
  • 4,127
  • 6
  • 26
  • 48
  • AS IN add_index :stylefeatures, [:style_id, :feature_id], :unique => true AND add_index :features, :name, :unique => true – Abram Sep 20 '13 at 22:17
1

Small change to answer by Tilo: use remove_index instead of drop_index:

class AddIndexesToStyleFeatures < ActiveRecord::Migration
  def self.up
    add_index :stylefeatures , [:style_id , :feature_id] , :unique => true
  end

  def self.down
    remove_index :stylefeatures, [:style_id , :feature_id]
  end
end
Martin Fenner
  • 76
  • 2
  • 2