PostgreSQL lze vertikálně škálovat poměrně dobře. Čím více zdrojů (CPU, paměť, disk), které můžete svému PostgreSQL serveru zpřístupnit, tím lépe může fungovat. Nicméně zatímco některé části Postgresu mohou automaticky využívat zvýšené zdroje, jiné části potřebují změny konfigurace, než si všimnete vylepšení.
Čtěte dále a zjistěte více o tom, jak zajistit, aby PostgreSQL plně využíval systém, na kterém jej provozujete.
CPU
Jaké měřítko automaticky
PostgreSQL má tradiční procesní architekturu sestávající z hlavního procesu (nazývaného postmaster ), který vytvoří nový proces (nazývanýbackend ) pro každé nové připojení klienta. To znamená, že pokud je k dispozici více jader CPU, může současně běžet více procesů, a proto backendy nemusí tolik bojovat o dostupnost CPU. Dotazy vázané na CPU budou dokončeny rychleji.
Možná budete chtít upravit maximální povolená simultánní připojení na úrovni celého systému, databáze nebo uživatele:
-- system level
ALTER SYSTEM SET max_connections = 200;
-- database level
ALTER DATABASE dbname CONNECTION LIMIT 200;
-- user level
ALTER ROLE username CONNECTION LIMIT 20;
tak, aby podvodné aplikace nemohly skončit nahromaděním příliš mnoha připojení.
Co je třeba vylepšit
Server PostgreSQL může spustit proces, který se postará o úklidové úkoly, jako je vysávání, replikace, předplatné (pro logickou replikaci) atd. Počet těchto pracovníků se neurčuje dynamicky, ale pouze se nastavuje pomocí konfigurace a výchozí je 8.
Nastavení nejvyšší úrovně konfigurace pro počet pracovních procesů je:
# typically specified in postgresql.conf
max_worker_processes = 16
Zvýšení této hodnoty může výsledkem je urychlení úloh údržby, paralelních dotazů a vytváření indexů.
Paralelní dotazy
Počínaje verzí 9.6 může Postgres provádět dotazy paralelně, pokud se plánovač dotazů rozhodne, že to pomůže. Paralelní dotazování zahrnuje vytváření pracovníků, rozdělování práce mezi ně a následné shromažďování (shromažďování) výsledků. Podléhá celkovému limitu max_worker_processes
nastavena dříve, Postgres určí, kolik pracovníků může být vytvořeno pro paralelní dotaz v závislosti na hodnotě dvou konfiguračních nastavení:
# 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
Pokud máte nečinné CPU a paralelizovatelné dotazy, zvýšení těchto hodnot může takové dotazy urychlit.
Vytvoření paralelního indexu
V Postgres 11 byla přidána podpora pro paralelní vytváření indexů B-Tree. Pokud pravidelně vytváříte indexy B-Stromu nebo je REINDEXujete, zvýšení této hodnoty může pomoci:
# the maximum number of parallel workers that can be
# started by a single utility command
max_parallel_maintenance_workers = 8
To Postgresu umožní vytvořit tolik pracovníků (s výhradou celkového limitu max_worker_processes
), abyste urychlili vytváření indexů B-Stromu.
Logická replikace
Logická replikace (dostupná v Postgres 10 a vyšší) se při získávání změn od vydavatele spoléhá na pracovní procesy na straně předplatného. Když Postgres požádáte, aby vytvořil více logických replikačních pracovníků, změny mohou být načteny a aplikovány paralelně, zvláště pokud existuje více tabulek. Toto nastavení konfigurace zvyšuje celkový počet pracovníků replikace:
# maximum number of logical replication workers
max_logical_replication_workers = 8
Při streamování replikace můžete zahájit synchronizaci se základní zálohou. Forlogická replikace však musí být změny vtaženy přes samotný replikační protokol přes síť. To může být časově náročné. Povolení více pracovníků během fáze synchronizace může tento proces urychlit:
# basically the number of tables that are synced in
# parallel during initialization of subscription
max_sync_workers_per_subscription = 8
Autovakuum
Periodicky, na základě hromady konfiguračních nastavení, bude Postgres generovat hromadu pracovníků, kteří budou VAKUOVAT databázové tabulky. To se samozřejmě nazývá autovakuum a počet pracovníků, které spouštěč autovakua pokaždé spustí, lze nastavit pomocí konfiguračního nastavení:
# the maximum number of autovacuum processes
autovacuum_max_workers = 8
Komprese WAL
Pokud máte CPU volné, můžete vyměnit CPU za šířku pásma disku komprimací stránek, které jsou zapsány do souborů WAL. To snižuje množství dat, která je třeba zapsat na disk, na úkor většího počtu cyklů CPU pro kompresi dat. Také snižuje velikost dat, která je třeba posílat přes drát pro streamingovou replikaci.
V praxi výhody komprese WAL stojí za velmi rozumnou režii. Chcete-li jej zapnout, použijte:
# compresses full page images written to WAL
wal_compression = on
Paměť
Jaké měřítko automaticky
Operační systém automaticky spravuje a využívá paměť, která není využívána žádnou aplikací, pro ukládání dat čtených z disku a zapisovaných na disk v poslední době do mezipaměti. To výrazně zrychluje aplikace náročné na disk a určitě PostgreSQL.
V Linuxu, nejoblíbenějším hostiteli pro Postgres, nemůže uživatel nastavit velikost mezipaměti disku OS. Jeho správa je interní pro Linux. Pod tlakem paměti poskytne aplikacím diskovou mezipaměť.
Co je třeba vylepšit
Plánovač dotazů
Plánovač dotazů musí do svých odhadů zahrnout množství diskové mezipaměti poskytované OS jako faktor. Pokud se vám podařilo výrazně zvýšit diskovou mezipaměť operačního systému (zvýšením dostupné paměti), zvýšení tohoto konfiguračního nastavení může pomoci zlepšit odhady plánovače:
# the planner's assumption about the effective size
# of the disk cache that is available to a single query.
effective_cache_size = 64GB
Sdílená paměť
PostgreSQL používá sadu vyrovnávacích pamětí, které sdílejí všichni pracovníci a backendprocess. Tyto se nazývají sdílené vyrovnávací paměti a množství paměti přidělené pro sdílené vyrovnávací paměti se nastavuje pomocí konfiguračního nastavení:
shared_buffers = 32GB
Dočasné vyrovnávací paměti
Při přístupu k dočasným tabulkám pomocí dotazu jsou vyrovnávací paměti přiděleny do mezipaměti obsahu, který je načten. Velikost této vyrovnávací paměti se nastavuje pomocí nastavení konfigurace:
# the maximum number of temporary buffers used
# by each database session
temp_buffers = 100MB
Pokud máte dostatek paměti a dotazy, které intenzivně využívají dočasné tabulky, zvýšení této hodnoty může takové dotazy urychlit.
Pracovní paměť
Pracovní paměť je alokována lokálně a soukromě pomocí backendů. Používá se k řazení a spojování, aniž byste museli vytvářet dočasné tabulky. Zvětšením z výchozích 4 MB může být dotazy dokončeny rychleji při vytváření dočasné tabulky:
# the amount of memory to be used by internal sort
# operations and hash tables before writing to temporary disk files
work_mem = 16MB
Provozy údržby
Paměť používaná VACUUM, vytváření indexů a další podobné příkazy údržby se řídí konfiguračním nastavením maintenance_work_mem
. Zvýšení této částky může urychlit tyto operace, zejména u indexů nebo tabulek, které je třeba znovu vytvořit.
Paměť používanou pracovníky autovakuování lze převzít z pracovní paměti údržby (nastavením autovacuum_work_mem = -1
) nebo nakonfigurované nezávisle.
# 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
Jaké měřítko automaticky
Disky mohou být větší, rychlejší nebo více souběžné. Velikost disku je jediná věc, o které PostgreSQL nemusí být instruován. Ve výchozím nastavení se PostgreSQL nebude omezovat v používání jakéhokoli dostupného místa na disku. To je obvykle v pořádku.
Můžete však omezit celkovou velikost vytvořených dočasných souborů a poskytnout určitou ochranu proti dotazům, které se snaží seřadit miliardy řádků a podobně:
# the maximum amount of disk space that a process
# can use for temporary files
temp_file_limit = 500GB
Co je třeba vylepšit
Souběh
Disky RAID a souborové systémy jako ZFS lze nastavit tak, aby podporovaly více souběžnosti. To znamená, že můžete mít několik čtení/zápisů na disk souběžně obsluhovaných těmito systémy souborů kvůli způsobu, jakým interně ukládají nebo zpracovávají data.
Můžete nechat Postgres vydat více souběžných diskových I/O pomocí tohoto konfiguračního nastavení:
# the number of concurrent disk I/O operations that
# PostgreSQL expects can be executed simultaneously
effective_io_concurrency = 4
To se však v současnosti používá pouze při skenování haldy bitmapy.
Cena náhodné stránky
Plánovač dotazů Postgres předpokládá, že sekvenční čtení je rychlejší než náhodné čtení. O kolik přesně rychleji je hodnota, kterou můžete vyladit. Ve výchozím nastavení předpokládá, že náhodné čtení je 4krát dražší.
V závislosti na nastavení disku, pracovní zátěži a benchmarkingu, pokud jste si jisti, že náhodné čtení je řekněme jen dvakrát dražší než sekvenční čtení, můžete to Postgresu sdělit:
# 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
Tabulkové prostory
Chcete-li využít výhody více disků, které nejsou připojeny jako jeden velký systém souborů, můžete použít tabulkové prostory. Pomocí tabulkových prostorů můžete umístit tabulky nebo indexovat různé systémy souborů. To může zlepšit souběžnost a poskytuje snadný způsob, jak zvládnout růst tabulky.
CREATE TABLESPACE disk2 LOCATION '/mnt/disk2/postgres';
Přečtěte si více o tabulkových prostorech zde.
Síť
Síť je obvykle nejméně používaným zdrojem na serveru PostgreSQL a je zřídka saturovaná. Pokud potřebujete škálovat, je dost snadné přidat další síťová rozhraní, každé se svou vlastní IP a nechat PostreSQL poslouchat na všech:
listen_addresses = '10.1.0.10,10.1.0.11'
Klienti budou muset mít vyváženou zátěž napříč všemi IP adresami, na kterých Postgres poslouchá.
Jiné
Existuje několik dalších konfiguračních nastavení, která lze vylepšit, z nichž většina zabírá více CPU a paměť.
Operace po částech
Postgres 10 zavedl dělení tabulek, které bylo vylepšeno v Postgresu 11. Některé optimalizace dotazů na oddílech nejsou ve výchozím nastavení zapnuté, protože mohou mít za následek vyšší spotřebu CPU a paměti. Jsou to:
# 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