I'm trying to reason about how Postgres partial indexes are stored inside Postgres. Suppose I create an index like this
CREATE INDEX orders_unbilled_index ON orders (order_nr)
WHERE billed is not true
in order to quickly run a query like
SELECT *
FROM orders
WHERE billed is not true AND order_nr > 1000000
Postgres obviously stores an index on order_nr
built over a subset of the orders
table as defined by the conditional expression billed is not true
. However, I have a couple of questions related to this:
- Does Postgres store another index internally on
billed is not true
to quickly find the rows associated with the partial index? - If (1) is not the case, would it then make the query above run faster if I made a separate index on
billed is not true
? (assuming a large table and few rows withbilled is true
)
EDIT: My example query based on the docs is not the best due to how boolean indexes are rarely used, but please consider my questions in the context of any conditional expression.
A b-tree index can be thought of an ordered list of index entries, each with a pointer to a row in the table.
In a partial index, the list is just smaller: there are only index entries for rows that meet the condition.
If you have the index condition in your
WHERE
clause, PostgreSQL knows it can use the index and doesn't have to check the index condition, because it will be satisfied automatically.So:
No, any row found via the index will automatically satisfy the index condition, so using the index is enough to make sure it is satisfied.
No, an index on a boolean column will not be used, because it would not be cheaper than this partial index, and the partial index can be used to check the condition on
order_nr
as well.It is actually the other way around: the partial index could well be used for queries that only have the
boolean
column in theWHERE
condition, if there are few enough rows that satisfy the condition.