Thread: Question on creating keys on partitioned tables

Question on creating keys on partitioned tables

From
Siddharth Jain
Date:
Hi All,

I have this question. Say I create a partitioned table on column X.

Option 1:

I add a primary key on (X,Y). Y is another column. Even though Y is a globally unique PK (global meaning it is unique across partitions, not just in one partition), Postgres does not allow me to create a PK on Y in a partitioned table.

Option 2:

I add PK on Y on each of the partitions

Are these not equivalent? If not, which is better and why? 

Thanks

S.

PS: This is what my best friend had to say:

In PostgreSQL partitioning, the decision of where to place the primary key can depend on the specific requirements of the application and the partitioning strategy being used.


If you are using the "table inheritance" approach to partitioning, where child tables inherit from a parent table, then the primary key should be placed on the parent table. This is because the child tables do not have their own primary key constraints, and their primary key columns are inherited from the parent table.


On the other hand, if you are using the "declarative partitioning" approach, where each partition is a separate table defined within a partitioned table, then the primary key can be placed on either the parent table or the child tables. However, placing the primary key on the child tables can improve query performance, as it allows for more efficient indexing and partition pruning.


In summary, if you are using table inheritance for partitioning, place the primary key on the parent table. If you are using declarative partitioning, you can choose to place the primary key on either the parent table or the child tables, with potential performance benefits for placing it on the child tables.


Re: Question on creating keys on partitioned tables

From
Laurenz Albe
Date:
On Thu, 2023-03-30 at 17:05 -0700, Siddharth Jain wrote:
> I have this question. Say I create a partitioned table on column X.
>
> Option 1:
>
> I add a primary key on (X,Y). Y is another column. Even though Y is a globally unique PK (global meaning it is unique
acrosspartitions, not just in one partition), Postgres does not allow me to 
> create a PK on Y in a partitioned table.
>
> Option 2:
>
> I add PK on Y on each of the partitions
>
> Are these not equivalent? If not, which is better and why?

No, they are not equivalent.

Option 2 comes closer to guaranteeing uniqueness for column X, so use that.

> PS: This is what my best friend had to say:
>
> [...] If you are using the "table inheritance" approach [...]

Don't even consider that.  Declarative partitioning is so much better.

Yours,
Laurenz Albe



Re: Question on creating keys on partitioned tables

From
Siddharth Jain
Date:
Thanks Laurenz.

I think the two are equivalent. If not, could you please explain why? 

On Fri, Mar 31, 2023 at 6:46 AM Laurenz Albe <laurenz.albe@cybertec.at> wrote:
On Thu, 2023-03-30 at 17:05 -0700, Siddharth Jain wrote:
> I have this question. Say I create a partitioned table on column X.
>
> Option 1:
>
> I add a primary key on (X,Y). Y is another column. Even though Y is a globally unique PK (global meaning it is unique across partitions, not just in one partition), Postgres does not allow me to
> create a PK on Y in a partitioned table.
>
> Option 2:
>
> I add PK on Y on each of the partitions
>
> Are these not equivalent? If not, which is better and why?

No, they are not equivalent.

Option 2 comes closer to guaranteeing uniqueness for column X, so use that.

> PS: This is what my best friend had to say:
>
> [...] If you are using the "table inheritance" approach [...]

Don't even consider that.  Declarative partitioning is so much better.

Yours,
Laurenz Albe

Re: Question on creating keys on partitioned tables

From
Tom Lane
Date:
Siddharth Jain <siddhsql@gmail.com> writes:
> I think the two are equivalent. If not, could you please explain why?

Well, they're formally equivalent if you require there to be only one
X value per partition (ie, PARTITION BY LIST with only one listed value
per partition); if there's more, they're not the same thing.

Neither one guarantees that Y is globally unique.  We have no mechanism
for enforcing uniqueness across partitions except for partition key
columns.

            regards, tom lane



Re: Question on creating keys on partitioned tables

From
Siddharth Jain
Date:


On Fri, Mar 31, 2023 at 9:07 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:
Siddharth Jain <siddhsql@gmail.com> writes:
> I think the two are equivalent. If not, could you please explain why?

Well, they're formally equivalent if you require there to be only one
X value per partition (ie, PARTITION BY LIST with only one listed value
per partition); if there's more, they're not the same thing.

Yes. This is what I have. I think I understand now. Is following correct?

when a PK is created on (X,Y) on the parent table what happens internally is that the command is run individually on each of the child tables. nothing more. nothing less.

 

Neither one guarantees that Y is globally unique.  We have no mechanism
for enforcing uniqueness across partitions except for partition key
columns.

                        regards, tom lane

Re: Question on creating keys on partitioned tables

From
Laurenz Albe
Date:
On Fri, 2023-03-31 at 10:35 -0700, Siddharth Jain wrote:
> Is following correct?
>
> when a PK is created on (X,Y) on the parent table what happens internally is that the
> command is run individually on each of the child tables. nothing more. nothing less.

If you are talking about inheritance, no.  Creating a constraint on the parent table
has no effect on a child table.

If you are talking about partitioning: If you create a primary key on the partitioned
table, that will be implemented by a partitioned index.  That partitioned index consists
of a unique index for each partition.  So I guess that is more or less what you mean.

There are some differences between a primary key on the partitioned table and a unique
index on each partition:
- the primary key is a constraint, so it can be the target of a foreign key
- the primary key will force a unique index on each new partition
- the primary key keeps you from dropping the unique index on the partitions

Yours,
Laurenz Albe