queries involving only <literal>y</literal>. Just
how useful will depend on how effective the B-tree index skip scan
optimization is; if <literal>x</literal> has no more than several hundred
distinct values, skip scan will make searches for specific
<literal>y</literal> values execute reasonably efficiently. A combination
of a multicolumn index on <literal>(x, y)</literal> and a separate index on
<literal>y</literal> might also serve reasonably well. For
queries involving only <literal>x</literal>, the multicolumn index could be
used, though it would be larger and hence slower than an index on
<literal>x</literal> alone. The last alternative is to create all three
indexes, but this is probably only reasonable if the table is searched
much more often than it is updated and all three types of query are
common. If one of the types of query is much less common than the
others, you'd probably settle for creating just the two indexes that
best match the common types.
</para>
</sect1>
<sect1 id="indexes-unique">
<title>Unique Indexes</title>
<indexterm zone="indexes-unique">
<primary>index</primary>
<secondary>unique</secondary>
</indexterm>
<para>
Indexes can also be used to enforce uniqueness of a column's value,
or the uniqueness of the combined values of more than one column.
<synopsis>
CREATE UNIQUE INDEX <replaceable>name</replaceable> ON <replaceable>table</replaceable> (<replaceable>column</replaceable> <optional>, ...</optional>) <optional> NULLS <optional> NOT </optional> DISTINCT </optional>;
</synopsis>
Currently, only B-tree indexes can be declared unique.
</para>
<para>
When an index is declared unique, multiple table rows with equal
indexed values are not allowed. By default, null values in a unique column
are not considered equal, allowing multiple nulls in the column. The
<literal>NULLS NOT DISTINCT</literal> option modifies this and causes the
index to treat nulls as equal. A multicolumn unique index will only reject
cases where all indexed columns are equal in multiple rows.
</para>
<para>
<productname>PostgreSQL</productname> automatically creates a unique
index when a unique constraint or primary key is defined for a table.
The index covers the columns that make up the primary key or unique
constraint (a multicolumn index, if appropriate), and is the mechanism
that enforces the constraint.
</para>
<note>
<para>
There's no need to manually
create indexes on unique columns; doing so would just duplicate
the automatically-created index.
</para>
</note>
</sect1>
<sect1 id="indexes-expressional">
<title>Indexes on Expressions</title>
<indexterm zone="indexes-expressional">
<primary>index</primary>
<secondary sortas="expressions">on expressions</secondary>
</indexterm>
<para>
An index column need not be just a column of the underlying table,
but can be a function or scalar expression computed from one or
more columns of the table. This feature is useful to obtain fast
access to tables based on the results of computations.
</para>
<para>
For example, a common way to do case-insensitive comparisons is to
use the <function>lower</function> function:
<programlisting>
SELECT * FROM test1 WHERE lower(col1) = 'value';
</programlisting>
This query can use an index if one has been
defined on the result of the <literal>lower(col1)</literal>
function:
<programlisting>
CREATE INDEX test1_lower_col1_idx ON test1 (lower(col1));
</programlisting>
</para>
<para>
If we were to declare this index <literal>UNIQUE</literal>, it would prevent
creation of rows whose <literal>col1</literal> values differ only in case,
as well as rows whose <literal>col1</literal> values are actually identical.
Thus, indexes on expressions can be used to enforce constraints that
are not definable as simple unique constraints.
</para>
<para>