Presented by Keith Fiske / @keithf4
Senior Database Engineer @ Crunchy Data Solutions, Inc
(pg_partman, pgmonitor, pg_extractor, mimeo)
Follow along at
http://slides.keithf4.com/dontforget
Version | Released | Final Version | EOL |
---|---|---|---|
PostgreSQL 6.3 | March 1998 | 6.3.2 | March 2003 |
PostgreSQL 6.4 | Oct 1998 | 6.4.2 | Oct 2003 |
PostgreSQL 6.5 | June 1999 | 6.5.3 | June 2004 |
PostgreSQL 7.0 | May 2000 | 7.0.3 | May 2005 |
PostgreSQL 7.1 | Apr 2001 | 7.1.3 | Apr 2006 |
PostgreSQL 7.2 | Feb 2002 | 7.2.8 | Feb 2007 |
PostgreSQL 7.3 | Nov 2002 | 7.3.21 | Nov 2007 |
PostgreSQL 7.4 | Nov 2003 | 7.4.30 | Oct 2010 |
PostgreSQL 8.0 | Jan 2005 | 8.0.26 | Oct 2010 |
PostgreSQL 8.1 | Nov 2005 | 8.1.23 | Oct 2010 |
PostgreSQL 8.2 | Dec 2006 | 8.2.23 | Dec 2011 |
PostgreSQL 8.3 | Feb 2008 | 8.3.23 | Feb 2013 |
Version | Released | Final/Latest Version | EOL |
---|---|---|---|
PostgreSQL 8.4 | July 2008 | 8.4.22 | July 2014 |
PostgreSQL 9.0 | Sept 2010 | 9.0.23 | Oct 2015 |
PostgreSQL 9.1 | Sept 2011 | 9.1.24 | Oct 2016 |
PostgreSQL 9.2 | Sept 2012 | 9.2.24 | Nov 2017 |
PostgreSQL 9.3 | Sept 2013 | 9.3.25 | Nov 2018 |
PostgreSQL 9.4 | Dec 2014 | 9.4.24 | Feb 2020 |
PostgreSQL 9.5 | Jan 2016 | 9.5.19 | Feb 2021 |
PostgreSQL 9.6 | Sept 2016 | 9.6.15 | Nov 2021 |
PostgreSQL 10 | Oct 2017 | 10.10 | Nov 2022 |
PostgreSQL 11 | Oct 2018 | 11.5 | Nov 2023 |
PostgreSQL 12 | Oct 2019 | 12.0 | Nov 2024 |
SELECT salary, sum(salary) OVER () FROM empsalary;
salary | sum
--------+-------
5200 | 47100
5000 | 47100
3500 | 47100
4800 | 47100
3900 | 47100
4200 | 47100
4500 | 47100
4800 | 47100
6000 | 47100
5200 | 47100
(10 rows)
SELECT salary, sum(salary) OVER (ORDER BY salary) FROM empsalary;
salary | sum
--------+-------
3500 | 3500
3900 | 7400
4200 | 11600
4500 | 16100
4800 | 25700
4800 | 25700
5000 | 30700
5200 | 41100
5200 | 41100
6000 | 47100
(10 rows)
SELECT depname, empno, salary, avg(salary)
OVER (PARTITION BY depname)
FROM empsalary;
depname | empno | salary | avg
-----------+-------+--------+-----------------------
develop | 11 | 5200 | 5020.0000000000000000
develop | 7 | 4200 | 5020.0000000000000000
develop | 9 | 4500 | 5020.0000000000000000
develop | 8 | 6000 | 5020.0000000000000000
develop | 10 | 5200 | 5020.0000000000000000
personnel | 5 | 3500 | 3700.0000000000000000
personnel | 2 | 3900 | 3700.0000000000000000
sales | 3 | 4800 | 4866.6666666666666667
sales | 1 | 5000 | 4866.6666666666666667
sales | 4 | 4800 | 4866.6666666666666667
(10 rows)
SELECT depname, empno, salary, rank()
OVER (PARTITION BY depname ORDER BY salary DESC)
FROM empsalary;
depname | empno | salary | rank
-----------+-------+--------+------
develop | 8 | 6000 | 1
develop | 10 | 5200 | 2
develop | 11 | 5200 | 2
develop | 9 | 4500 | 4
develop | 7 | 4200 | 5
personnel | 2 | 3900 | 1
personnel | 5 | 3500 | 2
sales | 1 | 5000 | 1
sales | 4 | 4800 | 2
sales | 3 | 4800 | 2
(10 rows)
WITH regional_sales AS (
SELECT region, SUM(amount) AS total_sales
FROM orders
GROUP BY region
), top_regions AS (
SELECT region
FROM regional_sales
WHERE total_sales > (SELECT SUM(total_sales)/10 FROM regional_sales)
)
SELECT region,
product,
SUM(quantity) AS product_units,
SUM(amount) AS product_sales
FROM orders
WHERE region IN (SELECT region FROM top_regions)
GROUP BY region, product;
WITH RECURSIVE t(n) AS (
VALUES (1)
UNION ALL
SELECT n+1 FROM t WHERE n < 100
)
SELECT sum(n) FROM t;
sum
------
5050
(1 row)
WITH moved_rows AS (
DELETE FROM products
WHERE
"date" >= '2010-10-01' AND
"date" < '2010-11-01'
RETURNING *
)
INSERT INTO products_log
SELECT * FROM moved_rows;
BEFORE:
BEGIN;
INSERT INTO users (name, email) VALUES (?,?) RETURNING userid;
INSERT INTO addresses (userid, address, city, state, zip)
VALUES (?,?,?,?,?) RETURNING addressid;
INSERT INTO user_history (userid, addressid, action) VALUES (?,?,?) RETURNING historyid;
COMMIT;
AFTER:
WITH userdata AS (
INSERT INTO users (name, email) VALUES (?,?)
RETURNING userid
), addressdata AS (
INSERT INTO addresses (userid, address, city, state, zip)
SELECT userid,?,?,?,?
FROM userdata
RETURNING addressid
), historydata AS (
INSERT INTO user_history (userid, addressid, action)
SELECT userid, addressid,?
FROM userdata, addressdata
RETURNING historyid
)
SELECT userid, addressid, historyid
FROM userdata, addressdata, historydata;
-- includes 3, does not include 7, and does include all points in between
SELECT '[3,7)'::int4range;
-- does not include either 3 or 7, but includes all points in between
SELECT '(3,7)'::int4range;
-- includes only the single point 4
SELECT '[4,4]'::int4range;
-- includes no points (and will be normalized to 'empty')
SELECT '[4,4)'::int4range;
CREATE TABLE reservation (room int, during tsrange);
INSERT INTO reservation VALUES
(1108, '[2010-01-01 14:30, 2010-01-01 15:30)');
-- Containment
SELECT int4range(10, 20) @> 3;
?column?
----------
f
-- Overlaps
SELECT numrange(11.1, 22.2) && numrange(20.0, 30.0);
?column?
----------
t
-- Extract the upper bound
SELECT upper(int8range(15, 25));
upper
-------
25
-- Compute the intersection
SELECT int4range(10, 20) * int4range(15, 25);
?column?
----------
[15,20)
test=# SELECT * FROM cars ORDER BY lower(cars.price_range);
id | name | price_range
-----+---------------------+-----------------
2 | Buick Skylark | [2000,4001)
3 | Pontiac GTO | [5000,7501)
4 | Chevrolet Camero | [10000,12001)
5 | Ford Mustang | [11000,15001)
6 | Lincoln Continental | [12000,14001)
7 | BMW M3 | [35000,42001)
8 | Audi RS4 | [41000,45001)
9 | Porsche 911 | [47000,58001)
10 | Lamborghini LP700 | [385000,400001)
SELECT *
FROM cars
WHERE
(
cars.min_price ≤ 13000 AND
cars.min_price ≤ 15000 AND
cars.max_price ≥ 13000 AND
cars.max_price ≤ 15000
) OR
(
cars.min_price ≤ 13000 AND
cars.min_price ≤ 15000 AND
cars.max_price ≥ 13000 AND
cars.max_price ≥ 15000
) OR
(
cars.min_price ≥ 13000 AND
cars.min_price ≤ 15000 AND
cars.max_price ≥ 13000 AND
cars.max_price ≤ 15000
) OR
(
cars.min_price ≥ 13000 AND
cars.min_price ≤ 15000 AND
cars.max_price ≥ 13000 AND
cars.max_price ≥ 15000
)
ORDER BY cars.min_price;
SELECT *
FROM cars
WHERE cars.price_range && int4range(13000, 15000, '[]')
ORDER BY lower(cars.price_range);
id | name | price_range
----+---------------------+---------------
5 | Ford Mustang | [11000,15001)
6 | Lincoln Continental | [12000,14001)
IpcMemoryCreate: shmget(key=5432001, size=415776768, 03600) failed: Invalid argument This error usually means that PostgreSQL's request for a shared memory segment exceeded your kernel's SHMMAX parameter. You can either reduce the request size or reconfigure the kernel with larger SHMMAX. To reduce the request size (currently 415776768 bytes), reduce PostgreSQL's shared_buffers parameter (currently 50000) and/or its max_connections parameter (currently 12).
CREATE TABLE cards (
id integer NOT NULL,
board_id integer NOT NULL,
data jsonb
);
INSERT INTO cards VALUES (1, 1, '{"name": "Paint house", "tags": ["Improvements", "Office"], "finished": true}');
SELECT data->>'name' AS name FROM cards;
SELECT count(*) FROM cards WHERE data->>'finished' = 'true';
Aggregate (cost=335.12..335.13 rows=1 width=0) (actual time=4.421..4.421 rows=1 loops=1) -> Seq Scan on cards (cost=0.00..335.00 rows=50 width=0) (actual time=0.016..3.961 rows=4938 loops=1)
Filter: ((data ->> 'finished'::text) = 'true'::text)
Rows Removed by Filter: 5062
Planning time: 0.071 ms
Execution time: 4.465 ms
CREATE INDEX idxfinished ON cards ((data->>'finished'));
Aggregate (cost=118.97..118.98 rows=1 width=0) (actual time=2.122..2.122 rows=1 loops=1) -> Bitmap Heap Scan on cards (cost=4.68..118.84 rows=50 width=0) (actual time=0.711..1.664 rows=4938 loops=1)
Recheck Cond: ((data ->> 'finished'::text) = 'true'::text)
Heap Blocks: exact=185
-> Bitmap Index Scan on idxfinished (cost=0.00..4.66 rows=50 width=0) (actual time=0.671..0.671 rows=4938 loops=1)
Index Cond: ((data ->> 'finished'::text) = 'true'::text)
Planning time: 0.084 ms
Execution time: 2.199 ms
synchronous_standby_names = '2 (s1, s2, s3)'
synchronous_standby_names = 'FIRST 2 (s1, s2, s3)'
synchronous_standby_names = 'ANY 2 (s1, s2, s3)'
CREATE TABLE measurement (
city_id int not null,
logdate date not null,
peaktemp int,
unitsales int
) PARTITION BY RANGE (logdate);
CREATE TABLE measurement_y2006m02 PARTITION OF measurement
FOR VALUES FROM ('2006-02-01') TO ('2006-03-01');
CREATE TABLE measurement_y2006m03 PARTITION OF measurement
FOR VALUES FROM ('2006-03-01') TO ('2006-04-01');
keith@keith=# \d+ measurement
Table "public.measurement"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
-----------+---------+-----------+----------+---------+---------+--------------+-------------
city_id | integer | | not null | | plain | |
logdate | date | | not null | | plain | |
peaktemp | integer | | | | plain | |
unitsales | integer | | | | plain | |
Partition key: RANGE (logdate)
Partitions: measurement_y2006m02 FOR VALUES FROM ('2006-02-01') TO ('2006-03-01'),
measurement_y2006m03 FOR VALUES FROM ('2006-03-01') TO ('2006-04-01')
wal_level = logical
CALL partman.partition_data_proc('public.mytable');
=# \h DROP PROCEDURE
Command: DROP PROCEDURE
Description: remove a procedure
Syntax:
DROP PROCEDURE [ IF EXISTS ] name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] [, ...]
[ CASCADE | RESTRICT ]
URL: https://www.postgresql.org/docs/12/sql-dropprocedure.html