It is a multi part blog series of partitioning an existing table.
This is part 1 below is the scenario...
Scenario: A simple table without any referential constraint dependency or indexes. Let us move the data from this simple independent nonpartitioned table to other simple partitioned table.
Table Setup:
Command: create table
test_nonpart_nofk_noidx as with t as ( select
generate_series(0,100) lvl ) select t.lvl ,(mod(t.lvl,100)+date
'1/1/2022') as dob ,lpad('A',(mod(t.lvl,20)+(20-mod(t.lvl,20))),chr(65+mod((t.lvl/26),26)))
as hosptl ,substr(md5(random()::text),15)
as fn ,substr(md5(random()::text),15)
as ln ,'UKCO'||chr(65+mod(t.lvl,26))||chr(65+mod((t.lvl/26),26))
as POSCODE from t;
Command output: postgres=#
create table test_nonpart_nofk_noidx as postgres-#
with t as postgres-# ( postgres(#
select generate_series(0,100) lvl postgres(# ) postgres-#
select t.lvl postgres-#
,(mod(t.lvl,100)+date '1/1/2022') as dob postgres-#
,lpad('A',(mod(t.lvl,20)+(20-mod(t.lvl,20))),chr(65+mod((t.lvl/26),26))) as
hosptl postgres-#
,substr(md5(random()::text),15) as fn postgres-#
,substr(md5(random()::text),15) as ln postgres-#
,'UKCO'||chr(65+mod(t.lvl,26))||chr(65+mod((t.lvl/26),26)) as POSCODE postgres-#
from t; SELECT 101 Time: 28.733
ms postgres=# |
B) Identifying the partition key & partitioning scheme:
1. We have to be sure the partition key chosen has business benefits or interests (like data archiving, data selection or partition pruning)
2. Technically a feasible column for the partition scheme of our choice
3. A right partitioning scheme
Look at the data below..
postgres=# select count(distinct(dob)) from test_nonpart_nofk_noidx; count ------- 100 (1 row)
Time: 3.090
ms postgres=#
select count(distinct(hosptl)) from test_nonpart_nofk_noidx; count ------- 4 (1 row)
Time: 0.338
ms postgres=#
select count(distinct(POSCODE)) from test_nonpart_nofk_noidx; count ------- 101 (1 row)
Time: 0.951
ms postgres=#
select count(1) from test_nonpart_nofk_noidx; count ------- 101 (1 row)
Time: 0.399
ms
|
Pg_dump command: /usr/pgsql-14/bin/pg_dump
--table='public.test_nonpart_nofk_noidx' --username=postgres
--dbname=postgres --schema-only --file=/tmp/test_nonpart_nofk_noidx_ddl.sql
--verbose
--table :
filters the table we need this operation performed --username,
--dbname : are username to connect to the designated dbname --schema-only
: dump only the table skeleton which is DDL --file : Dump
the content to file --verbose :
throw pg_dump messages
Output snippet: pg_dump: last
built-in OID is 16383 pg_dump:
reading extensions pg_dump:
identifying extension members pg_dump:
reading schemas .. pg_dump:
saving search_path = pg_dump:
creating TABLE "public.test_nonpart_nofk_noidx"
Output file snippet: -- -- TOC entry
213 (class 1259 OID 16444) -- Name:
test_nonpart_nofk_noidx; Type: TABLE; Schema: public; Owner: postgres --
CREATE TABLE
public.test_nonpart_nofk_noidx ( lvl integer, dob date, hosptl text, fn text, ln text, poscode text );
ALTER TABLE
public.test_nonpart_nofk_noidx OWNER TO postgres;
-- Completed
on 2023-04-03 19:06:14 BST |
Command: CREATE TABLE
public.test_part_nofk_noidx ( lvl integer, dob date, hosptl text, fn text, ln text, poscode text ) partition
by list(hosptl); CREATE TABLE
public.test_part_nofk_noidx_a partition of public.test_part_nofk_noidx for
values in ('AAAAAAAAAAAAAAAAAAAA'); CREATE TABLE
public.test_part_nofk_noidx_b partition of public.test_part_nofk_noidx for
values in ('BBBBBBBBBBBBBBBBBBBA'); CREATE TABLE
public.test_part_nofk_noidx_c partition of public.test_part_nofk_noidx for
values in ('CCCCCCCCCCCCCCCCCCCA'); CREATE TABLE
public.test_part_nofk_noidx_d partition of public.test_part_nofk_noidx for
values in ('DDDDDDDDDDDDDDDDDDDA'); CREATE TABLE
public.test_part_nofk_noidx_default partition of public.test_part_nofk_noidx
default; Command output: postgres=#
CREATE TABLE public.test_part_nofk_noidx ( postgres(# lvl integer, postgres(# dob date, postgres(# hosptl text, postgres(# fn text, postgres(# ln text, postgres(# poscode text postgres(# )
partition by list(hosptl); CREATE TABLE Time: 6.651
ms postgres=#
CREATE TABLE public.test_part_nofk_noidx_a partition of
public.test_part_nofk_noidx for values in ('AAAAAAAAAAAAAAAAAAAA'); CREATE TABLE Time: 6.445
ms postgres=#
CREATE TABLE public.test_part_nofk_noidx_b partition of
public.test_part_nofk_noidx for values in ('BBBBBBBBBBBBBBBBBBBA'); CREATE TABLE Time: 8.316
ms postgres=#
CREATE TABLE public.test_part_nofk_noidx_c partition of
public.test_part_nofk_noidx for values in ('CCCCCCCCCCCCCCCCCCCA'); CREATE TABLE Time: 6.457
ms postgres=#
CREATE TABLE public.test_part_nofk_noidx_d partition of
public.test_part_nofk_noidx for values in ('DDDDDDDDDDDDDDDDDDDA'); CREATE TABLE Time: 8.252
ms postgres=#
CREATE TABLE public.test_part_nofk_noidx_default partition of
public.test_part_nofk_noidx default; CREATE TABLE Time: 6.275
ms postgres=# |
Verify: postgres=#
\d+ public.test_part_nofk_noidx Partitioned
table "public.test_part_nofk_noidx" Column
| Type | Collation | Nullable | Default |
Storage | Compression | Stats target |
Description ---------+---------+-----------+----------+---------+----------+-------------+--------------+------------- lvl
| integer | |
| | plain | | | dob
| date | | | | plain | | | hosptl
| text | | | | extended | | | fn
| text | | | | extended | | | ln
| text | | | | extended | | | poscode | text | | | | extended | | | Partition
key: LIST (hosptl) Partitions:
test_part_nofk_noidx_a FOR VALUES IN ('AAAAAAAAAAAAAAAAAAAA'), test_part_nofk_noidx_b FOR VALUES
IN ('BBBBBBBBBBBBBBBBBBBA'), test_part_nofk_noidx_c FOR VALUES
IN ('CCCCCCCCCCCCCCCCCCCA'), test_part_nofk_noidx_d FOR VALUES
IN ('DDDDDDDDDDDDDDDDDDDA'), test_part_nofk_noidx_default
DEFAULT
postgres=# |
postgres=#
select relname,relpersistence from pg_class where relname like 'test%' order
by 1; relname | relpersistence ------------------------------+---------------- test_nonpart_nofk_noidx | p test_part_nofk_noidx | p test_part_nofk_noidx_a | p test_part_nofk_noidx_b | p test_part_nofk_noidx_c | p test_part_nofk_noidx_d | p test_part_nofk_noidx_default | p test_shrbuf | p test_shrbuf_idx_lvl | p (9 rows) Time: 0.580
ms postgres=# postgres=#
alter table test_part_nofk_noidx_a set unlogged; ALTER TABLE Time: 12.750
ms postgres=#
alter table test_part_nofk_noidx_b set unlogged; ALTER TABLE Time: 17.305
ms postgres=#
alter table test_part_nofk_noidx_c set unlogged; ALTER TABLE Time: 20.743
ms postgres=#
alter table test_part_nofk_noidx_d set unlogged; ALTER TABLE Time: 17.444
ms postgres=#
alter table test_part_nofk_noidx_default set unlogged; ALTER TABLE Time: 15.323
ms postgres=#
select relname,relpersistence from pg_class where relname like 'test%' order
by 1; relname | relpersistence ------------------------------+---------------- test_nonpart_nofk_noidx | p test_part_nofk_noidx | p test_part_nofk_noidx_a | u test_part_nofk_noidx_b | u test_part_nofk_noidx_c | u test_part_nofk_noidx_d | u test_part_nofk_noidx_default | u test_shrbuf | p test_shrbuf_idx_lvl | p (9 rows) Time: 0.787
ms postgres=# |
insert into
test_part_nofk_noidx select * from
test_nonpart_nofk_noidx; -- commit; --
auto commit postgres=#
insert into test_part_nofk_noidx postgres-#
select * from test_nonpart_nofk_noidx; INSERT 0 101 Time: 1.461
ms postgres=# select * from
pg_stat_user_tables; relid | schemaname | relname | seq_scan | seq_tup_read |
idx_scan | idx_tup_fetch | n_tup_ins | n_tup_upd | n_tup_del | n_tup_hot_upd
| n_live_tup | n_dead_tup | n_mod_since_analyze | n_ins_since_vacuum |
last_vacuum | last_autovacuum | last_analyze | last_autoanalyze | vacuum_count | autovacuum_count |
analyze_count | autoanalyze_count -------+------------+------------------------------+----------+--------------+----------+---------------+-----------+-----------+-----------+---------------+------------+------------+---------------------+--------------------+-------------+-------------------------------+--------------+-------------------------------+--------------+------------------+---------------+------------------- 16475 | public | test_part_nofk_noidx_default | 1 | 0 | | | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | | | | 0 | 0 | 0 | 0 16455 | public | test_part_nofk_noidx_a | 3 | 0 | | | 26 | 0 | 0 | 0 | 26 | 0 | 26 | 26 | | | | | 0 | 0 | 0 | 0 16411 | public | test_shrbuf | 59 | 20000020 | 2 | 1 | 1000001 | 0 |
0 | 0 | 1000001 | 0 | 0 | 0 | | 2023-04-01 20:41:25.488159+01
| | 2023-04-01
20:41:26.594851+01 | 0
| 1 | 0 | 1 16470 | public | test_part_nofk_noidx_d | 1 | 0 | | | 23 | 0 | 0 | 0 | 23 | 0 | 23 | 23 | | | | | 0 | 0 | 0 | 0 16460 | public | test_part_nofk_noidx_b | 1 | 0 | | | 26 | 0 | 0 | 0 | 26 | 0 | 26 | 26 | | | | | 0 | 0 | 0 | 0 16452 | public | test_part_nofk_noidx | 0 | 0 | | |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | | | | 0 | 0 | 0 | 0 16465 | public | test_part_nofk_noidx_c | 1 | 0 | | | 26 | 0 | 0 | 0 | 26 | 0 | 26 | 26 | | | | | 0 | 0 | 0 | 0 16444 | public | test_nonpart_nofk_noidx |
11 | 1111 | |
| 101 | 0 | 0 | 0 | 101 | 0 | 0 | 101 | | | | 2023-04-03 17:58:46.003797+01
| 0 | 0 | 0 | 1 (8 rows) Time: 12.779
ms SELECT
t.oid::regclass AS partition ,t.relname ,t.relpages ,t.reltuples ,t.relallvisible ,t.relpersistence ,t.relkind ,t.relispartition ,t.reloptions ,pg_get_expr(t.relpartbound,
t.oid) AS bounds FROM
pg_inherits AS i JOIN pg_class AS t ON t.oid = i.inhrelid WHERE
i.inhparent = 'test_part_nofk_noidx'::regclass; partition | relname | relpages | reltuples | relallvisible
| relpersistence | relkind | relispartition | reloptions | bounds ------------------------------+------------------------------+----------+-----------+---------------+----------------+---------+----------------+------------+---------------------------------------- test_part_nofk_noidx_a | test_part_nofk_noidx_a | 0 | -1 | 0 | u | r | t | | FOR VALUES IN
('AAAAAAAAAAAAAAAAAAAA') test_part_nofk_noidx_b | test_part_nofk_noidx_b | 0 | -1 | 0 | u | r | t | | FOR VALUES IN ('BBBBBBBBBBBBBBBBBBBA') test_part_nofk_noidx_c | test_part_nofk_noidx_c | 0 | -1 | 0 | u | r | t | | FOR VALUES IN
('CCCCCCCCCCCCCCCCCCCA') test_part_nofk_noidx_d | test_part_nofk_noidx_d | 0 | -1 | 0 | u | r | t | | FOR VALUES IN
('DDDDDDDDDDDDDDDDDDDA') test_part_nofk_noidx_default |
test_part_nofk_noidx_default | 0
| -1 | 0 | u | r | t | | DEFAULT (5 rows) Time: 0.999
ms postgres=# analyze
verbose table test_part_nofk_noidx; postgres=#
analyze verbose test_part_nofk_noidx; INFO: analyzing
"public.test_part_nofk_noidx" inheritance tree INFO: "test_part_nofk_noidx_a": scanned
1 of 1 pages, containing 26 live rows and 0 dead rows; 26 rows in sample, 26
estimated total rows INFO: "test_part_nofk_noidx_b": scanned
1 of 1 pages, containing 26 live rows and 0 dead rows; 26 rows in sample, 26
estimated total rows INFO: "test_part_nofk_noidx_c": scanned
1 of 1 pages, containing 26 live rows and 0 dead rows; 26 rows in sample, 26
estimated total rows INFO: "test_part_nofk_noidx_d": scanned
1 of 1 pages, containing 23 live rows and 0 dead rows; 23 rows in sample, 23
estimated total rows INFO: analyzing
"public.test_part_nofk_noidx_a" INFO: "test_part_nofk_noidx_a": scanned
1 of 1 pages, containing 26 live rows and 0 dead rows; 26 rows in sample, 26
estimated total rows INFO: analyzing
"public.test_part_nofk_noidx_b" INFO: "test_part_nofk_noidx_b": scanned
1 of 1 pages, containing 26 live rows and 0 dead rows; 26 rows in sample, 26
estimated total rows INFO: analyzing
"public.test_part_nofk_noidx_c" INFO: "test_part_nofk_noidx_c": scanned
1 of 1 pages, containing 26 live rows and 0 dead rows; 26 rows in sample, 26
estimated total rows INFO: analyzing
"public.test_part_nofk_noidx_d" INFO: "test_part_nofk_noidx_d": scanned
1 of 1 pages, containing 23 live rows and 0 dead rows; 23 rows in sample, 23
estimated total rows INFO: analyzing
"public.test_part_nofk_noidx_default" INFO: "test_part_nofk_noidx_default":
scanned 0 of 0 pages, containing 0 live rows and 0 dead rows; 0 rows in
sample, 0 estimated total rows ANALYZE Time: 14.814
ms postgres=# partition | relname | relpages | reltuples |
relallvisible | relpersistence | relkind | relispartition | reloptions | bounds ------------------------------+------------------------------+----------+-----------+---------------+----------------+---------+----------------+------------+---------------------------------------- test_part_nofk_noidx_a | test_part_nofk_noidx_a | 1 | 26 | 0 | u | r | t | | FOR VALUES IN
('AAAAAAAAAAAAAAAAAAAA') test_part_nofk_noidx_b | test_part_nofk_noidx_b | 1 | 26 | 0 | u | r | t | | FOR VALUES IN
('BBBBBBBBBBBBBBBBBBBA') test_part_nofk_noidx_c | test_part_nofk_noidx_c | 1 | 26 | 0 | u | r | t | | FOR VALUES IN
('CCCCCCCCCCCCCCCCCCCA') test_part_nofk_noidx_d | test_part_nofk_noidx_d | 1 | 23 |
0 | u | r | t | | FOR VALUES IN
('DDDDDDDDDDDDDDDDDDDA') test_part_nofk_noidx_default |
test_part_nofk_noidx_default | 0
| 0 | 0 | u | r | t | | DEFAULT (5 rows) Time: 0.817
ms postgres=# |
alter table
test_nonpart_nofk_noidx rename to test_nonpart_nofk_noidx_old;
postgres=# \d List of relations Schema | Name | Type |
Owner --------+------------------------------+-------------------+---------- .. public | test_nonpart_nofk_noidx_old | table | postgres public | test_part_nofk_noidx | partitioned table | postgres |
alter table
test_part_nofk_noidx rename to test_nonpart_nofk_noidx; List of relations Schema | Name | Type |
Owner --------+------------------------------+-------------------+---------- .. public | test_nonpart_nofk_noidx | partitioned table | postgres public | test_nonpart_nofk_noidx_old | table | postgres |
alter table
test_part_nofk_noidx_a rename to test_nonpart_nofk_noidx_a; alter table
test_part_nofk_noidx_b rename to test_nonpart_nofk_noidx_b; alter table
test_part_nofk_noidx_c rename to test_nonpart_nofk_noidx_c; alter table
test_part_nofk_noidx_d rename to test_nonpart_nofk_noidx_d; alter table
test_part_nofk_noidx_default rename to test_nonpart_nofk_noidx_default;
postgres=# \d List of relations Schema | Name | Type |
Owner --------+---------------------------------+-------------------+---------- .. public | test_nonpart_nofk_noidx | partitioned table | postgres public | test_nonpart_nofk_noidx_a | table | postgres public | test_nonpart_nofk_noidx_b | table | postgres public | test_nonpart_nofk_noidx_c | table | postgres public | test_nonpart_nofk_noidx_d | table | postgres public | test_nonpart_nofk_noidx_default |
table | postgres public | test_nonpart_nofk_noidx_old | table | postgres |
postgres=#
explain analyze select * from test_nonpart_nofk_noidx where
hosptl='AAAAAAAAAAAAAAAAAAAA';
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------------- Seq Scan on test_nonpart_nofk_noidx_a
test_nonpart_nofk_noidx
(cost=0.00..1.32 rows=26 width=74) (actual time=0.008..0.017 rows=26
loops=1) Filter: (hosptl =
'AAAAAAAAAAAAAAAAAAAA'::text) Planning Time: 0.213 ms Execution Time: 0.033 ms (4 rows) Time: 0.659
ms postgres=# |
postgres=#
select relname,seq_scan,seq_tup_read,idx_scan,idx_tup_fetch from
pg_stat_user_tables where relname like 'test_nonpart%' order by relname; relname | seq_scan | seq_tup_read |
idx_scan | idx_tup_fetch ---------------------------------+----------+--------------+----------+--------------- test_nonpart_nofk_noidx | 0 | 0 | | test_nonpart_nofk_noidx_a | 4 | 26 | | <<<< we scanned this
partition, rest partitions are showing no tuples read. test_nonpart_nofk_noidx_b | 1 | 0 | | test_nonpart_nofk_noidx_c | 1 | 0 | | test_nonpart_nofk_noidx_d | 1 | 0 | | test_nonpart_nofk_noidx_default | 1 | 0 | | test_nonpart_nofk_noidx_old |
11 | 1111 | | (7 rows) Time: 12.038
ms postgres=# |
No comments:
Post a Comment