title: Why doesn't my Postgres SQL Query use an index
body: <p>I have a table (sales_points) with ~23M rows. It has a b-tree index on (store_id, book_id). I would expect the following query to use that index, but EXPLAIN indicates that it is doing a sequential scan:</p>
  
  <pre><code>select distinct store_id, book_id from sales_points
  </code></pre>
  
  <p>Here is the output from EXPLAIN:</p>
  
  <pre><code>Unique  (cost=2050448.88..2086120.31 rows=861604 width=8)
    -&gt;  Sort  (cost=2050448.88..2062339.35 rows=23780957 width=8)
          Sort Key: store_id, book_id
          -&gt;  Seq Scan on sales_points  (cost=0.00..1003261.87 rows=23780957 width=8)
  </code></pre>
  
  <p>If I do this, it does use the index:</p>
  
  <pre><code>select distinct book_id from sales_points where store_id = 1
  </code></pre>
  
  <p>Here is the EXPLAIN output from this query:</p>
  
  <pre><code>HashAggregate  (cost=999671.02..999672.78 rows=587 width=4)
    -&gt;  Bitmap Heap Scan on sales_points  (cost=55576.17..998149.04 rows=3043963 width=4)
          Recheck Cond: (store_id = 1)
          -&gt;  Bitmap Index Scan on index_sales_points_on_store_id_and_book_id  (cost=0.00..55423.97 rows=3043963 width=0)
                Index Cond: (store_id = 1)
  </code></pre>
  
  <p>Here is the table DDL:</p>
  
  <pre><code>CREATE TABLE sales_points
  (
    id serial NOT NULL,
    book_id integer,
    store_id integer,
    date date,
    created_at timestamp without time zone,
    updated_at timestamp without time zone,
    avg_list_price numeric(5,2),
    royalty_amt numeric(9,2),
    currency character varying(255),
    settlement_date date,
    paid_sales integer,
    paid_returns integer,
    free_sales integer,
    free_returns integer,
    lent_units integer,
    lending_revenue numeric(9,2),
    is_placeholder boolean,
    distributor_id integer,
    source1_id integer,
    source2_id integer,
    source3_id integer,
    CONSTRAINT sales_points_pkey PRIMARY KEY (id)
  )
  WITH (
    OIDS=FALSE
  );
  </code></pre>
  
  <p>Here is the index expression:</p>
  
  <pre><code>CREATE INDEX index_sales_points_on_store_id_and_book_id
    ON sales_points
    USING btree
    (store_id, book_id);
  </code></pre>
  
  <p>So why wouldn't Postgres use the index to speed up the SELECT?</p>