DOs and DONTs for Indexes
Measure system throughput as a whole. An index may help some queries but harm insert, update and delete.
Create the index.
Measure system throughput as a whole.
If performance is better, leave the index there. If performance is worse, delete it.
Generally speaking:
1. Don't add an index unless you actually need it.
Each index makes writes slower...
2. An index will be used on where clauses:
-- index on foo (bar)
select bar from foo where bar = :bar;
By the same token it'll be used in foreign key references (on both tables).
-- index on foo (bar) if baz (bar) is frequently updated/deleted.
create table foo (bar references baz (bar));
3. An index will be used for sorting, especially when tied to a limit:
-- index on foo (bar)
select bar from foo order by bar limit 10;
4. Multicolumn indexes are occasionally useful when 2. and 3. both apply.
In this case put the where conditions first, and the sort key last:
-- index on foo (baz, bar)
select bar from foo where baz between :baz1 and :baz2 group by bar;
5. Keep your table statistics up to date.
If the table stats are garbage, there is little chances that the optimizer will use your indexes. Manually vacuum/analyze your database if needed.
6. Index usage depends on your table repartition.
Past a certain threshold of rows retrieved, it'll be faster to do a full table scan. If your index is on a boolean field that more or less splits your table in two, it'll never be used.
Likewise, if your data is stored in such a way that the index scan will likely end up randomly accessing nearly ever applicable disk page for that table, the planner will prefer a full table scan.
7. Consider partial/expression indexes when available.
If you've a field that has the same value except for 10% of your rows, consider a partial index on it (i.e. where not that value). This results in a much smaller index without hindering its actual usefulness.
If you're constantly querying against an expression applied to your column and you platform offers expression indexes, consider adding an index on it. When used, the expression won't get evaluated for each row.