0% found this document useful (0 votes)
36 views56 pages

Postgresql

The document discusses tuning PostgreSQL for high performance. It covers topics like PostgreSQL modules, performance tuning parameters like shared_buffers, wal_buffers and work_mem, and techniques like parallel query optimization.

Uploaded by

rama38udaya
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
36 views56 pages

Postgresql

The document discusses tuning PostgreSQL for high performance. It covers topics like PostgreSQL modules, performance tuning parameters like shared_buffers, wal_buffers and work_mem, and techniques like parallel query optimization.

Uploaded by

rama38udaya
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 56

Tuning PostgreSQL for High Performance and Optimization

PostgreSQL High Performance

Ibrar Ahmed

2
Who am I?
Software Career
• Software industries since 1998.

PostgreSQL Career
• Working on PostgreSQL Since 2006.

• EnterpriseDB (Associate Software

Architect core Database Engine)


@ibrar_ahmad 2006-2009

• EnterpriseDB (Software Architect core

Database Engine) 2011 - 2016


https://www.facebook.com/ibrar.ahmed
• EnterpriseDB (Senior Software Architect

IBRAR AHMED core Database Engine) 2016 – 2018

Senior Software Architect https://www.linkedin.com/in/ibrarahmed74/ • Percona (Senior


PostgreSQL Books Software Architect core

Database Engine) 2018 – Present


Percona LLC • PostgreSQL Developer's Guide

https://pgelephant.com/ • PostgreSQL 9.6 High Performance


01 Database Performance

02 PostgreSQL Modules

03 PostgreSQL Performance Tuning

04 Linux Kernel Tuning

05 Parallel Query Optimizations

06 Questions and Answers


Timeline

Database Performance PostgreSQL Performance Tuning Q Parallel Query Optimization Question Answers

5 Minutes 10 Minutes 15 Minutes 10 Minutes 5 Minutes 5 Minutes 5 Minutes

PostgreSQL Modules Linux Kernel Tuning Tips


1.
Database Performance
Overall Database System Performance
Database Performance

Hardware Database
Choose better Hardware Tune your database (PostgreSQL)

Operating System Application


Operating System Selection and Tuning Tune client application

Workload SELECT * FROM foo


Choose Database Depend based on Workload Tune your query properly.
Query
2.
PostgreSQL Modules
PostgreSQL
PostgreSQL Modules
Clients PostgreSQL Memory
work_mem
Client - psql Client - JDBC Client - ODBC
Shared Buffers
Default = 128MB
Processes

WAL Buffers maintancework_mem


Postgres Postgres Default = 16MB
Postmaster
Port = 5432

WAL Writer Archiver

Checkpointer Background Writer Logger Kernel Memory

4K 2MB/1GB Huge Pages THP


Disk Management
$PGDATA Table Spaces

base/ Datafiles global

pg_wal/ WAL files Configuration Files

/dev/sda /dev/sdb
3.
PostgreSQL Performance Tuning
PostgreSQL
Tuning Parameters
• shared_buffers

• wal_buffers

• effective_cache_size

• maintenance_work_mem

• synchronous_commit

• checkpoint_timeout

• checkpoint_completion_target

• temp_buffers

• huge_pages
PostgreSQL Tuning / shared_buffers
• PostgreSQL uses its own buffer along with kernel buffered I/O.

• PostgreSQL does not change the information on disk directly then how?

• Writes the data to shared buffer cache.

• The backend process writes that these blocks kernel buffer.

postgresql=# SHOW shared_buffers;


shared_buffers
----------------
128MB
(1 row)

The proper size for the POSTGRESQL shared buffer cache is the largest useful size that does not adversely affect other activity.
—Bruce Momjian
PostgreSQL Tuning / max_connections
• Maximum connection for PostgreSQL

• Default is 100
postgres=# SELECT pg_backend_pid(); ps aux | grep postgres | grep idle
pg_backend_pid vagrant 3214 0.0 1.2 194060 12948 ? Ss 15:09 0:00
---------------- postgres: vagrant postgres [local] idle
3214
(1 row) vagrant 3590 0.0 1.2 193840 12936 ? Ss 15:11 0:00
postgres: vagrant postgres [local] idle
postgres=# SELECT pg_backend_pid();
pg_backend_pid vagrant 3616 0.0 1.2 193840 13072 ? Ss 15:11 0:00
---------------- postgres: vagrant postgres [local] idle
3590
(1 row)

postgres=# SELECT pg_backend_pid();


pg_backend_pid
----------------
3616
(1 row)

If you want too many connections, try using pooler (pgbouncer)


PostgreSQL Tuning / shared_buffers

shared_buffers vs TPS
Shared_buffer vs TPS

Shared_buffer TPS

35%
128 Megabyte 500

128 Megabyte 3023

128 Megabyte 6801

1 Gigabyte 12898

2 Gigabyte 30987

4 Gigabyte 54536

8 Gigabyte 55352

16 Gigabyte 55364
PostgreSQL Tuning / wal_buffer
• Do you have Transaction? Obviously

• WAL – (Write Ahead LOG) Log your transactions

• Size of WAL files 16MB with 8K Block size (can be changed at compile time)

• PostgreSQL writes WAL into the buffers(wal_buffer ) and then these buffers are flushed to disk.

Bigger value for wal_buffer in case of lot of concurrent connection gives better performance.
PostgreSQL Tuning effective_cache_size
• This used by the optimizer to estimate the size of the kernel's disk buffer cache.

• The effective_cache_size provides an estimate of the memory available for disk caching.

• It is just a guideline, not the exact allocated memory or cache size.


PostgreSQL Tuning / work_mem
• This configuration is used for complex sorting.

• It allows PostgreSQL to do larger in-memory sorts.

• Each value is per session based, that means if you set that value to 10MB and 10 users issue sort queries then 100MB will

be allocated.

• In case of merge sort, if x number of tables are involved in the sort then x * work_mem will be used.

• It will allocate when required.

• Line in EXPLAIN ANALYZE “Sort Method: external merge Disk: 70208kB”


PostgreSQL Tuning / work_mem
postgres=# SET work_mem ='2MB';
postgres=# EXPLAIN ANALYZE SELECT * FROM foo ORDER BY id;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------------
Gather Merge (cost=848382.53..1917901.57 rows=9166666 width=9) (actual time=5646.575..12567.495 rows=11000000 loops=1)
Workers Planned: 2
Workers Launched: 2
-> Sort (cost=847382.51..858840.84 rows=4583333 width=9) (actual time=5568.049..7110.789 rows=3666667 loops=3)
Sort Key: id
Sort Method: external merge Disk: 74304kB
Worker 0: Sort Method: external merge Disk: 70208kB
Worker 1: Sort Method: external merge Disk: 70208kB
-> Parallel Seq Scan on foo (cost=0.00..105293.33 rows=4583333 width=9) (actual time=0.018..985.524 rows=3666667 loops=3)
Planning Time: 0.055 ms
Execution Time: 13724.353 ms
(11 rows)

postgres=# SET work_mem ='1GB';


postgres=# EXPLAIN ANALYZE SELECT * FROM foo ORDER BY id;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------
Sort (cost=1455965.01..1483465.01 rows=11000000 width=9) (actual time=5346.423..6554.609 rows=11000000 loops=1)
Sort Key: id
Sort Method: quicksort Memory: 916136kB
-> Seq Scan on foo (cost=0.00..169460.00 rows=11000000 width=9) (actual time=0.011..1794.912 rows=11000000 loops=1)
Planning Time: 0.049 ms
Execution Time: 7756.950 ms
(6 rows)

Time: 7757.595 ms (00:07.758)


maintenance_work_mem
● maintmaintenance_work_mem is a memory setting used for maintenance tasks.

● The default value is 64MB.

● Setting a large value helps in tasks like VACUUM, RESTORE, CREATE INDEX, ADD FOREIGN KEY and ALTER TABLE.
maintenance_work_mem
postgres=# CHECKPOINT;
postgres=# SET maintenance_work_mem='10MB';
postgres=# SHOW maintenance_work_mem;
maintenance_work_mem
----------------------
10MB
(1 row)
postgres=# CREATE INDEX idx_foo ON foo(id);
Time: 12374.931 ms (00:12.375)

postgres=# CHECKPOINT;
postgres=# SET maintenance_work_mem='1GB';
postgres=# SHOW maintenance_work_mem;
maintenance_work_mem
----------------------
1GB
(1 row)
postgres=# CREATE INDEX idx_foo ON foo(id);
Time: 9550.766 ms (00:09.551)
synchronous_commit
• This is used to enforce that commit will wait for WAL to be written on disk before returning a success status to the client.

• This is a trade-off between performance and reliability.

• Increasing reliability decreases performance and vice versa.

Synchronous commit doesn't introduce the risk of corruption, which is really bad, just some risk of data loss.
https://wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Server
checkpoint_timeout
• PostgreSQL writes changes into WAL. The checkpoint process flushes the data into the data files.

• More checkpoints have a negative impact on performance.

• Frequent checkpoint reduces the recovery time


4.
Linux Tuning for PostgreSQL
Ubuntu
Input Output Handling
• Direct IO, Buffered IO and Double buffering

• PostgreSQL believes that the Operating system (Kernel) knows much better about storage and IO scheduling.

• PostgreSQL has its own buffering; and also needs the pages cache. Double Buffering

• It Increase the use of memory.

• And different kernel and setting behave differently.


Virtual Memory
• Every process is given the impression that it is working with large, contiguous

sections of memory

• Each process runs in its own dedicated address space

• Pages Table are used to translate the virtual addresses seen by the application

into Physical Address

https://en.wikipedia.org/wiki/Virtual_memory
https://en.wikipedia.org/wiki/Page_table
Translation Lookaside Buffer (TLB)
• Translation Lookaside Buffer is a memory cache

• It reduce the time to access a user memory location

• If a match is found the physical address of the page is returned → TLB hit

• If match not found scan the page table (walk)

• looking for the address mapping (entry) → TLB miss

Small page size bigger TLB size → expensive


Memory Pages
• Different OS has different size of Pages

• Linux has a concept of Classic Huge Pages and Transparent Huge Pages.

• BSD has Super Pages.

• Windows has Large Pages.


Linux Page sizes
• Linux Page size is 4K

• Many modern processors support other page sizes

If we consider a server with 256G of RAM:

4K 6710886
4
g es
g e pa 2M 131072
e/h u
la r g
1G 256
Classic Huge Pages
# cat /proc/meminfo
MemTotal: 264041660 kB
...
Hugepagesize: 2048 kB
DirectMap4k: 128116 kB
DirectMap2M: 3956736 kB
DirectMap1G: 266338304 kB

sysctl -w vm.nr_hugepages=256
Classic Huge Pages
# vi /etc/default/grub

GRUB_CMDLINE_LINUX_DEFAULT="hugepagesz=1GB default_hugepagesz=1G”

# update-grub

Generating grub configuration file ...

Found linux image: /boot/vmlinuz-4.4.0-75-generic

Found initrd image: /boot/initrd.img-4.4.0-75-generic

Found memtest86+ image: /memtest86+.elf

Found memtest86+ image: /memtest86+.bin

Done

# shutdown -r now
Classic Huge Pages
# vim /etc/postgresql/10/main/postgresql.conf

huge_pages=ON # default is try

# service postgresql restart


Transparent Huge pages
• The kernel works in the background (khugepaged) trying to:

○ "create" huge pages.

○ Find enough contiguous blocks of memory

○ Convert them into a huge page

• Transparently allocate them to processes when there is a "fit"


Disabling Transparent Huge pages
# cat /proc/meminfo | grep AnonHuge

AnonHugePages: 2048 kB

# ps aux | grep huge

root 42 0.0 0.0 0 0 ? SN Jan17 0:00 [khugepaged]

To disable it:

• at runtime:

# echo never > /sys/kernel/mm/transparent_hugepage/enabled

# echo never > /sys/kernel/mm/transparent_hugepage/defrag

• at boot time:

GRUB_CMDLINE_LINUX_DEFAULT="(...) transparent_hugepage=never"
vm.swappiness
• This is another kernel parameter that can affect the performance of the database.

• Used to control the swappiness (swapping pages to swap memory into RAM) behavior on a Linux system.

• The parameter can take anything from “0” to “100”.

• The default value is 60.

• Higher value means more aggressively swap.

sudo sh -c 'echo 1 > /proc/sys/vm/swappiness'

sudo sh -c 'echo "vm.swappiness = 1" >> /etc/sysctl.conf'


vm.overcommit_memory and vm.overcommit_ratio
• Applications acquire memory and free that memory when it is no longer needed.

• But in some cases, an application acquires too much memory and does not release it. This can invoke the OOM killer.

• This is used to control the memory over-commit.

• It has three options

○ 0 - Heuristic overcommits, Do it intelligently (default); based kernel heuristics

○ 1 - Allow overcommit anyway

○ 2 - Don’t over commit beyond the overcommit ratio.

sudo sh -c ‘echo 2 > /proc/sys/vm/overcommit_memory’

sudo sh -c ‘echo 50 > /proc/sys/vm/overcommit_ratio’


vm.dirty_background_ratio and vm.dirty_background_bytes
• The vm.dirty_background_ratio is the percentage of memory filled with dirty pages that need to be flushed to disk.

• Flushing is done in the background.

• The value of this parameter ranges from 0 to 100;


vm.dirty_ratio / vm.dirty_bytes
• The vm.dirty_background_ratio is the percentage of memory filled with dirty pages that need to be flushed to disk.

• Flushing is done in the foreground.

• The value of this parameter ranges from 0 to 100;


5.
Parallel Query Optimizations
Parallel Query
Parallel Query
● How Parallel Query Works?

○ Actual working mechanism of parallel queries.


● When Can Parallel Query Be Used?

○ When parallel query can be used, and when it can not.


● Parallel Plans

○ Different parallel plans available.


● Parallel Safety

○ Parallel query operations are parallel safe, parallel restricted, or parallel unsafe.

https://www.postgresql.org/docs/12/parallel-plans.html
How Parallel Query Works - Configuration
• max_worker_processes The default is 8

Sets the maximum number of background processes that the system can support. This parameter can only be set at server start..

• max_parallel_workers_per_gather (integer) The default value is 2

Sets the maximum number of workers that can be started by a single Gather or Gather Merge node.

• max_parallel_workers (integer) The default value is 8

Sets the maximum number of workers that the system can support for parallel queries.

• dynamic_shared_memory_type (enum)

Parallel query requires dynamic shared memory in order to pass data between cooperating processes, so there should not be set to “none”

● Posix
● sysv
● windows
● mmap

• parallel_workers (integer) Sets the number of workers that should be used to assist a parallel scan of this table

postgresql.conf is the place where you can set these.


Some of the setting can be set on psql useng set command.
How Parallel Query Works - Configuration
EXPLAIN ANALYZE SELECT COUNT(*) FROM foo; EXPLAIN ANALYZE SELECT COUNT(*) FROM foo;
Finalize Aggregate Finalize Aggregate
-> Gather
-> Gather Check Workers Planned: 1
1 - max_worker_processes
Workers Planned: 2 2 - max_parallel_workers Workers Launched: 1
-> Partial Aggregate
Workers Launched: 0 -> Parallel Seq Scan on foo
-> Partial Aggregate
Check
-> Parallel Seq Scan on foo 1 - max_parallel_workers_per_gather
2 - parallel_workers

EXPLAIN ANALYZE SELECT COUNT(*) FROM foo; ALTER TABLE foo SET (parallel_workers = 2);
Finalize Aggregate EXPLAIN ANALYZE SELECT COUNT(*) FROM foo;
-> Gather Finalize Aggregate
Workers Planned: 1 -> Gather
Workers Launched: 1 Workers Planned: 2
-> Partial Aggregate Workers Launched: 2
-> Parallel Seq Scan on foo -> Partial Aggregate
-> Parallel Seq Scan on foo
ALTER TABLE foo SET (parallel_workers =
2);

These are quick tips, there may be some other reasons.


How Parallel Query Works - Example
EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%’;
QUERY PLAN
------------------------------------------------------------------------------------------------
Gather (cost=1000.00..217018.43 rows=1 width=97)
Workers Planned: 2
-> Parallel Seq Scan on pgbench_accounts (cost=0.00..216018.33 rows=1 width=97)
Filter: (filler ~~ '%x%'::text) (4 rows)

If the Gather or Gather Merge node is at the very top of the plan tree, then the entire query will execute in parallel,
otherwise only the portion of the plan below it will run in parallel
When Can Parallel Query Be Used?
• Number of backgrounds < max_worker_processes.

• Background workers for purposes of parallel query < max_parallel_workers.

• The client sends an execute message with a non-zero fetch count.

• When a prepared statement is executed using a CREATE TABLE .. AS EXECUTE .. statement.

• When the transaction isolation level is serializable*.

• The query uses any function marked PARALLEL UNSAFE.

• The query is running inside of another query that is already parallel.

• The query might be suspended during execution.

▪ PL/pgSQL Loops of the form FOR x IN query LOOP .. END LOOP

▪ DECLARE CURSOR

• The query writes any data or locks any database rows. If a query contains a data-modifying operation (top level/within a

CTE)*.
Default value of max_worker_processes and max_parallel_workers are 8.
* Limitation of current implementation.
When Can Parallel Query Be Used? 2/2
• Windowed functions and ordered-set aggregate functions are non-parallel*.

• Support for FULL OUTER JOIN

* This is a limitation of the current implementation.


Parallel Plans
● Parallel Scans

○ Parallel Sequential Scan

○ Parallel Bitmap Heap Scan

○ Parallel Index Scan

○ Parallel Index Only Scan

● Parallel Joins

● Parallel Aggregation

● Parallel Append
Parallel Sequential Scan
CREATE TABLE foo AS SELECT id AS id, 'name’::TEXT||id::TEXT AS name FROM
generate_series(1,10000000) AS id;
EXPLAIN ANALYZE SELECT * FROM foo WHERE id %2 = 10; Process
QUERY PLAN
-----------------------------------------------------------------------------
TABLE
----Seq Scan on foo (cost=0.00..204052.90 rows=49999 width=15) Block0
Planning Time: 0.063 ms Block1

Execution Time: 1657.964 ms Planning time Block2


Blockn

EXPLAIN ANALYZE SELECT * FROM foo WHERE id %2 = 10;


Leader
QUERY PLAN
--------------------------------------------------------------------------------
Gather Gather
Workers Planned: 4
Workers Launched: 4
-> Parallel Seq Scan on foo (cost=0.00..91554.48 rows=12500 width=15)
Filter: ((id % 2) = 10)
Worker1 Worker2 Worker3 Workern
Planning Time: 0.074 ms
Execution Time: 469.946 ms
TABLE
Reduce query execution Block0
time by using machines
Block1
multiple CPUs
Block2
Blockn

No benefit if table size is < min_parallel_table_scan_size


Parallel Bitmap Heap Scan
EXPLAIN (COSTS OFF )SELECT COUNT(*) FROM foo JOIN bar ON id =
• One process is chosen as the leader. v WHERE v > 10 AND name ~ 'name%';
QUERY PLAN
• Leader performs a scan of one or more indexes and ---------------------------------------------------------
Finalize Aggregate
-> Gather
builds a bitmap indicating which table blocks need to Workers Planned: 2
-> Partial Aggregate
be visited. -> Nested Loop
-> Parallel Bitmap Heap Scan on bar
• These blocks are then divided among the Recheck Cond: (v > 10)
-> Bitmap Index Scan on idx1
Index Cond: (v > 10)
cooperating processes as in a parallel sequential -> Bitmap Heap Scan on foo
Recheck Cond: (id = bar.v)
scan. Filter: (name ~ 'name%'::text)
-> Bitmap Index Scan on idx
Index Cond: (id = bar.v)

There is no benefit if bitmap size is very small.


Parallel Index Scan
EXPLAIN (costs off) SELECT id FROM foo WHERE val % 100 = 2 and id < 200000;
QUERY PLAN
--------------------------------------------------
Gather
Workers Planned: 2
-> Parallel Index Only Scan using idx1 on foo
Index Cond: (id < 200000)
Filter: ((val % 100) = 2)
(5 rows)

• Worker-0 will start from the root node 100 200 300

and scan until the leaf node 200. 100 101 102 200 210 220 300 301 302

• It’ll handover the next block under node


100 103 101 104 102 105 200 203 210 204 220 230 300 300 301 301 302 302

105 to Worker-1, which is in a blocked


and wait-state. 1,31 1,34 1,32 1,35 1,33 1,36 0,55 0,60 0,57 0,61 0,58 0,59 0,56 0,56 0,63 0,63 0,63 0,63

• If there are other workers, blocks are


Worker - 0 Worker - 1

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 . . . n
divided into the workers
Parallel Joins
Parallel Hash Join EXPLAIN ANALYZE SELECT COUNT(*)
In case of hash join the inner side is executed in full by every cooperating process FROM foo JOIN bar ON id = v WHERE v > 10;
QUERY PLAN
to build identical copies of the hash table. -------------------------------------------------------------
-Finalize Aggregate
What if hash table is too big ? -> Gather
Workers Planned: 2
Workers Launched: 2
-> Partial Aggregate
-> Parallel Hash Join
In parallel hash join the inner side is a parallel hash that divides the work of
Hash Cond: (bar.v = foo.id)
building a shared hash table over the cooperating processes. -> Parallel Seq Scan on)
All workers participate in creating the Hash table. Filter: (v > 10)
Rows Removed by Filter: 500058
After the hash, each worker can perform the join. -> Parallel Hash
Merge Join -> Parallel Seq Scan on foo
Planning Time: 0.211 ms
The inner side is always a non-parallel plan and therefore executed in full.
Execution Time: 758.847 ms
This may be inefficient, especially if a sort must be performed, because the work
and resulting data are duplicated in every cooperating process.
Nested Loop Join
The inner side is always non-parallel.
The outer tuples and thus the loops that look up values in the index are divided
over the cooperating processes.
Parallel Aggregation
Master
• Worker performs the scans on the pages and applies the
Finalize Aggregate
filter.
Gather Merge
• Transfer all the tuples to master.
Worker-0 Worker-1 Worker-2 Worker-3 Worker-4

• Master performs the final aggregate. Partial Aggregate Partial Aggregate Partial Aggregate Partial Aggregate Partial Aggregate

Seuential Scan Seuential Scan Seuential Scan Seuential Scan Seuential Scan

0 1 2 3 4 5 6 7 8 9 10 10 . . . n

EXPLAIN (COSTS FALSE) SELECT sum(id) FROM foo WHERE id EXPLAIN (COSTS FALSE) SELECT sum(id) FROM foo WHERE id %2 = 10;
QUERY PLAN
%2 = 10; ---------------------------------------------------------------
QUERY PLAN Finalize Aggregate A new Finalize Aggregate
-> Gather node to combine the
----------------------------------------------- Workers Planned: 4 results
-> Partial Aggregate
Aggregate Node to handle -> Parallel Seq Scan on foo
Aggregate aggregates Filter: ((id % 2) = 10)
-> Seq Scan on foo A new PartialAggregate
produces transition state
Filter: (( id % 2) = 10) outputs.
(3 rows)

Parallel aggregation is not supported if any aggregate function call contains DISTINCT or ORDER BY clause
Parallel Append
\d+ foo; EXPLAIN (costs off)SELECT count(id) FROM foo WHERE id <= 201;
Partitioned table "public.foo" QUERY PLAN
Column | Type | ---------------------------------------------------------
------+-------------- Finalize Aggregate
-> Gather Used to combine rows from
id | integer
Workers Planned: 2 multiple sources
name | text
-> Partial Aggregate
Partition key: RANGE (id) -> Parallel Append
Partitions: foo1 FOR VALUES FROM ('-1000000') TO (1), -> Parallel Seq Scan on foo1 foo_1
foo2 FOR VALUES FROM (1) TO (1000000) Filter: (id <= 201)
-> Parallel Seq Scan on foo2 foo_2
Filter: (id <= 201)
• Append node used to combine rows from multiple sources into a single result

set.

• In Append, all the participating processes cooperate to execute the first child

plan until it is complete and then move to the second plan at around the same
time

• In Parallel Append executor spread out the participating processes to its

child plans, so that multiple child plans are executed simultaneously

• Avoids CPU contention and enhances I/O parallelism.

enable_parallel_append can be used to disable/enable parallel append.


Parallel Labeling for Functions and Aggregates 1/2
CREATE FUNCTION add(integer, integer) RETURNS integer
• Parallel safe
AS 'select $1 + $2;'
A parallel safe operation is one which does not LANGUAGE SQL PARALLEL RESTRICTED;

conflict with the use of parallel query


CREATE FUNCTION add(integer, integer) RETURNS integer
• Parallel restricted AS 'select $1 + $2;'
LANGUAGE SQL PARALLEL SAFE;
A parallel restricted operation is one which cannot be
performed in a parallel worker, but which can be \df+ add
performed in the leader while parallel query is in use List of functions
Schema | Name | Parallel
• Parallel unsafe
+---------+----------+-------------------

A parallel unsafe operation is one which cannot be public | add | safe


(1 row)
performed while parallel query is in use, not even in
the leader.

All user-defined functions are assumed to be parallel unsafe unless otherwise marked.
Parallel Labeling for Functions and Aggregates 2/2
● The following operations are always parallel restricted:

• Scans of common table expressions (CTEs).

• Scans of temporary tables.

• Scans of foreign tables, unless the foreign data wrapper has an IsForeignScanParallelSafe API
which indicates otherwise.

• Plan nodes to which an InitPlan is attached.

• Plan nodes which reference a correlated SubPlan.


Parallel Index Creation
● PostgreSQL can build indexes while leveraging multiple CREATE INDEX idx ON foo(id);

CPUs in order to process the table rows faster. This feature CREATE INDEX
is known as parallel index build. Time: 11815.685 ms (00:11.816)
● Generally, a cost model automatically determines how

many worker processes should be requested, if any. SET max_parallel_maintenance_workers = 8;


CREATE INDEX idx ON foo(id);
CREATE INDEX
Time: 17281.309 ms (00:17.281)

Only B-tree parallel build is supported.


Blog Posts
• Tuning PostgreSQL Database Parameters to Optimize Performance.

○ https://www.percona.com/blog/2018/08/31/tuning-postgresql-database-parameters-to-optimize-performance/
• Tune Linux Kernel Parameters For PostgreSQL Optimization

○ https://www.percona.com/blog/2018/08/29/tune-linux-kernel-parameters-for-postgresql-optimization/
Thanks!
Any questions?
You can find me at:
[email protected]
● Pgelephant.com

56

You might also like