# pgslice
Postgres partitioning as easy as pie
## Install
Run:
```sh
gem install pgslice
```
## Steps
1. Specify your database credentials
```sh
export PGSLICE_URL=postgres://localhost/myapp_development
```
2. Create an intermediate table
```sh
pgslice prep
```
Period can be `day` or `month`.
This creates a table named `_intermediate` with the appropriate trigger for partitioning.
3. Add partitions
```sh
pgslice add_partitions --intermediate --past 3 --future 3
```
This creates child tables that inherit from the intermediate table.
Use the `--past` and `--future` options to control the number of partitions.
4. *Optional, for tables with data* - Fill the partitions in batches with data from the original table
```sh
pgslice fill
```
Use the `--batch-size` and `--sleep` options to control the speed.
5. Swap the intermediate table with the original table
```sh
pgslice swap
```
The original table is renamed `_retired` and the intermediate table is renamed ``.
6. Fill the rest
```sh
pgslice fill --swapped
```
7. Archive and drop the original table
## Adding Partitions
To add partitions, use:
```sh
pgslice add_partitions --future 3
```
## Additional Commands
To undo prep (which will delete partitions), use:
```sh
pgslice unprep
```
To undo swap, use:
```sh
pgslice unswap
```
## Sample Output
`pgslice` prints the SQL commands that were executed on the server. To print without executing, use the `--dry-run` option.
```console
$ pgslice prep locations created_at day
BEGIN;
CREATE TABLE locations_intermediate (
LIKE locations INCLUDING ALL
);
CREATE FUNCTION locations_insert_trigger()
RETURNS trigger AS $$
BEGIN
EXECUTE 'INSERT INTO public.locations_' || to_char(NEW.created_at, 'YYYYMMDD') || ' VALUES ($1.*)' USING NEW;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER locations_insert_trigger
BEFORE INSERT ON locations_intermediate
FOR EACH ROW EXECUTE PROCEDURE locations_insert_trigger();
COMMIT;
```
```console
$ pgslice add_partitions locations --intermediate --past 1 --future 1
BEGIN;
CREATE TABLE locations_20160423 (
CHECK (created_at >= '2016-04-23'::date AND created_at < '2016-04-24'::date)
) INHERITS (locations_intermediate);
ALTER TABLE locations_20160423 ADD PRIMARY KEY (id);
CREATE INDEX ON locations_20160423 USING btree (updated_at, shopper_id);
CREATE TABLE locations_20160424 (
CHECK (created_at >= '2016-04-24'::date AND created_at < '2016-04-25'::date)
) INHERITS (locations_intermediate);
ALTER TABLE locations_20160424 ADD PRIMARY KEY (id);
CREATE INDEX ON locations_20160424 USING btree (updated_at, shopper_id);
CREATE TABLE locations_20160425 (
CHECK (created_at >= '2016-04-25'::date AND created_at < '2016-04-26'::date)
) INHERITS (locations_intermediate);
ALTER TABLE locations_20160425 ADD PRIMARY KEY (id);
CREATE INDEX ON locations_20160425 USING btree (updated_at, shopper_id);
COMMIT;
```
```console
$ pgslice swap locations
BEGIN;
ALTER TABLE locations RENAME TO locations_retired;
ALTER TABLE locations_intermediate RENAME TO locations;
COMMIT;
```
## Upgrading
Run:
```sh
gem install pgslice
```
To use master, run:
```sh
gem install specific_install
gem specific_install ankane/pgslice
```
## TODO
- Command to sync index changes with partitions
- Disable indexing for faster `fill`
## Contributing
Everyone is encouraged to help improve this project. Here are a few ways you can help:
- [Report bugs](https://github.com/ankane/pgslice/issues)
- Fix bugs and [submit pull requests](https://github.com/ankane/pgslice/pulls)
- Write, clarify, or fix documentation
- Suggest or add new features