PostgreSQL   Partition
table 
 
 
 
This
is a simple tutorial for creating partitions on an existing table in PostgreSQL.
 
 
 
▋PostgreSQL 11
 
 
 
▋Create a
demo table
 
Lets create a table first. We will use [CreateOn]
as the the value for partitioning.
 
CREATE TABLE "OnlineTxs"
(
    "Id"       serial NOT NULL,
    "CardNo"   varchar(19) NOT NULL,
    "Amt"      decimal(10, 0) NOT NULL,
    "CreateOn" timestamp NOT NULL
) PARTITION BY RANGE ("CreateOn"); -- Add more columns for partitioning
 
▋ Create
Partitions
 
We will create the following partition tables with
different boundaries.
CREATE TABLE "OnlineTxs_20201126" PARTITION OF "OnlineTxs"
    FOR VALUES FROM ('2020-11-25') TO ('2020-11-26');
CREATE TABLE "OnlineTxs_20201127" PARTITION OF "OnlineTxs"
    FOR VALUES FROM ('2020-11-26') TO ('2020-11-27');
CREATE TABLE "OnlineTxs_20201128" PARTITION OF "OnlineTxs"
    FOR VALUES FROM ('2020-11-27') TO ('2020-11-28');
CREATE TABLE "OnlineTxs_20201129" PARTITION OF "OnlineTxs"
    FOR VALUES FROM ('2020-11-28') TO ('2020-11-29');
 CREATE TABLE "OnlineTxs_20201130" PARTITION OF "OnlineTxs"
    FOR VALUES FROM ('2020-11-29') TO ('2020-11-30');    
The records
will be stored in this way by the boundaries,
 
 
  | Partition table name |                     Range | 
 
  | OnlineTxs_20201126 | >= 2020-11-25 00:00:00 &
  < 2020-11-26 00:00:00 | 
 
  | OnlineTxs_20201127 | >= 2020-11-26 00:00:00 &
  < 2020-11-27 00:00:00 | 
 
  | OnlineTxs_20201128 | >= 2020-11-27 00:00:00 &
  < 2020-11-28 00:00:00 | 
 
  | OnlineTxs_20201129 | >= 2020-11-28 00:00:00 &
  < 2020-11-29 00:00:00 | 
 
  | OnlineTxs_20201130 | >= 2020-11-29 00:00:00 &
  < 2020-11-30 00:00:00 | 
 
 
Verify the partitions we just made by the
following SQL.
SELECT
    nmsp_parent.nspname AS parent_schema,
    parent.relname      AS parent,
    nmsp_child.nspname  AS child_schema,
    child.relname       AS child_name,
    pg_get_expr(child.relpartbound, child.oid, true) as partition_expression
FROM pg_inherits
    JOIN pg_class AS parent            ON pg_inherits.inhparent = parent.oid
    JOIN pg_class AS child             ON pg_inherits.inhrelid   = child.oid
    JOIN pg_namespace AS nmsp_parent   ON nmsp_parent.oid  = parent.relnamespace
    JOIN pg_namespace AS nmsp_child    ON nmsp_child.oid   = child.relnamespace
WHERE parent.relname='OnlineTxs'; 
▋ (Optional) Create the Primary key and Index
ALTER TABLE public."OnlineTxs" ADD PRIMARY KEY ("Id", "CreateOn");
CREATE INDEX IX_OnlineTxs_CreateOn ON public."OnlineTxs"
(
    "CreateOn" ASC
);
 
 
▋Test the partition table with data
 
We can use the following SQL to generate some data
into the table.
-- Get a random integer between low and high (low <= the random interger <= high)
CREATE OR REPLACE FUNCTION fn_random_int(low INT, high INT) 
   RETURNS INT AS
$$
BEGIN
   RETURN floor(random()* (high-low + 1) + low);
END;
$$ language 'plpgsql' STRICT;
-- Create mock data
do $loop$
declare r INT;
begin
for r in 1..1000 loop
    INSERT INTO public."OnlineTxs"("CardNo","Amt","CreateOn")
    SELECT
    '123456****789' AS "CardNo",
    fn_random_int(100,9999) AS "Amt",
    '2020-11-29'::timestamp + fn_random_int(0,4) * interval '-1' day as "CreateOn";
    -- NOW() + fn_random_int(0,4) * interval '-1' day as "CreateOn";
end loop;
end;
$loop$;
 
Verify the records by the following SQL,
-- First do VACUUM ANALYZE
VACUUM ANALYZE
-- Check count from "pg_stat_user_tabls"
SELECT schemaname, relname, n_live_tup as Cnt
FROM pg_stat_user_tables
WHERE relname LIKE '%OnlineTxs%'
ORDER BY relname;
-- Or check count from "pg_inherits"
SELECT
    nmsp_parent.nspname AS parent_schema,
    parent.relname      AS parent,
    nmsp_child.nspname  AS child_schema,
    child.relname       AS child_name,
    pg_get_expr(child.relpartbound, child.oid, true) as partition_expression,
    SUM(child.reltuples)    AS cnt
FROM pg_inherits
     JOIN pg_class AS parent            ON pg_inherits.inhparent = parent.oid
     JOIN pg_class AS child             ON pg_inherits.inhrelid   = child.oid
     JOIN pg_namespace AS nmsp_parent   ON nmsp_parent.oid  = parent.relnamespace
     JOIN pg_namespace AS nmsp_child    ON nmsp_child.oid   = child.relnamespace
WHERE parent.relname='OnlineTxs'
GROUP BY parent_schema, parent, child_schema, child_name, partition_expression
 
 
 
 
 
▋Move on more actions
 
▋Truncate a Partition
Truncating by Partition is much faster than doing
deletion. Here is how to truncate a Partition table.
TRUNCATE "OnlineTxs_20201126"; 
 
▋Remove a Partition and its data
DROP TABLE "OnlineTxs_20201126";
▋Detach a Partition as a table
ALTER TABLE public."OnlineTxs" DETACH PARTITION "OnlineTxs_20201127";
 
▋Attach a detachd partition table
ALTER TABLE "OnlineTxs" ATTACH PARTITION "OnlineTxs_20201126" 
FOR VALUES FROM ('2020-11-25') TO ('2020-11-26');
 
▌Reference
 
 
▋ Documentation: 10:
5.10. Table Partitioning - PostgreSQL
 
 
沒有留言:
張貼留言