I am trying to ALTER a table to use partitions LIST in postgres 11. I have been trying for hours but i keep getting errors.
I have a huge table, clients, with ( client_id, customer_id, value).
I have already created a new empty table, clients, by renaming the old table to clients_old and then created the new table with: CREATE TABLE clients( like clients_old including all).
And from here I am stuck when trying to add the LIST partition.
I have tried to:
ALTER TABLE Clients attach PARTITION BY LIST (client_id) --> fail;
ALTER TABLE Clients attach PARTITION LIST (client_id) --> fail;
ALTER TABLE Clients ADD PARTITION LIST (client_id) --> fail;
What syntax should I use to alter the table to use partitions?
Quote from the manual
It is not possible to turn a regular table into a partitioned table or vice versa
So, you can not change an existing non-partitioned table to a partitioned table.
You need to create a new table (with a different name) that is partitioned, create all necessary partitions and then copy the data from the old table to the new, partitioned table.
Something like:
create table clients_partitioned
(
.... all columns ...
)
PARTITION BY LIST (client_id);
Then create the partitions:
create table clients_1
partition of clients_partioned
for values in (1,2,3);
create table clients_1
partition of clients_partioned
for values in (4,5,6);
Then copy the data:
insert into clients_partitioned
select *
from clients;
Once that is done, you can drop the old table and rename the new table:
drop table clients;
alter table clients_partitioned rename to clients;
Don't forget to re-create your foreign keys and indexes.
I had to add for tag in order to add the partition:
create table clients_1
partition of clients_partioned
for values in (4,5,6);
because without for was a syntax error.
Related
I have a Postgres table named: services, and it has columns called id, mac_addr, dns_name, hash, and it is partitioned based on mac_addr, so the partition tables names look like: services_3eeeea123e3 and so on. And there are around 20K partition based on mac_addrs
Q1: there was no index created when the tables were created. so now, when I am trying to add an index CREATE INDEX idx_services_id on services (id), it throws an error ERROR: cannot create an index on partitioned table "services"
But I am able to add indexes to individual partitioned tables CREATE INDEX idx_services_3eeeea123e3 on services_3eeeea123e3 (id).
So do I have to create an index on each partition table now? Is there a way to create an index on the base table(services) itself, which will automatically create an index on each partition table?
Q2: When I run a select query, it is fast when I use the direct partition table; however, using the base table is very slow. Any idea what could be the reason.
Fast: SELECT id, dns_name, hash from services_3eeeea123e3 where id='123232'
very slow: SELECT id,dns_name, hash from services where mac_addr='3eeeea123e3' and id='123232'
I have a postgres table set up with a list partition defined on a column like so:
create table table1 (
val varchar(10),
t_type varchar(10)
) partition by list(t_type);
create table table1_xvals partition of table1 for values in ('xval1','xval2');
create table table1_yvals partition of table1 for values in ('yval1','yval2');
As I insert data into table1, and I can see the size of the table and individual partitions increasing, however when I try to select data from any of those tables, nothing shows up (select * from ). Is there anything wrong with how I'm creating the tables or selecting data?
That is normal. You are loading the data in a single database transaction, and the effects of a database transaction only become visible when the transaction is completed (committed). If you are loading the data with a single INSERT or COPY statement, the transaction will end as soon as the statement is done.
is it ok to rename a parent table from which partitioned child tables are based ?
For example if I have
CREATE TABLE demos_qa (
demo_id int,
demo_date VARCHAR,
demo_text TEXT)
PARTITION BY RANGE (trxn_post_dt);
CREATE TABLE demos_2022 PARTITION OF demos_qa
FOR VALUES FROM ('2022-01-01') TO ('2023-01-01');
CREATE TABLE demos_2021 PARTITION OF demos_qa
FOR VALUES FROM ('2021-01-01') TO ('2022-01-01');
CREATE TABLE demos_2020 PARTITION OF demos_qa
FOR VALUES FROM ('2020-01-01') TO ('2021-01-01');
and I bulk load the partition tables.
I now want to rename the parent table from demo_qa to demo. Can I do that and will things work as normal without having to change the definitions of the partition tables ?
Yes, this will work.
The partitions won't be renamed though, in case you expected that.
I have created a new master table with multiple partitions on basis of a column value using declarative partitioning of postgres 10.
How can i add new columns to the tables?
You only need to add that column to the base table:
alter table master_table add new_column integer;
All partitions will automatically get that new column.
I have a postgres table creating with the following SQL:
CREATE TABLE mytable (
mytable_id BIGSERIAL NOT NULL,
mytable_char VARCHAR(8) NOT NULL
)
This creates the table as well as an implicit mytable_mytable_id_seq sequence.
Now, after creating 1.000.000 records, I want to split this table into partitioned tables (using inheritance). Because I link refer to the main table from other tables, I want to keep using the IDs from the original table in the new child tables and keep using the sequence.
However, if I do DROP TABLE mytable it also deletes the sequence. How can I keep the sequence when dropping the table?
You need to first remove the association between the column and the sequence:
alter sequence mytable_mytable_id_seq owned by none;
If you now drop the table, the sequence will not be dropped.
Details are in the manual: http://www.postgresql.org/docs/current/static/sql-altersequence.html
An alternative is to create a new sequence and set that to the value of the existing sequence:
create sequence part_seq;
select setval('part_seq', (select nextval('mytable_mytable_id_seq'), false);