Hi all,
I noticed that when creating a partial index with multiple predicates in
the WHERE clause, the order in which I write the predicates appears to
affect the index build time (specifically the index validation phase).

I created an index with this WHERE clause:

  CREATE INDEX CONCURRENTLY idx_v1
      ON my_table (tenant_id, jsonb_extract_path_text(data, 'field1'),
object_type, id)
      WHERE deleted IS NULL
        AND jsonb_extract_path_text(data, 'field1') <> ''
        AND object_type = 'SpecificType';

  Then I tried reordering the predicates to put expensive operations last:

  CREATE INDEX CONCURRENTLY idx_v2
      ON my_table (tenant_id, jsonb_extract_path_text(data, 'field1'),
object_type, id)
      WHERE deleted IS NULL
        AND object_type = 'SpecificType'
        AND jsonb_extract_path_text(data, 'field1') <> '';

The second version (idx_v2) was significantly faster to build
Looking at the PostgreSQL source, it appears that:
  - Regular query WHERE clauses go through the planner's
order_qual_clauses()
  function (in createplan.c), which sorts predicates by cost
  - Partial index predicates appear to go through ExecPrepareQual() (in
execExpr.c),
  which processes predicates in the given order without reordering

This seems to be a difference between how the planner handles query
predicates versus how the executor handles index predicates.

Is this expected/intended behavior?
Is there a reason partial index predicates aren't reordered by cost?

I'm using Postgres 16.9

Thanks for any insights!
Arik Schimmel

Reply via email to