| From: | Nguyễn Thành <ntthanh120192(at)gmail(dot)com> |
|---|---|
| To: | pgsql-performance(at)postgresql(dot)org |
| Subject: | Question: ALTER COLUMN TYPE rebuilds child indexes when a parent partitioned index references the altered column |
| Date: | 2026-07-14 02:52:56 |
| Message-ID: | CAFevQGYY43mwzWEWoaRm461S2oxwBFYzSq3ze2DFo3EmFj4TcA@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-performance |
Hi,
I'm trying to understand whether the following behavior is expected in
PostgreSQL.
Environment
- PostgreSQL 15.17
- Declarative partitioning
- B-tree indexes
According to the documentation, increasing the length of a varchar column
does not require a table rewrite.
PostgreSQL: Documentation: 15: ALTER TABLE
However, I observed different behaviors depending on whether the parent
partitioned table has an index referencing the altered column.
========================================================================
Case 1 - No parent index
========================================================================
CREATE TABLE orders
(
id bigint,
order_date date,
data_field varchar(30),
PRIMARY KEY (id, order_date)
) PARTITION BY RANGE (order_date);
CREATE TABLE orders_p202510
PARTITION OF orders
FOR VALUES FROM ('2025-10-01') TO ('2025-11-01');
CREATE INDEX orders_p202510_data_field_idx
ON orders_p202510(data_field);
ALTER TABLE orders
ALTER COLUMN data_field TYPE varchar(50);
Observation:
- No heap rewrite occurs.
- pg_stat_progress_cluster remains empty.
- pg_stat_progress_create_index remains empty.
- relfilenode of orders_p202510_data_field_idx remains unchanged.
========================================================================
Case 2 - Parent partitioned index exists
========================================================================
CREATE TABLE orders
(
id bigint,
order_date date,
data_field varchar(30),
PRIMARY KEY (id, order_date)
) PARTITION BY RANGE (order_date);
CREATE TABLE orders_p202510
PARTITION OF orders
FOR VALUES FROM ('2025-10-01') TO ('2025-11-01');
CREATE INDEX idx_orders_data_field
ON orders(data_field);
ALTER TABLE orders
ALTER COLUMN data_field TYPE varchar(50);
Observation:
- No heap rewrite occurs.
- pg_stat_progress_cluster remains empty.
- pg_stat_progress_create_index reports:
command = CREATE INDEX
phase = building index: scanning table
- relfilenode of the child index changes.
- ALTER TABLE execution time increases proportionally with the child index
size.
========================================================================
Additional observations
========================================================================
I also tested other parent index definitions.
The behavior is the same whether data_field is:
CREATE INDEX idx1 ON orders(data_field);
or
CREATE INDEX idx2 ON orders(id) INCLUDE (data_field);
In both cases, child indexes are rebuilt.
On the other hand, if the parent table has no index referencing data_field,
child indexes are left untouched.
From my testing, the deciding factor appears to be simply the existence of
a parent index that depends on the altered column.
========================================================================
Questions
========================================================================
1. Is this expected behavior?
2. If so, what is the rationale for rebuilding child indexes even though
the heap itself is not rewritten?
3. Is rebuilding triggered simply because a parent partitioned index
depends on the altered column, or is there another internal reason for
doing so?
I searched the documentation and mailing list archives but couldn't find
any discussion describing this specific behavior.
Any clarification would be greatly appreciated.
Thank you.
| From | Date | Subject | |
|---|---|---|---|
| Next Message | MAILBOX-DBS | 2026-07-30 13:41:03 | pg_stat_statement not collecting information about queries inside functions. |
| Previous Message | Merlin Moncure | 2026-05-11 17:59:54 | Re: Improving insert performance |