pgslice 0.4.2 → 0.4.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +48 -22
- data/LICENSE.txt +1 -1
- data/README.md +99 -126
- data/exe/pgslice +4 -7
- data/lib/pgslice.rb +18 -740
- data/lib/pgslice/cli.rb +32 -0
- data/lib/pgslice/cli/add_partitions.rb +133 -0
- data/lib/pgslice/cli/analyze.rb +13 -0
- data/lib/pgslice/cli/fill.rb +103 -0
- data/lib/pgslice/cli/prep.rb +97 -0
- data/lib/pgslice/cli/swap.rb +28 -0
- data/lib/pgslice/cli/unprep.rb +18 -0
- data/lib/pgslice/cli/unswap.rb +25 -0
- data/lib/pgslice/helpers.rb +180 -0
- data/lib/pgslice/table.rb +199 -0
- data/lib/pgslice/version.rb +1 -1
- metadata +18 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 73d406b68757fa95efcc58a98249f9a8394cab3408a9ae14ef642983720f44b3
|
4
|
+
data.tar.gz: 7952c9aaa1734c76260b76a59822a4065e6184ac01bf3b1916bd217f7b368403
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 057aeaddcf952f2bb99f657f290e03f2ec3bac2deffce0d7701a7549418d7d8211b2454cbc71039226b369fc5b355d7ad426df0c4ce032d660e8ce09ebe15eab
|
7
|
+
data.tar.gz: a36f9db976f72cc656e289ff5af6ebb89657eb739fb6ca1bc4ccba652fdfa8b93894bc2e3fde5a9fdcd63d53a24574347a280af60157d124445a565810b9839c
|
data/CHANGELOG.md
CHANGED
@@ -1,106 +1,132 @@
|
|
1
|
-
## 0.4.
|
1
|
+
## 0.4.7 (2020-08-14)
|
2
|
+
|
3
|
+
- Added `--tablespace` option to `add_partitions`
|
4
|
+
- Fixed sequence query if sequence in different schema than table
|
5
|
+
|
6
|
+
## 0.4.6 (2020-05-29)
|
7
|
+
|
8
|
+
- Ensure correct order with multi-column primary keys
|
9
|
+
- Ensure fill always uses correct date range (bug introduced in 0.4.5)
|
10
|
+
|
11
|
+
## 0.4.5 (2018-10-18)
|
12
|
+
|
13
|
+
- Added support for Postgres 11 foreign key improvements
|
14
|
+
- Improved versioning
|
15
|
+
|
16
|
+
## 0.4.4 (2018-08-18)
|
17
|
+
|
18
|
+
- Added partitioning by `year`
|
19
|
+
- Fixed `--source-table` and `--dest-table` options
|
20
|
+
- Added descriptions to options
|
21
|
+
|
22
|
+
## 0.4.3 (2018-08-16)
|
23
|
+
|
24
|
+
- Fixed sequence ownership
|
25
|
+
- Improved help
|
26
|
+
|
27
|
+
## 0.4.2 (2018-07-23)
|
2
28
|
|
3
29
|
- Added support for Postgres 11 index improvements
|
4
30
|
- Added support for all connection options
|
5
31
|
|
6
|
-
## 0.4.1
|
32
|
+
## 0.4.1 (2018-04-30)
|
7
33
|
|
8
34
|
- Better support for schemas
|
9
35
|
- Use latest partition for schema
|
10
36
|
- Added support for composite primary keys
|
11
37
|
|
12
|
-
## 0.4.0
|
38
|
+
## 0.4.0 (2017-10-07)
|
13
39
|
|
14
40
|
- Added support for declarative partitioning
|
15
41
|
- Added support for foreign keys
|
16
42
|
|
17
|
-
## 0.3.6
|
43
|
+
## 0.3.6 (2017-07-10)
|
18
44
|
|
19
45
|
- Fixed drop trigger on `unprep` for non-lowercase tables
|
20
46
|
- Fixed index creation for non-lowercase tables
|
21
47
|
|
22
|
-
## 0.3.5
|
48
|
+
## 0.3.5 (2017-07-06)
|
23
49
|
|
24
50
|
- Added support for non-lowercase tables and columns
|
25
51
|
|
26
|
-
## 0.3.4
|
52
|
+
## 0.3.4 (2017-07-06)
|
27
53
|
|
28
54
|
- Added `analyze` method
|
29
55
|
- Fixed `fill` with `--dry-run` option
|
30
56
|
- Better error message for tables without primary key
|
31
57
|
|
32
|
-
## 0.3.3
|
58
|
+
## 0.3.3 (2017-03-22)
|
33
59
|
|
34
60
|
- Fixed error when creating partitions
|
35
61
|
|
36
|
-
## 0.3.2
|
62
|
+
## 0.3.2 (2016-12-15)
|
37
63
|
|
38
64
|
- Exit with error code on interrupt
|
39
65
|
- Fixed `--start` option with `--swapped`
|
40
66
|
|
41
|
-
## 0.3.1
|
67
|
+
## 0.3.1 (2016-12-13)
|
42
68
|
|
43
69
|
- Fixed exception with `--no-partition` option
|
44
70
|
- Use proper cast type in `fill` method for legacy `timestamptz` columns
|
45
71
|
|
46
|
-
## 0.3.0
|
72
|
+
## 0.3.0 (2016-12-12)
|
47
73
|
|
48
74
|
- Better query performance for `timestamptz` columns
|
49
75
|
- Added support for schemas other than `public`
|
50
76
|
|
51
|
-
## 0.2.3
|
77
|
+
## 0.2.3 (2016-10-10)
|
52
78
|
|
53
79
|
- Added `--dest-table` option to `fill`
|
54
80
|
- Fixed errors with `fill` when no partitions created
|
55
81
|
|
56
|
-
## 0.2.2
|
82
|
+
## 0.2.2 (2016-10-06)
|
57
83
|
|
58
84
|
- Set `lock_timeout` on `swap` to prevent bad things from happening
|
59
85
|
- Friendlier error messages
|
60
86
|
|
61
|
-
## 0.2.1
|
87
|
+
## 0.2.1 (2016-09-28)
|
62
88
|
|
63
89
|
- Added `--where` option to `fill`
|
64
90
|
- Fixed partition detection with `fill`
|
65
91
|
- Fixed error for columns named `user` with `fill`
|
66
92
|
|
67
|
-
## 0.2.0
|
93
|
+
## 0.2.0 (2016-09-22)
|
68
94
|
|
69
95
|
- Switched to new trigger, which is about 20% faster
|
70
96
|
|
71
|
-
## 0.1.7
|
97
|
+
## 0.1.7 (2016-09-14)
|
72
98
|
|
73
99
|
- Added `--source-table` option to `fill`
|
74
100
|
|
75
|
-
## 0.1.6
|
101
|
+
## 0.1.6 (2016-08-04)
|
76
102
|
|
77
103
|
- Added `--no-partition` option to `prep`
|
78
104
|
- Added `--url` option
|
79
105
|
|
80
|
-
## 0.1.5
|
106
|
+
## 0.1.5 (2016-04-26)
|
81
107
|
|
82
108
|
- Removed `activesupport` dependency for speed
|
83
109
|
- Fixed `fill` for months
|
84
110
|
|
85
|
-
## 0.1.4
|
111
|
+
## 0.1.4 (2016-04-24)
|
86
112
|
|
87
113
|
- Added sequence ownership
|
88
114
|
- Default to 0 for `--past` and `--future` options
|
89
115
|
- Better `fill` with `--swapped`
|
90
116
|
|
91
|
-
## 0.1.3
|
117
|
+
## 0.1.3 (2016-04-24)
|
92
118
|
|
93
119
|
- Fixed table inheritance
|
94
120
|
|
95
|
-
## 0.1.2
|
121
|
+
## 0.1.2 (2016-04-24)
|
96
122
|
|
97
123
|
- Added `--dry-run` option
|
98
124
|
- Print sql to stdout instead of stderr
|
99
125
|
|
100
|
-
## 0.1.1
|
126
|
+
## 0.1.1 (2016-04-24)
|
101
127
|
|
102
128
|
- Added sql commands to output
|
103
129
|
|
104
|
-
## 0.1.0
|
130
|
+
## 0.1.0 (2016-04-24)
|
105
131
|
|
106
132
|
- First release
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# pgslice
|
2
2
|
|
3
|
-
Postgres partitioning as easy as pie. Works great for both new and existing tables, with zero downtime and minimal app changes. Archive older data on a rolling basis to keep your database size under control.
|
3
|
+
Postgres partitioning as easy as pie. Works great for both new and existing tables, with zero downtime and minimal app changes. No need to install anything on your database server. Archive older data on a rolling basis to keep your database size under control.
|
4
4
|
|
5
5
|
:tangerine: Battle-tested at [Instacart](https://www.instacart.com/opensource)
|
6
6
|
|
@@ -14,7 +14,7 @@ pgslice is a command line tool. To install, run:
|
|
14
14
|
gem install pgslice
|
15
15
|
```
|
16
16
|
|
17
|
-
This will give you the `pgslice` command.
|
17
|
+
This will give you the `pgslice` command. If installation fails, you may need to install [dependencies](#dependencies).
|
18
18
|
|
19
19
|
## Steps
|
20
20
|
|
@@ -32,18 +32,16 @@ This will give you the `pgslice` command.
|
|
32
32
|
pgslice prep <table> <column> <period>
|
33
33
|
```
|
34
34
|
|
35
|
-
Period can be `day` or `
|
35
|
+
Period can be `day`, `month`, or `year`.
|
36
36
|
|
37
|
-
This creates a table named `<table>_intermediate
|
37
|
+
This creates a partitioned table named `<table>_intermediate`.
|
38
38
|
|
39
|
-
4. Add partitions
|
39
|
+
4. Add partitions to the intermediate table
|
40
40
|
|
41
41
|
```sh
|
42
42
|
pgslice add_partitions <table> --intermediate --past 3 --future 3
|
43
43
|
```
|
44
44
|
|
45
|
-
This creates child tables that inherit from the intermediate table.
|
46
|
-
|
47
45
|
Use the `--past` and `--future` options to control the number of partitions.
|
48
46
|
|
49
47
|
5. *Optional, for tables with data* - Fill the partitions in batches with data from the original table
|
@@ -80,7 +78,7 @@ This will give you the `pgslice` command.
|
|
80
78
|
|
81
79
|
```sql
|
82
80
|
pg_dump -c -Fc -t <table>_retired $PGSLICE_URL > <table>_retired.dump
|
83
|
-
psql -c "DROP <table>_retired" $PGSLICE_URL
|
81
|
+
psql -c "DROP TABLE <table>_retired" $PGSLICE_URL
|
84
82
|
```
|
85
83
|
|
86
84
|
## Sample Output
|
@@ -92,34 +90,13 @@ pgslice prep visits created_at month
|
|
92
90
|
```
|
93
91
|
|
94
92
|
```sql
|
95
|
-
-- Postgres 10
|
96
|
-
|
97
93
|
BEGIN;
|
98
94
|
|
99
|
-
CREATE TABLE visits_intermediate (LIKE visits INCLUDING DEFAULTS INCLUDING CONSTRAINTS INCLUDING STORAGE INCLUDING COMMENTS) PARTITION BY RANGE (created_at);
|
100
|
-
|
101
|
-
COMMENT ON TABLE visits_intermediate is 'column:created_at,period:day';
|
102
|
-
|
103
|
-
COMMIT;
|
104
|
-
|
105
|
-
-- Postgres 9.6 and below
|
106
|
-
|
107
|
-
BEGIN;
|
95
|
+
CREATE TABLE "public"."visits_intermediate" (LIKE "public"."visits" INCLUDING DEFAULTS INCLUDING CONSTRAINTS INCLUDING STORAGE INCLUDING COMMENTS) PARTITION BY RANGE ("created_at");
|
108
96
|
|
109
|
-
CREATE
|
97
|
+
CREATE INDEX ON "public"."visits_intermediate" USING btree ("created_at");
|
110
98
|
|
111
|
-
|
112
|
-
RETURNS trigger AS $$
|
113
|
-
BEGIN
|
114
|
-
RAISE EXCEPTION 'Create partitions first.';
|
115
|
-
END;
|
116
|
-
$$ LANGUAGE plpgsql;
|
117
|
-
|
118
|
-
CREATE TRIGGER visits_insert_trigger
|
119
|
-
BEFORE INSERT ON visits_intermediate
|
120
|
-
FOR EACH ROW EXECUTE PROCEDURE visits_insert_trigger();
|
121
|
-
|
122
|
-
COMMENT ON TRIGGER visits_insert_trigger ON visits_intermediate is 'column:created_at,period:month';
|
99
|
+
COMMENT ON TABLE "public"."visits_intermediate" is 'column:createdAt,period:day,cast:date,version:3';
|
123
100
|
|
124
101
|
COMMIT;
|
125
102
|
```
|
@@ -129,73 +106,19 @@ pgslice add_partitions visits --intermediate --past 1 --future 1
|
|
129
106
|
```
|
130
107
|
|
131
108
|
```sql
|
132
|
-
-- Postgres 10
|
133
|
-
|
134
109
|
BEGIN;
|
135
110
|
|
136
|
-
CREATE TABLE
|
137
|
-
|
138
|
-
ALTER TABLE visits_201608 ADD PRIMARY KEY (id);
|
111
|
+
CREATE TABLE "public"."visits_201808" PARTITION OF "public"."visits_intermediate" FOR VALUES FROM ('2018-08-01') TO ('2018-09-01');
|
139
112
|
|
140
|
-
|
113
|
+
ALTER TABLE "public"."visits_201808" ADD PRIMARY KEY ("id");
|
141
114
|
|
142
|
-
CREATE TABLE
|
115
|
+
CREATE TABLE "public"."visits_201809" PARTITION OF "public"."visits_intermediate" FOR VALUES FROM ('2018-09-01') TO ('2018-10-01');
|
143
116
|
|
144
|
-
ALTER TABLE
|
117
|
+
ALTER TABLE "public"."visits_201809" ADD PRIMARY KEY ("id");
|
145
118
|
|
146
|
-
CREATE
|
119
|
+
CREATE TABLE "public"."visits_201810" PARTITION OF "public"."visits_intermediate" FOR VALUES FROM ('2018-10-01') TO ('2018-11-01');
|
147
120
|
|
148
|
-
|
149
|
-
|
150
|
-
ALTER TABLE visits_201610 ADD PRIMARY KEY (id);
|
151
|
-
|
152
|
-
CREATE INDEX ON visits_201610 USING btree (user_id);
|
153
|
-
|
154
|
-
COMMIT;
|
155
|
-
|
156
|
-
-- Postgres 9.6 and below
|
157
|
-
|
158
|
-
BEGIN;
|
159
|
-
|
160
|
-
CREATE TABLE visits_201608
|
161
|
-
(CHECK (created_at >= '2016-08-01'::date AND created_at < '2016-09-01'::date))
|
162
|
-
INHERITS (visits_intermediate);
|
163
|
-
|
164
|
-
ALTER TABLE visits_201608 ADD PRIMARY KEY (id);
|
165
|
-
|
166
|
-
CREATE INDEX ON visits_201608 USING btree (user_id);
|
167
|
-
|
168
|
-
CREATE TABLE visits_201609
|
169
|
-
(CHECK (created_at >= '2016-09-01'::date AND created_at < '2016-10-01'::date))
|
170
|
-
INHERITS (visits_intermediate);
|
171
|
-
|
172
|
-
ALTER TABLE visits_201609 ADD PRIMARY KEY (id);
|
173
|
-
|
174
|
-
CREATE INDEX ON visits_201609 USING btree (user_id);
|
175
|
-
|
176
|
-
CREATE TABLE visits_201610
|
177
|
-
(CHECK (created_at >= '2016-10-01'::date AND created_at < '2016-11-01'::date))
|
178
|
-
INHERITS (visits_intermediate);
|
179
|
-
|
180
|
-
ALTER TABLE visits_201610 ADD PRIMARY KEY (id);
|
181
|
-
|
182
|
-
CREATE INDEX ON visits_201610 USING btree (user_id);
|
183
|
-
|
184
|
-
CREATE OR REPLACE FUNCTION visits_insert_trigger()
|
185
|
-
RETURNS trigger AS $$
|
186
|
-
BEGIN
|
187
|
-
IF (NEW.created_at >= '2016-09-01'::date AND NEW.created_at < '2016-10-01'::date) THEN
|
188
|
-
INSERT INTO visits_201609 VALUES (NEW.*);
|
189
|
-
ELSIF (NEW.created_at >= '2016-10-01'::date AND NEW.created_at < '2016-11-01'::date) THEN
|
190
|
-
INSERT INTO visits_201610 VALUES (NEW.*);
|
191
|
-
ELSIF (NEW.created_at >= '2016-08-01'::date AND NEW.created_at < '2016-09-01'::date) THEN
|
192
|
-
INSERT INTO visits_201608 VALUES (NEW.*);
|
193
|
-
ELSE
|
194
|
-
RAISE EXCEPTION 'Date out of range. Ensure partitions are created.';
|
195
|
-
END IF;
|
196
|
-
RETURN NULL;
|
197
|
-
END;
|
198
|
-
$$ LANGUAGE plpgsql;
|
121
|
+
ALTER TABLE "public"."visits_201808" ADD PRIMARY KEY ("id");
|
199
122
|
|
200
123
|
COMMIT;
|
201
124
|
```
|
@@ -206,19 +129,19 @@ pgslice fill visits
|
|
206
129
|
|
207
130
|
```sql
|
208
131
|
/* 1 of 3 */
|
209
|
-
INSERT INTO visits_intermediate ("id", "user_id", "ip", "created_at")
|
210
|
-
SELECT "id", "user_id", "ip", "created_at" FROM visits
|
211
|
-
WHERE id > 0 AND id <= 10000 AND created_at >= '
|
132
|
+
INSERT INTO "public"."visits_intermediate" ("id", "user_id", "ip", "created_at")
|
133
|
+
SELECT "id", "user_id", "ip", "created_at" FROM "public"."visits"
|
134
|
+
WHERE "id" > 0 AND "id" <= 10000 AND "created_at" >= '2018-08-01'::date AND "created_at" < '2018-11-01'::date
|
212
135
|
|
213
136
|
/* 2 of 3 */
|
214
|
-
INSERT INTO visits_intermediate ("id", "user_id", "ip", "created_at")
|
215
|
-
SELECT "id", "user_id", "ip", "created_at" FROM visits
|
216
|
-
WHERE id > 10000 AND id <= 20000 AND created_at >= '
|
137
|
+
INSERT INTO "public"."visits_intermediate" ("id", "user_id", "ip", "created_at")
|
138
|
+
SELECT "id", "user_id", "ip", "created_at" FROM "public"."visits"
|
139
|
+
WHERE "id" > 10000 AND "id" <= 20000 AND "created_at" >= '2018-08-01'::date AND "created_at" < '2018-11-01'::date
|
217
140
|
|
218
141
|
/* 3 of 3 */
|
219
|
-
INSERT INTO visits_intermediate ("id", "user_id", "ip", "created_at")
|
220
|
-
SELECT "id", "user_id", "ip", "created_at" FROM visits
|
221
|
-
WHERE id > 20000 AND id <= 30000 AND created_at >= '
|
142
|
+
INSERT INTO "public"."visits_intermediate" ("id", "user_id", "ip", "created_at")
|
143
|
+
SELECT "id", "user_id", "ip", "created_at" FROM "public"."visits"
|
144
|
+
WHERE "id" > 20000 AND "id" <= 30000 AND "created_at" >= '2018-08-01'::date AND "created_at" < '2018-11-01'::date
|
222
145
|
```
|
223
146
|
|
224
147
|
```sh
|
@@ -226,13 +149,13 @@ pgslice analyze visits
|
|
226
149
|
```
|
227
150
|
|
228
151
|
```sql
|
229
|
-
ANALYZE VERBOSE
|
152
|
+
ANALYZE VERBOSE "public"."visits_201808";
|
230
153
|
|
231
|
-
ANALYZE VERBOSE
|
154
|
+
ANALYZE VERBOSE "public"."visits_201809";
|
232
155
|
|
233
|
-
ANALYZE VERBOSE
|
156
|
+
ANALYZE VERBOSE "public"."visits_201810";
|
234
157
|
|
235
|
-
ANALYZE VERBOSE visits_intermediate;
|
158
|
+
ANALYZE VERBOSE "public"."visits_intermediate";
|
236
159
|
```
|
237
160
|
|
238
161
|
```sh
|
@@ -244,11 +167,11 @@ BEGIN;
|
|
244
167
|
|
245
168
|
SET LOCAL lock_timeout = '5s';
|
246
169
|
|
247
|
-
ALTER TABLE visits RENAME TO visits_retired;
|
170
|
+
ALTER TABLE "public"."visits" RENAME TO "visits_retired";
|
248
171
|
|
249
|
-
ALTER TABLE visits_intermediate RENAME TO visits;
|
172
|
+
ALTER TABLE "public"."visits_intermediate" RENAME TO "visits";
|
250
173
|
|
251
|
-
ALTER SEQUENCE visits_id_seq OWNED BY visits.id;
|
174
|
+
ALTER SEQUENCE "public"."visits_id_seq" OWNED BY "public"."visits"."id";
|
252
175
|
|
253
176
|
COMMIT;
|
254
177
|
```
|
@@ -261,7 +184,7 @@ To add partitions, use:
|
|
261
184
|
pgslice add_partitions <table> --future 3
|
262
185
|
```
|
263
186
|
|
264
|
-
Add this as a cron job to create a new partition each day or
|
187
|
+
Add this as a cron job to create a new partition each day, month, or year.
|
265
188
|
|
266
189
|
```sh
|
267
190
|
# day
|
@@ -269,6 +192,9 @@ Add this as a cron job to create a new partition each day or month.
|
|
269
192
|
|
270
193
|
# month
|
271
194
|
0 0 1 * * pgslice add_partitions <table> --future 3 --url ...
|
195
|
+
|
196
|
+
# year
|
197
|
+
0 0 1 1 * pgslice add_partitions <table> --future 3 --url ...
|
272
198
|
```
|
273
199
|
|
274
200
|
Add a monitor to ensure partitions are being created.
|
@@ -283,21 +209,22 @@ WHERE
|
|
283
209
|
n.nspname = 'public' AND
|
284
210
|
c.relname = '<table>_' || to_char(NOW() + INTERVAL '3 days', 'YYYYMMDD')
|
285
211
|
-- for months, use to_char(NOW() + INTERVAL '3 months', 'YYYYMM')
|
212
|
+
-- for years, use to_char(NOW() + INTERVAL '3 years', 'YYYY')
|
286
213
|
```
|
287
214
|
|
288
215
|
## Archiving Partitions
|
289
216
|
|
290
|
-
Back up and drop older partitions each day or
|
217
|
+
Back up and drop older partitions each day, month, or year.
|
291
218
|
|
292
219
|
```sh
|
293
|
-
pg_dump -c -Fc -t <table>
|
294
|
-
psql -c "DROP <table>
|
220
|
+
pg_dump -c -Fc -t <table>_201809 $PGSLICE_URL > <table>_201809.dump
|
221
|
+
psql -c "DROP TABLE <table>_201809" $PGSLICE_URL
|
295
222
|
```
|
296
223
|
|
297
224
|
If you use [Amazon S3](https://aws.amazon.com/s3/) for backups, [s3cmd](https://github.com/s3tools/s3cmd) is a nice tool.
|
298
225
|
|
299
226
|
```sh
|
300
|
-
s3cmd put <table>
|
227
|
+
s3cmd put <table>_201809.dump s3://<s3-bucket>/<table>_201809.dump
|
301
228
|
```
|
302
229
|
|
303
230
|
## Additional Commands
|
@@ -318,16 +245,9 @@ pgslice unswap <table>
|
|
318
245
|
|
319
246
|
This set up allows you to read and write with the original table name with no knowledge it’s partitioned. However, there are a few things to be aware of.
|
320
247
|
|
321
|
-
### Writes
|
322
|
-
|
323
|
-
Before Postgres 10, if you use `INSERT` statements with a `RETURNING` clause (as frameworks like Rails do), you’ll no longer receive the id of the newly inserted record(s) back. If you need this, you can either:
|
324
|
-
|
325
|
-
1. Insert directly into the partition
|
326
|
-
2. Get value before the insert with `SELECT nextval('sequence_name')` (for multiple rows, append `FROM generate_series(1, n)`)
|
327
|
-
|
328
248
|
### Reads
|
329
249
|
|
330
|
-
When possible, queries should include the column you partition on to limit the number of partitions the database needs to check.
|
250
|
+
When possible, queries should include the column you partition on to limit the number of partitions the database needs to check. For instance, if you partition on `created_at`, try to include it in queries:
|
331
251
|
|
332
252
|
```sql
|
333
253
|
SELECT * FROM
|
@@ -335,7 +255,7 @@ SELECT * FROM
|
|
335
255
|
WHERE
|
336
256
|
user_id = 123 AND
|
337
257
|
-- for performance
|
338
|
-
created_at >= '
|
258
|
+
created_at >= '2018-09-01' AND created_at < '2018-09-02'
|
339
259
|
```
|
340
260
|
|
341
261
|
For this to be effective, ensure `constraint_exclusion` is set to `partition` (default value) or `on`.
|
@@ -344,6 +264,33 @@ For this to be effective, ensure `constraint_exclusion` is set to `partition` (d
|
|
344
264
|
SHOW constraint_exclusion;
|
345
265
|
```
|
346
266
|
|
267
|
+
### Writes
|
268
|
+
|
269
|
+
Before Postgres 10, if you use `INSERT` statements with a `RETURNING` clause (as frameworks like Rails do), you’ll no longer receive the id of the newly inserted record(s) back. If you need this, you can either:
|
270
|
+
|
271
|
+
1. Insert directly into the partition
|
272
|
+
2. Get value before the insert with `SELECT nextval('sequence_name')` (for multiple rows, append `FROM generate_series(1, n)`)
|
273
|
+
|
274
|
+
## Rails
|
275
|
+
|
276
|
+
For Postgres 10+, specify the primary key for partitioned models to ensure it’s returned.
|
277
|
+
|
278
|
+
```ruby
|
279
|
+
class Visit < ApplicationRecord
|
280
|
+
self.primary_key = "id"
|
281
|
+
end
|
282
|
+
```
|
283
|
+
|
284
|
+
Before Postgres 10, preload the value.
|
285
|
+
|
286
|
+
```ruby
|
287
|
+
class Visit < ApplicationRecord
|
288
|
+
before_create do
|
289
|
+
self.id ||= self.class.connection.select_all("SELECT nextval('#{self.class.sequence_name}')").first["nextval"]
|
290
|
+
end
|
291
|
+
end
|
292
|
+
```
|
293
|
+
|
347
294
|
## One Off Tasks
|
348
295
|
|
349
296
|
You can also use pgslice to reduce the size of a table without partitioning by creating a new table, filling it with a subset of records, and swapping it in.
|
@@ -358,13 +305,38 @@ pgslice swap <table>
|
|
358
305
|
|
359
306
|
Once a table is partitioned, here’s how to change the schema:
|
360
307
|
|
361
|
-
|
362
|
-
|
308
|
+
To add, remove, or modify a column, make the update on the master table only.
|
309
|
+
|
310
|
+
To add or remove an index or foreign key:
|
311
|
+
|
312
|
+
- For Postgres 11+, make the update on the master table only.
|
313
|
+
- For Postgres 10, make the update on partitions only.
|
314
|
+
- For Postgres < 10, make the update on the master table and all partitions.
|
363
315
|
|
364
316
|
## Declarative Partitioning
|
365
317
|
|
366
318
|
Postgres 10 introduces [declarative partitioning](https://www.postgresql.org/docs/10/static/ddl-partitioning.html#ddl-partitioning-declarative). A major benefit is `INSERT` statements with a `RETURNING` clause work as expected. If you prefer to use trigger-based partitioning instead (not recommended), pass the `--trigger-based` option to the `prep` command.
|
367
319
|
|
320
|
+
## Data Protection
|
321
|
+
|
322
|
+
Always make sure your [connection is secure](https://ankane.org/postgres-sslmode-explained) when connecting to a database over a network you don’t fully trust. Your best option is to connect over SSH or a VPN. Another option is to use `sslmode=verify-full`. If you don’t do this, your database credentials can be compromised.
|
323
|
+
|
324
|
+
## Dependencies
|
325
|
+
|
326
|
+
If installation fails, your system may be missing Ruby or libpq.
|
327
|
+
|
328
|
+
On Mac, run:
|
329
|
+
|
330
|
+
```sh
|
331
|
+
brew install postgresql
|
332
|
+
```
|
333
|
+
|
334
|
+
On Ubuntu, run:
|
335
|
+
|
336
|
+
```sh
|
337
|
+
sudo apt-get install ruby-dev libpq-dev build-essential
|
338
|
+
```
|
339
|
+
|
368
340
|
## Upgrading
|
369
341
|
|
370
342
|
Run:
|
@@ -398,6 +370,7 @@ This will give you the `pgslice` command.
|
|
398
370
|
|
399
371
|
Also check out:
|
400
372
|
|
373
|
+
- [Dexter](https://github.com/ankane/dexter) - The automatic indexer for Postgres
|
401
374
|
- [PgHero](https://github.com/ankane/pghero) - A performance dashboard for Postgres
|
402
375
|
- [pgsync](https://github.com/ankane/pgsync) - Sync Postgres data to your local machine
|
403
376
|
|
@@ -410,14 +383,14 @@ Everyone is encouraged to help improve this project. Here are a few ways you can
|
|
410
383
|
- Write, clarify, or fix documentation
|
411
384
|
- Suggest or add new features
|
412
385
|
|
413
|
-
To
|
386
|
+
To get started with development:
|
414
387
|
|
415
388
|
```sh
|
416
389
|
git clone https://github.com/ankane/pgslice.git
|
417
390
|
cd pgslice
|
418
391
|
bundle install
|
419
392
|
createdb pgslice_test
|
420
|
-
bundle exec rake
|
393
|
+
bundle exec rake test
|
421
394
|
```
|
422
395
|
|
423
396
|
To test against different versions of Postgres with Docker, use:
|