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
@@ -80,18 +80,130 @@ This will generate a migration that creates the partitioned table with a default
80
80
Do not use the standard ``python manage.py makemigrations`` command for partitioned models. Django will issue a standard :class:`~django:django.db.migrations.operations.CreateModel` operation. Doing this will not create a partitioned table and all subsequent operations will fail.
81
81
82
82
83
-
Adding/removing partitions manually
84
-
-----------------------------------
83
+
Automatically managing partitions
84
+
---------------------------------
85
85
86
-
Postgres does not have support for automatically creating new partitions as needed. Therefore, one must manually add new partitions. Depending on the partitioning method you have chosen, the partition has to be created differently.
86
+
The ``python manage.py pgpartition`` command can help you automatically create new partitions ahead of time and delete old ones for time-based partitioning.
87
87
88
-
Partitions are tables. Each partition must be given a unique name. :class:`~psqlextra.models.PostgresPartitionedModel` does not require you to create a model for each partition because you are not supposed to query partitions directly.
88
+
You can run this command manually as needed, schedule to run it periodically or run it every time you release a new version of your app.
89
89
90
+
.. warning::
91
+
92
+
We DO NOT recommend that you set up this command to automatically delete partitions without manual review.
93
+
94
+
Specify ``--skip-delete`` to not delete partitions automatically. Run the command manually periodically without the ``--yes`` flag to review partitions to be deleted.
In order to use the command, you have to declare an instance of :class:`psqlextra.partitioning.PostgresPartitioningManager` and set ``PSQLEXTRA_PARTITIONING_MANAGER`` to a string with the import path to your instance of :class:`psqlextra.partitioning.PostgresPartitioningManager`.
115
+
116
+
For example:
117
+
118
+
.. code-block:: python
119
+
120
+
# myapp/partitioning.py
121
+
from psqlextra.partitioning import PostgresPartitioningManager
# partitions will be named `[table_name]_[year]_[3-letter month name]`.
147
+
PostgresPartitioningConfig(
148
+
model=MyPartitionedModel,
149
+
strategy=PostgresCurrentTimePartitioningStrategy(
150
+
size=PostgresTimePartitionSize(months=1),
151
+
count=3,
152
+
max_age=relativedelta(months=6),
153
+
),
154
+
),
155
+
# 6 partitions ahead, each partition is two weeks
156
+
# delete partitions older than 8 months
157
+
# partitions will be named `[table_name]_[year]_week_[week number]`.
158
+
PostgresPartitioningConfig(
159
+
model=MyPartitionedModel,
160
+
strategy=PostgresCurrentTimePartitioningStrategy(
161
+
size=PostgresTimePartitionSize(weeks=2),
162
+
count=6,
163
+
max_age=relativedelta(months=8),
164
+
),
165
+
),
166
+
# 12 partitions ahead, each partition is 5 days
167
+
# old partitions are never deleted, `max_age` is not set
168
+
# partitions will be named `[table_name]_[year]_[month]_[month day number]`.
169
+
PostgresPartitioningConfig(
170
+
model=MyPartitionedModel,
171
+
strategy=PostgresCurrentTimePartitioningStrategy(
172
+
size=PostgresTimePartitionSize(wdyas=5),
173
+
count=12,
174
+
),
175
+
),
176
+
])
177
+
178
+
179
+
Changing a time partitioning strategy
180
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
181
+
182
+
When switching partitioning strategies, you might encounter the problem that partitions for part of a particular range already exist.
183
+
184
+
In order to combat this, you can use the :class:`psqlextra.partitioning.PostgresTimePartitioningStrategy` and specify the `start_datetime` parameter. As a result, no partitions will be created before the given date/time.
185
+
186
+
187
+
Custom strategy
188
+
~~~~~~~~~~~~~~~
189
+
190
+
You can create a custom partitioning strategy by implementing the :class:`psqlextra.partitioning.PostgresPartitioningStrategy` interface.
191
+
192
+
You can look at :class:`psqlextra.partitioning.PostgresCurrentTimePartitioningStrategy` as an example.
193
+
194
+
195
+
Manually managing partitions
196
+
----------------------------
197
+
198
+
If you are using list or has partitioning, you most likely have a fixed amount of partitions that can be created up front using migrations or using the schema editor.
199
+
200
+
Using migration operations
201
+
**************************
90
202
91
203
Adding a range partition
92
204
~~~~~~~~~~~~~~~~~~~~~~~~
93
205
94
-
Use the :class:`~psqlextra.backend.migrations.operations.PostgresAddRangePartition` operation to add a new range partition. Only use this operation when your partitioned model uses the :attr:`psqlextra.types.PostgresPartitioningMethod.RANGE`.
206
+
Use the :class:`~psqlextra.backend.migrations.operations.PostgresAddRangePartition` operation to add a new range partition. Only use this operation when your partitioned model uses :attr:`psqlextra.types.PostgresPartitioningMethod.RANGE`.
95
207
96
208
.. code-block:: python
97
209
@@ -113,7 +225,7 @@ Use the :class:`~psqlextra.backend.migrations.operations.PostgresAddRangePartiti
113
225
Adding a list partition
114
226
~~~~~~~~~~~~~~~~~~~~~~~
115
227
116
-
Use the :class:`~psqlextra.backend.migrations.operations.PostgresAddListPartition` operation to add a new list partition. Only use this operation when your partitioned model uses the :attr:`psqlextra.types.PostgresPartitioningMethod.LIST`.
228
+
Use the :class:`~psqlextra.backend.migrations.operations.PostgresAddListPartition` operation to add a new list partition. Only use this operation when your partitioned model uses :attr:`psqlextra.types.PostgresPartitioningMethod.LIST`.
117
229
118
230
.. code-block:: python
119
231
@@ -131,12 +243,36 @@ Use the :class:`~psqlextra.backend.migrations.operations.PostgresAddListPartitio
131
243
]
132
244
133
245
246
+
Adding a hash partition
247
+
~~~~~~~~~~~~~~~~~~~~~~~
248
+
249
+
Use the :class:`~psqlextra.backend.migrations.operations.PostgresAddHashPartition` operation to add a new list partition. Only use this operation when your partitioned model uses :attr:`psqlextra.types.PostgresPartitioningMethod.HASH`.
250
+
251
+
.. code-block:: python
252
+
253
+
from django.db import migrations, models
254
+
255
+
from psqlextra.backend.migrations.operations import PostgresAddHashPartition
256
+
257
+
classMigration(migrations.Migration):
258
+
operations = [
259
+
PostgresAddHashPartition(
260
+
model_name="mypartitionedmodel",
261
+
name="pt1",
262
+
modulus=3,
263
+
remainder=1,
264
+
),
265
+
]
266
+
267
+
134
268
Adding a default partition
135
269
~~~~~~~~~~~~~~~~~~~~~~~~~~
136
270
137
-
Use the :class:`~psqlextra.backend.migrations.operations.PostgresAddDefaultPartition` operation to add a new default partition. A default partition is the partition where records get saved that couldn't fit in any other partition.
271
+
Use the :class:`~psqlextra.backend.migrations.operations.PostgresAddDefaultPartition` operation to add a new list partition.
272
+
273
+
Note that you can only have one default partition per partitioned table/model. An error will be thrown if you try to create a second default partition.
138
274
139
-
Note that you can only have one default partition per partitioned table/model.
275
+
If you used ``python manage.py pgmakemigrations`` to generate a migration for your newly created partitioned model, you do not need this operation. This operation is added automatically when you create a new partitioned model.
140
276
141
277
.. code-block:: python
142
278
@@ -158,6 +294,12 @@ Deleting a default partition
158
294
159
295
Use the :class:`~psqlextra.backend.migrations.operations.PostgresDeleteDefaultPartition` operation to delete an existing default partition.
160
296
297
+
298
+
.. warning::
299
+
300
+
Deleting the default partition and leaving your model without a default partition can be dangerous. Rows that do not fit in any other partition will fail to be inserted.
301
+
302
+
161
303
.. code-block:: python
162
304
163
305
from django.db import migrations, models
@@ -176,7 +318,7 @@ Use the :class:`~psqlextra.backend.migrations.operations.PostgresDeleteDefaultPa
176
318
Deleting a range partition
177
319
~~~~~~~~~~~~~~~~~~~~~~~~~~
178
320
179
-
Use the :class:`psqlextra.backend.migrations.operations.PostgresDeleteRangePartition` operation to delete an existing range partition.
321
+
Use the :class:`psqlextra.backend.migrations.operations.PostgresDeleteRangePartition` operation to delete an existing range partition. Only use this operation when your partitioned model uses :attr:`psqlextra.types.PostgresPartitioningMethod.RANGE`.
180
322
181
323
.. code-block:: python
182
324
@@ -196,7 +338,7 @@ Use the :class:`psqlextra.backend.migrations.operations.PostgresDeleteRangeParti
196
338
Deleting a list partition
197
339
~~~~~~~~~~~~~~~~~~~~~~~~~
198
340
199
-
Use the :class:`~psqlextra.backend.migrations.operations.PostgresDeleteListPartition` operation to delete an existing list partition.
341
+
Use the :class:`psqlextra.backend.migrations.operations.PostgresDeleteListPartition` operation to delete an existing range partition. Only use this operation when your partitioned model uses :attr:`psqlextra.types.PostgresPartitioningMethod.LIST`.
200
342
201
343
.. code-block:: python
202
344
@@ -213,6 +355,26 @@ Use the :class:`~psqlextra.backend.migrations.operations.PostgresDeleteListParti
213
355
]
214
356
215
357
358
+
Deleting a hash partition
359
+
~~~~~~~~~~~~~~~~~~~~~~~~~
360
+
361
+
Use the :class:`psqlextra.backend.migrations.operations.PostgresDeleteHashPartition` operation to delete an existing range partition. Only use this operation when your partitioned model uses :attr:`psqlextra.types.PostgresPartitioningMethod.HASH`.
362
+
363
+
.. code-block:: python
364
+
365
+
from django.db import migrations, models
366
+
367
+
from psqlextra.backend.migrations.operations import PostgresDeleteHashPartition
368
+
369
+
classMigration(migrations.Migration):
370
+
operations = [
371
+
PostgresDeleteHashPartition(
372
+
model_name="mypartitionedmodel",
373
+
name="pt1",
374
+
),
375
+
]
376
+
377
+
216
378
Using the schema editor
217
379
***********************
218
380
@@ -248,120 +410,42 @@ Adding a list partition
248
410
)
249
411
250
412
251
-
Adding a default partition
252
-
~~~~~~~~~~~~~~~~~~~~~~~~~~
413
+
Adding a hash partition
414
+
~~~~~~~~~~~~~~~~~~~~~~~
253
415
254
416
.. code-block:: python
255
417
256
418
from django.db import connection
257
419
258
-
connection.schema_editor().add_default_partition(
420
+
connection.schema_editor().add_hash_partition(
259
421
model=MyPartitionedModel,
260
-
name="default",
422
+
name="pt1",
423
+
modulus=3,
424
+
remainder=1,
261
425
)
262
426
263
427
264
-
Deleting a partition
265
-
~~~~~~~~~~~~~~~~~~~~
428
+
Adding a default partition
429
+
~~~~~~~~~~~~~~~~~~~~~~~~~~
266
430
267
431
.. code-block:: python
268
432
269
433
from django.db import connection
270
434
271
-
connection.schema_editor().delete_partition(
435
+
connection.schema_editor().add_default_partition(
272
436
model=MyPartitionedModel,
273
437
name="default",
274
438
)
275
439
276
440
277
-
Adding/removing partitions automatically
278
-
----------------------------------------
279
-
280
-
:class:`psqlextra.partitioning.PostgresPartitioningManager` an experimental helper class that can be called periodically to automatically create new partitions if you're using range partitioning.
281
-
282
-
.. note::
283
-
284
-
There is currently no scheduler or command to automatically create new partitions. You'll have to run this function in your own cron jobs.
285
-
286
-
The auto partitioner supports automatically creating yearly, monthly, weekly or daily partitions. Use the ``count`` parameter to configure how many partitions it should create ahead.
287
-
288
-
289
-
Partitioning strategies
290
-
***********************
291
-
292
-
293
-
Time-based partitioning
294
-
~~~~~~~~~~~~~~~~~~~~~~~
441
+
Deleting a partition
442
+
~~~~~~~~~~~~~~~~~~~~
295
443
296
444
.. code-block:: python
297
445
298
-
from dateutil.relativedelta import relativedelta
299
-
300
-
from psqlextra.partitioning import (
301
-
PostgresPartitioningManager,
302
-
PostgresCurrentTimePartitioningStrategy,
303
-
PostgresTimePartitionSize,
304
-
partition_by_current_time,
305
-
)
306
-
307
-
manager = PostgresPartitioningManager([
308
-
# 3 partitions ahead, each partition is one month
309
-
# delete partitions older than 6 months
310
-
# partitions will be named `[table_name]_[year]_[3-letter month name]`.
311
-
PostgresPartitioningConfig(
312
-
model=MyPartitionedModel,
313
-
strategy=PostgresCurrentTimePartitioningStrategy(
314
-
size=PostgresTimePartitionSize(months=1),
315
-
count=3,
316
-
max_age=relativedelta(months=6),
317
-
),
318
-
),
319
-
# 6 partitions ahead, each partition is two weeks
320
-
# delete partitions older than 8 months
321
-
# partitions will be named `[table_name]_[year]_week_[week number]`.
322
-
PostgresPartitioningConfig(
323
-
model=MyPartitionedModel,
324
-
strategy=PostgresCurrentTimePartitioningStrategy(
325
-
size=PostgresTimePartitionSize(weeks=2),
326
-
count=6,
327
-
max_age=relativedelta(months=8),
328
-
),
329
-
),
330
-
# 12 partitions ahead, each partition is 5 days
331
-
# old partitions are never deleted, `max_age` is not set
332
-
# partitions will be named `[table_name]_[year]_[month]_[month day number]`.
333
-
PostgresPartitioningConfig(
334
-
model=MyPartitionedModel,
335
-
strategy=PostgresCurrentTimePartitioningStrategy(
336
-
size=PostgresTimePartitionSize(wdyas=5),
337
-
count=12,
338
-
),
339
-
),
340
-
])
446
+
from django.db import connection
341
447
342
-
# these are the default arguments
343
-
partioning_plan = manager.plan(
344
-
skip_create=False,
345
-
skip_delete=False,
346
-
using='default'
448
+
connection.schema_editor().delete_partition(
449
+
model=MyPartitionedModel,
450
+
name="default",
347
451
)
348
-
349
-
# prints a list of partitions to be created/deleted
350
-
partitioning_plan.print()
351
-
352
-
# apply the plan
353
-
partitioning_plan.apply(using='default');
354
-
355
-
356
-
Custom strategy
357
-
~~~~~~~~~~~~~~~
358
-
359
-
You can create a custom partitioning strategy by implementing the :class:`psqlextra.partitioning.PostgresPartitioningStrategy` interface.
360
-
361
-
You can look at :class:`psqlextra.partitioning.PostgresCurrentTimePartitioningStrategy` as an example.
362
-
363
-
364
-
Switching partitioning strategies
365
-
*********************************
366
-
367
-
When switching partitioning strategies, you might encounter the problem that partitions for part of a particular range already exist. In order to combat this, you can use the :class:`psqlextra.partitioning.PostgresTimePartitioningStrategy` and specify the `start_datetime` parameter. As a result, no partitions will be created before the given date/time.
0 commit comments