You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: doc/fix_missing_procedures.md
+5-5Lines changed: 5 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -13,26 +13,26 @@ The best way to fix this and ensure all PROCEDUREs have been installed is to dro
13
13
## Update Steps
14
14
15
15
1. Perform a pg_dump of the data from the pg_partman configuration tables. Note that the contents of this dump will only contain the data and not the table definitions. The definitions are part of the CREATE EXTENSION step. This is just doing a plaintext dump to make it easier to review the contents if desired. Note the following command assumes pg_partman was installed in the `partman` schema.
If your trigger-based partition set happens to be managed by pg_partman version prior to 5.0.0, it is best to remove it from partman management. This can be done by deleting it from the `part_config` and `part_config_sub` tables (if sub-partitioned, ensure all child tables are removed as well). After it has been migrated to native partitioning, see the Migrating to pg_partman document mentioned above to return it to being managed by partman.
@@ -49,7 +49,7 @@ Next, we need to create a new parent table using native partitioning since you c
49
49
50
50
Please see the `Child Table Property Inheritance` section of `docs/pg_partman.md` for which properties can be set on the native parent and which must be managed via the template .
@@ -58,7 +58,7 @@ CREATE INDEX ON partman_test.time_taptest_table_native (col3);
58
58
```
59
59
60
60
Next check what the ownership and privileges on your original table were and ensure they exist on the new parent table. This will ensure all access to the table works the same after the migration. By default with native partitioning, privileges are no longer granted on child tables to provide direct access to them. If you'd like to keep that behavior, set the `inherit_privileges` column in `part_config` (and part_config_sub if needed) to true.
61
-
```
61
+
```sql
62
62
\dt partman_test.time_taptest_table
63
63
List of relations
64
64
Schema | Name | Type | Owner
@@ -75,14 +75,14 @@ Next check what the ownership and privileges on your original table were and ens
75
75
| | | testing=r/partman_owner | |
76
76
(1 row)
77
77
```
78
-
```
78
+
```sql
79
79
ALTERTABLEpartman_test.time_taptest_table_native OWNER TO partman_owner;
80
80
GRANTSELECT, INSERT, UPDATE, DELETEONpartman_test.time_taptest_table_native TO partman_basic;
81
81
GRANTSELECTONpartman_test.time_taptest_table_native TO testing;
82
82
```
83
83
84
84
It is best to halt all activity on the original table during the migration process to avoid any issues. This can be done by either revoking all permissions to the table temporarily or by taking out an exclusive lock on the parent table and running all of these steps in a single transaction. The transactional method is highly recommended for the simple fact that if you run into any issues before you've completed the migration process, you can simply rollback and return to the state your database was in before the migration started.
@@ -92,7 +92,7 @@ The first major step in this migration process is now to uninherit all the child
92
92
93
93
DO NOT RUN THE RESULTING STATEMENTS YET. A future query will not work if the child tables are no longer part of the inheritance set.
94
94
95
-
```
95
+
```sql
96
96
SELECT format('ALTER TABLE %s NO INHERIT %s;', inhrelid::regclass, inhparent::regclass)
97
97
FROM pg_inherits
98
98
WHERE inhparent::regclass ='partman_test.time_taptest_table'::regclass;
@@ -123,7 +123,7 @@ For any partition sets, even those not managed by pg_partman, the next step is t
123
123
If your child table names do not have a usable pattern like this, you'll have to figure out some method of determining each child table's boundaries.
124
124
125
125
Again, we can use some sql to generate statements to re-attach the children to the new parent:
126
-
```
126
+
```sql
127
127
WITH child_tables AS (
128
128
SELECT
129
129
inhrelid::regclass::textAS child_tablename_safe
@@ -161,7 +161,7 @@ FROM child_tables x;
161
161
162
162
```
163
163
We can now run these two sets of ALTER TABLE statements to first uninherit them from the old trigger-based parent and attach them to the new native parent. After doing so, the old trigger-based parent should have no longer have children:
164
-
```
164
+
```sql
165
165
\d+partman_test.time_taptest_table
166
166
167
167
Table "partman_test.time_taptest_table"
@@ -177,7 +177,7 @@ Triggers:
177
177
Access method: heap
178
178
```
179
179
And our new native parent should have now adopted all its new children:
@@ -206,20 +206,20 @@ Partitions: partman_test.time_taptest_table_p2023_03_26 FOR VALUES FROM ('2023-0
206
206
207
207
```
208
208
Next is to swap the names of your old trigger-based parent and the new native parent.
209
-
```
209
+
```sql
210
210
ALTERTABLEpartman_test.time_taptest_table RENAME TO time_taptest_table_old;
211
211
ALTERTABLEpartman_test.time_taptest_table_native RENAME TO time_taptest_table;
212
212
```
213
213
PG11+ supports the feature of a default partition to catch any data that doesn't have a matching child. If your table names are particularly long, ensure that adding the `_default` suffix doesn't get truncated unexpectedly. The suffix isn't required for functionality, but provides good context for what the table is for, so it's better to shorten the table name itself to fit the suffix.
214
-
```
214
+
```sql
215
215
CREATETABLEpartman_test.time_taptest_table_default (LIKEpartman_test.time_taptest_table INCLUDING ALL);
There was a primary key on the original parent table, but that is not possible with native partitioning unless the primary key also includes the partition key. This is typically not practical in time-based partitioning. You can place a primary key on each individual child table, but that only enforces the constraint for that child table, not across the entire partition set. You can add a primary key to each individual table using similar SQL generation above, but if you'd like a method to manage adding these to any new child tables, please see the features available in pg_partman.
220
220
221
221
If you've run this process inside a transaction, be sure to commit your work now:
222
-
```
222
+
```sql
223
223
COMMIT;
224
224
```
225
225
This should complete the migration process. If you'd like to migrate your partition set to be managed by pg_partman, please see the `migrate_to_partman.md` documentation file.
Copy file name to clipboardExpand all lines: doc/migrate_to_partman.md
+13-13Lines changed: 13 additions & 13 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,7 +7,7 @@ As always, if you can first test this migration on a development system, it is h
7
7
8
8
The following are the example tables we will be using:
9
9
10
-
```
10
+
```sql
11
11
CREATETABLEtracking.hits_time (id int GENERATED BY DEFAULT AS IDENTITY NOT NULL, start timestamptz DEFAULT now() NOT NULL) PARTITION BY RANGE (start);
12
12
CREATEINDEXONtracking.hits_time (start);
13
13
CREATETABLEtracking.hits_time2023_02_26 partition of tracking.hits_time FOR VALUESFROM ('2023-02-26'::timestamptz) TO ('2023-03-05'::timestamptz);
@@ -32,7 +32,7 @@ Partitions: tracking.hits_time20230226 FOR VALUES FROM ('2023-02-26 00:00:00-05'
32
32
tracking.hits_time20230312 FOR VALUESFROM ('2023-03-12 00:00:00-05') TO ('2023-03-19 00:00:00-04')
33
33
34
34
```
35
-
```
35
+
```sql
36
36
CREATETABLEtracking.hits_id (id int GENERATED BY DEFAULT AS IDENTITY NOT NULL, start timestamptz DEFAULT now() NOT NULL) PARTITION BY RANGE (id);
37
37
CREATEINDEXONtracking.hits_id (id);
38
38
CREATETABLEtracking.hits_id1000 partition of tracking.hits_id FOR VALUESFROM (1000) TO (2000);
@@ -56,7 +56,7 @@ Partitions: tracking.hits_id1000 FOR VALUES FROM (1000) TO (2000),
56
56
tracking.hits_id2000 FOR VALUESFROM (2000) TO (3000),
57
57
tracking.hits_id3000 FOR VALUESFROM (3000) TO (4000)
58
58
```
59
-
```
59
+
```sql
60
60
CREATETABLEtracking.hits_stufftime (id int GENERATED BY DEFAULT AS IDENTITY NOT NULL, start timestamptz DEFAULT now() NOT NULL) PARTITION BY RANGE (start);
61
61
CREATEINDEXONtracking.hits_stufftime (start);
62
62
CREATETABLEtracking.hits_stufftimeaa partition of tracking.hits_stufftime FOR VALUESFROM ('2023-01-01'::timestamptz) TO ('2023-01-08'::timestamptz);
@@ -80,7 +80,7 @@ Partitions: tracking.hits_stufftimeaa FOR VALUES FROM ('2023-01-01 00:00:00-05')
80
80
tracking.hits_stufftimebb FOR VALUESFROM ('2023-01-08 00:00:00-05') TO ('2023-01-15 00:00:00-05'),
81
81
tracking.hits_stufftimecc FOR VALUESFROM ('2023-01-15 00:00:00-05') TO ('2023-01-22 00:00:00-05')
82
82
```
83
-
```
83
+
```sql
84
84
CREATETABLEtracking.hits_stuffid (id int GENERATED BY DEFAULT AS IDENTITY NOT NULL, start timestamptz DEFAULT now() NOT NULL) PARTITION BY RANGE (id);
85
85
CREATEINDEXONtracking.hits_stuffid (id);
86
86
CREATETABLEtracking.hits_stuffidaa partition of tracking.hits_stuffid FOR VALUESFROM (1000) TO (2000);
@@ -130,7 +130,7 @@ For converting either time or serial based partition sets, if you have the lower
130
130
131
131
So a query like the following which first extracts the original name then reformats the suffix would work. It doesn't actually do the renaming, it just generates all the ALTER TABLE statements for you for all the child tables in the set. If all of them don't quite have the same pattern for some reason, you can easily just re-run this, editing things as needed, and filter the resulting list of ALTER TABLE statements accordingly. Note the `to_timestamp()` function is given the old datetime string pattern and the `to_char()` function is given the new string pattern.
132
132
133
-
```
133
+
```sql
134
134
SELECT format(
135
135
'ALTER TABLE %I.%I RENAME TO %I;'
136
136
, n.nspname
@@ -162,7 +162,7 @@ Running that should rename your tables to look like this now:
162
162
163
163
If you're migrating a serial/id based partition set, and also have the naming convention with the lowest possible value, you'd do something very similar. Everything would be the same as the time-series one above except the renaming would be slightly different. Using my second example table above, it would be something like this.
164
164
165
-
```
165
+
```sql
166
166
SELECT format(
167
167
'ALTER TABLE %I.%I RENAME TO %I;'
168
168
, n.nspname
@@ -196,7 +196,7 @@ If your partitioned sets are named in a manner that relates differently to the d
196
196
We'll be using the the `hits_stufftime` table in the first example here which has child tables that don't relate at all to the data contained.
197
197
198
198
This next step takes advantage of anonymous code blocks. It's basically writing pl/pgsql function code without creating an actual function. Just run this block of code, adjusting values as needed, right inside a psql session. Note that in PostgreSQL, weeks start on Monday's by default for the date_trunc function. However, say we wanted them to start on Sundays like they did for our other time partitioning example to keep things consistent. In that case we have to do a little extra date math to get that result.
199
-
```
199
+
```sql
200
200
DO $rename$
201
201
DECLARE
202
202
v_min_val timestamp;
@@ -237,21 +237,21 @@ END
237
237
$rename$;
238
238
```
239
239
This will output something like this:
240
-
```
240
+
```sql
241
241
NOTICE: ALTER TABLE tracking.hits_stufftimeaa RENAME TO hits_stufftime_p20230101
242
242
NOTICE: ALTER TABLE tracking.hits_stufftimebb RENAME TO hits_stufftime_p20230108
243
243
NOTICE: ALTER TABLE tracking.hits_stufftimecc RENAME TO hits_stufftime_p20230115
244
244
```
245
245
I'd recommend running it at least once with the final EXECUTE commented out to review what it generates. If it looks good, you can uncomment the EXECUTE and rename your tables!
246
246
247
247
If you've got a serial/id partition set, calculating the proper suffix value can be done by taking advantage of modulus arithmetic. Assume the following values in the tracking.hits_stuffid table:
We'll be partitioning by 1000 again and you can see none of the minimum values are that even.
254
-
```
254
+
```sql
255
255
DO $rename$
256
256
DECLARE
257
257
v_min_val bigint;
@@ -290,7 +290,7 @@ END
290
290
$rename$;
291
291
```
292
292
You can see this makes nice even partition names:
293
-
```
293
+
```sql
294
294
NOTICE: ALTER TABLE tracking.hits_stuffidaa RENAME TO hits_stuffid_p1000
295
295
NOTICE: ALTER TABLE tracking.hits_stuffidbb RENAME TO hits_stuffid_p2000
296
296
NOTICE: ALTER TABLE tracking.hits_stuffidcc RENAME TO hits_stuffid_p3000
@@ -306,13 +306,13 @@ Note that we're doing weekly partitioning, but pg_partman only knows that interv
306
306
307
307
You may or may not need to set the starting partition parameter. It all depends on the interval you are using, so please test things to see if they work as expected before running on production.
This single function call will add your old partition set into pg_partman's configuration and possibly create some new child tables as well. pg_partman always keeps a minimum number of future partitions premade (based on the *premake* value in the config table or as a parameter to the create_parent() function), so if you don't have those yet, this step will take care of that as well. Adjust the parameters as needed and see the documentation for additional options that are available. This call matches the time partition used in the example so far.
0 commit comments