32

I have a Rails model with a boolean field that I search on (I use a scope that finds all instances where the field is set to true). I'm using Postgres.

My instinct is to add an index on the boolean field. Is that good practice, or is there something in Postgres that makes an index on a boolean field unnecessary?

2 Answers 2

45

No, you can index a boolean field if you'll be filtering by it. That's a perfectly reasonable thing to do, although as with all indexes, PostgreSQL may choose to ignore it if it won't exclude enough of the table -- an index scan plus a ton of row fetches may be more expensive than a sequential scan -- which may or may not affect you depending on the values in that column.

You should also be aware that PostgreSQL lets you put conditions on indexes, which I often find useful with boolean fields. (See Partial Indexes for details.) If you'll be commonly filtering or sorting within that scope, you might be best served by something like CREATE INDEX ... ON table (some_field) WHERE boolean_field.

Sign up to request clarification or add additional context in comments.

2 Comments

Just to add to this, if your boolean field has 99.9% of one value in it, it can be very helpful to only index the other possible value(s). I.e. 99.9% false, 0% nulls, 0.1% true, then create index .. on table (boolval) where boolval is true; will index only the true values.
@ScottMarlowe - take the example of 'active' records. - where most of them will be 'active' - and most queries will be selecting only active records - its a default_scope - if I index where: 'active = false' - ie the small minority - does that only improve performance on queries that select this minority? - because I dont really care about those queries, - its the queries that ask for active=true - that I am worried about.
18

To create the partial index in a Rails migration, you would do this. In this example, the model is Product and the column is featured.

class AddFeaturedOnProducts < ActiveRecord::Migration
  def change
    add_index(:products, :featured, where: "featured")
  end
end

3 Comments

Dead helpful, thanks. How do you do the opposite and index on the false value? Something like add_index(:products, :featured, where_not: "featured")?
The :where option accepts a query, so you can do: add_index(:products, :featured, where: "featured = false")
I can't seem to get the clause working with false. Filter: ((NOT playoff). Did anyone figure it out?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.