PostgreSQL dapat menskalakan dengan cukup baik secara vertikal. Semakin banyak sumber daya (CPU, memori, disk) yang dapat Anda sediakan untuk server PostgreSQL Anda, semakin baik kinerjanya. Namun, sementara beberapa bagian Postgres dapat secara otomatis menggunakan sumber daya yang ditingkatkan, bagian lain memerlukan perubahan konfigurasi sebelum perbaikan dapat diperhatikan.
Baca terus untuk mempelajari lebih lanjut tentang cara memastikan PostgreSQL memanfaatkan sepenuhnya sistem tempat Anda menjalankannya.
CPU
Apa yang Menskalakan Secara Otomatis
PostgreSQL memiliki arsitektur proses tradisional, terdiri dari masterprocess (disebut postmaster ) yang memunculkan proses baru (disebutbackend ) untuk setiap koneksi klien baru. Ini berarti bahwa jika ada lebih banyak inti CPU yang tersedia, lebih banyak proses yang dapat berjalan secara bersamaan, dan oleh karena itu backend tidak harus bersaing terlalu banyak untuk ketersediaan CPU. Kueri terkait CPU akan selesai lebih cepat.
Anda mungkin ingin menyesuaikan koneksi simultan maksimum yang diizinkan pada tingkat seluruh sistem, per basis data, atau per pengguna:
-- system level
ALTER SYSTEM SET max_connections = 200;
-- database level
ALTER DATABASE dbname CONNECTION LIMIT 200;
-- user level
ALTER ROLE username CONNECTION LIMIT 20;
sehingga aplikasi jahat tidak dapat memonopoli terlalu banyak koneksi.
Yang Perlu Diubah
Server PostgreSQL dapat menelurkan proses untuk menangani tugas-tugas housekeeping, seperti vakum, replikasi, langganan (untuk replikasi logis), dll. Jumlah pekerja tersebut tidak ditentukan secara dinamis, tetapi hanya disetel melalui konfigurasi, dan default ke 8.
Pengaturan konfigurasi tingkat atas untuk jumlah proses pekerja adalah:
# typically specified in postgresql.conf
max_worker_processes = 16
Meningkatkan nilai ini bisa menghasilkan percepatan tugas pemeliharaan, kueri paralel, dan pembuatan indeks.
Kueri Paralel
Dimulai dengan versi 9.6, Postgres dapat mengeksekusi kueri secara paralel jika perencana kueri memutuskan itu akan membantu. Kueri paralel melibatkan pekerja pemijahan, mendistribusikan pekerjaan di antara mereka dan kemudian mengumpulkan (mengumpulkan) hasilnya. Tunduk pada batas keseluruhan max_worker_processes
ditetapkan sebelumnya, Postgres akan menentukan berapa banyak pekerja yang dapat dimunculkan untuk kueri paralel tergantung pada nilai dua pengaturan konfigurasi:
# the maximum number of workers that the system can
# support for parallel operations
max_parallel_workers = 8
# the maximum number of workers that can be started
# by a single Gather or Gather Merge node
max_parallel_workers_per_gather = 8
Jika Anda memiliki CPU yang tidak aktif dan kueri yang dapat diparalelkan, meningkatkan nilai ini dapat mempercepat kueri tersebut.
Pembuatan Indeks Paralel
Di Postgres 11, dukungan untuk pembuatan paralel indeks B-Tree telah ditambahkan. Jika Anda secara teratur membuat indeks B-Tree atau REINDEX, meningkatkan nilai ini dapat membantu:
# the maximum number of parallel workers that can be
# started by a single utility command
max_parallel_maintenance_workers = 8
Ini akan memungkinkan Postgres untuk menelurkan banyak pekerja ini (tunduk pada batas keseluruhan max_worker_processes
) untuk mempercepat pembuatan indeks B-Tree.
Replikasi Logis
Replikasi logis (tersedia di Postgres 10 dan di atasnya), bergantung pada proses pekerja di sisi langganan untuk mengambil perubahan dari penerbit. Dengan meminta Postgres untuk menelurkan lebih banyak pekerja replikasi logis, perubahan dapat diambil dan diterapkan secara paralel, terutama jika ada lebih banyak tabel. Pengaturan konfigurasi ini meningkatkan jumlah total pekerja replikasi:
# maximum number of logical replication workers
max_logical_replication_workers = 8
Dalam replikasi streaming, Anda dapat memulai sinkronisasi dengan pencadangan dasar. Namun, replikasi forlogis, perubahan harus dilakukan melalui protokol replikasi itu sendiri, melalui jaringan. Ini bisa memakan waktu. Mengizinkan lebih banyak pekerja selama fase sinkronisasi dapat mempercepat proses ini:
# basically the number of tables that are synced in
# parallel during initialization of subscription
max_sync_workers_per_subscription = 8
Autovacuum
Secara berkala, berdasarkan sekelompok pengaturan konfigurasi, Postgres akan memunculkan banyak pekerja yang akan MENGHAPUS tabel database. Ini tentu saja, disebut autovacuum, dan jumlah pekerja yang dihasilkan peluncur autovacuum setiap kali dapat diatur melalui pengaturan konfigurasi:
# the maximum number of autovacuum processes
autovacuum_max_workers = 8
Kompresi WAL
Jika Anda memiliki CPU cadangan, Anda dapat menukar CPU dengan bandwidth disk dengan mengompresi halaman yang ditulis ke dalam file WAL. Ini mengurangi jumlah data yang perlu ditulis ke disk, dengan mengorbankan lebih banyak siklus CPU untuk mengompresi data. Ini juga mengurangi ukuran data yang perlu dikirim melalui kabel untuk replikasi streaming.
Secara praktis, manfaat kompresi WAL sepadan dengan biaya overhead yang sangat masuk akal. Untuk mengaktifkannya, gunakan:
# compresses full page images written to WAL
wal_compression = on
Memori
Apa yang Menskalakan Secara Otomatis
OS secara otomatis mengelola dan menggunakan memori yang tidak digunakan oleh aplikasi apa pun untuk menyimpan data yang dibaca dan ditulis ke disk baru-baru ini. Ini sangat mempercepat aplikasi yang membutuhkan banyak disk, dan tentunya PostgreSQL.
Di Linux, host paling populer untuk Postgres, ukuran cache disk OS tidak dapat diatur oleh pengguna. Manajemennya internal untuk Linux. Di bawah tekanan memori, ini akan menghasilkan memori cache disk ke aplikasi.
Apa yang Perlu Diubah
Perencana Kueri
Perencana kueri harus menyertakan jumlah cache disk yang disediakan oleh OS sebagai faktor dalam estimasinya. Jika Anda berhasil meningkatkan cache disk OS secara signifikan (dengan meningkatkan memori yang tersedia), meningkatkan pengaturan konfigurasi ini dapat membantu meningkatkan perkiraan perencana:
# the planner's assumption about the effective size
# of the disk cache that is available to a single query.
effective_cache_size = 64GB
Memori Bersama
PostgreSQL menggunakan satu set buffer yang dibagi antara semua pekerja dan proses backend. Ini disebut buffer bersama , dan jumlah memori yang dialokasikan untuk buffer bersama diatur menggunakan pengaturan konfigurasi:
shared_buffers = 32GB
Buffer Sementara
Saat tabel sementara diakses oleh kueri, buffer dialokasikan ke cache konten yang dibaca. Ukuran buffer ini diatur menggunakan pengaturan konfigurasi:
# the maximum number of temporary buffers used
# by each database session
temp_buffers = 100MB
Jika Anda memiliki sisa memori dan kueri yang banyak menggunakan tabel sementara, meningkatkan nilai ini dapat mempercepat kueri tersebut.
Memori Kerja
Memori kerja dialokasikan secara lokal dan pribadi oleh backend. Ini digunakan untuk memenuhi pengurutan dan penggabungan tanpa harus membuat tabel sementara. Meningkatkan ini dari default 4MB dapat membuat kueri selesai lebih cepat selama pembuatan tabel sementara:
# the amount of memory to be used by internal sort
# operations and hash tables before writing to temporary disk files
work_mem = 16MB
Operasi Pemeliharaan
Memori yang digunakan oleh VACUUM, pembuatan indeks, dan perintah pemeliharaan lainnya dikendalikan oleh pengaturan konfigurasi maintenance_work_mem
. Meningkatkan jumlah ini dapat mempercepat operasi ini, terutama pada indeks atau tabel yang perlu dibuat ulang.
Memori yang digunakan oleh pekerja autovacuum dapat diambil dari memori kerja pemeliharaan (dengan mengatur autovacuum_work_mem = -1
) atau dikonfigurasi secara independen.
# the maximum amount of memory to be used by
# maintenance operations
maintenance_work_mem = 128MB
# maximum amount of memory to be used by each
# autovacuum worker process
autovacuum_work_mem = -1
Disk
Apa yang Menskalakan Secara Otomatis
Disk dapat dibuat lebih besar, lebih cepat atau lebih bersamaan. Ukuran disk adalah satu-satunya hal yang PostgreSQL tidak perlu diinstruksikan. Secara default, PostgreSQL tidak akan membatasi dirinya untuk menggunakan ruang disk yang tersedia. Ini biasanya baik-baik saja.
Anda dapat membatasi ukuran total file sementara yang dibuat, untuk memberikan sejumlah perlindungan terhadap kueri yang mencoba mengurutkan satu miliar baris dan sejenisnya:
# the maximum amount of disk space that a process
# can use for temporary files
temp_file_limit = 500GB
Apa yang Perlu Diubah
Konkurensi
Disk dan sistem file RAID-ed seperti ZFS dapat diatur untuk mendukung lebih banyak konkurensi. Artinya, Anda dapat memiliki beberapa disk yang membaca/menulis dilayani secara bersamaan oleh sistem file tersebut karena cara menyimpan atau menangani data secara internal.
Anda dapat membiarkan Postgres mengeluarkan beberapa I/O disk bersamaan, dengan menggunakan pengaturan konfigurasi ini:
# the number of concurrent disk I/O operations that
# PostgreSQL expects can be executed simultaneously
effective_io_concurrency = 4
Ini saat ini hanya digunakan oleh pemindaian heap bitmap.
Biaya Halaman Acak
Perencana kueri Postgres mengasumsikan bahwa pembacaan berurutan lebih cepat daripada pembacaan acak. Persisnya seberapa cepat nilai yang dapat Anda atur. Secara default, ini mengasumsikan pembacaan acak 4 kali lebih mahal.
Bergantung pada penyiapan disk, beban kerja, dan pembandingan Anda, jika Anda yakin bahwa pembacaan acak dikatakan, hanya dua kali lebih mahal daripada pembacaan berurutan, Anda dapat memberitahukannya kepada Postgres:
# the planner's estimate of the cost of a disk page
# fetch that is part of a series of sequential fetches
seq_page_cost = 1
# the planner's estimate of the cost of a
# non-sequentially-fetched disk page
random_page_cost = 2
Ruang tabel
Untuk memanfaatkan beberapa disk yang tidak dipasang sebagai satu sistem file tunggal yang besar, Anda dapat menggunakan tablespace. Dengan tablespace, Anda dapat menempatkan tabel atau mengindeks sistem file yang berbeda. Ini dapat meningkatkan konkurensi dan menyediakan cara mudah untuk menangani pertumbuhan tabel.
CREATE TABLESPACE disk2 LOCATION '/mnt/disk2/postgres';
Baca lebih lanjut tentang tablespace di sini.
Jaringan
Jaringan biasanya merupakan sumber daya yang paling jarang digunakan di server PostgreSQL, dan jarang jenuh. Jika Anda perlu menskalakan, cukup mudah untuk menambahkan lebih banyak antarmuka jaringan masing-masing dengan IP-nya sendiri dan membuat PostreSQL mendengarkan semuanya:
listen_addresses = '10.1.0.10,10.1.0.11'
Klien harus memiliki beban seimbang di semua IP yang digunakan Postgreslistens.
Lainnya
Ada beberapa pengaturan konfigurasi lain yang dapat diubah, sebagian besar menggunakan lebih banyak CPU dan memori.
Operasi Partisi
Postgres 10 memperkenalkan partisi tabel, yang ditingkatkan pada Postgres 11. Beberapa optimasi kueri pada partisi tidak diaktifkan secara default, karena dapat menghasilkan konsumsi CPU dan memori yang lebih tinggi. Ini adalah:
# allow a join between partitioned tables to be
# performed by joining the matching partitions
enable_partitionwise_join = on
# allow grouping or aggregation on a partitioned
# tables performed separately for each partition
enable_partitionwise_aggregate = on