ClickhouseTutorial
How we configure huge pages in ClickHouse Managed Postgres
Summary
ClickHouse Managed Postgres configures Linux huge pages to reduce the per-connection page-table cost and translation overhead of a large PostgreSQL shared_buffers cache. The configuration reserves a quarter of machine memory before PostgreSQL starts, verifies HugePages_Total, sets huge_pages = 'on' to prevent silent fallback, and sizes shared_buffers against the complete shared-memory segment, including buffer descriptors, WAL buffers, and lock tables. On an r7i.4xlarge with 32GB shared_buffers, 4KB pages added 31.1MB of page tables per connection and reached 6.12GB at 200 connections, while 2MB huge pages reached 111MB. A select-only pgbench test at 100 clients also rose from 373,083 TPS to 418,087 TPS, a 12% increase, while startup failure without a sufficient pool made misconfiguration explicit.
Context
Postgres is sensitive to page size because each backend maps the shared_buffers segment through its own page tables. With 4KB pages, a large cache creates substantial per-connection page-table memory costs and limited TLB coverage, while huge pages provide larger translation units. Reliable production use also requires avoiding allocation failures caused by memory fragmentation and preventing silent fallback to 4KB pages.
Approach / What changed
Reserve a huge-page pool before starting Postgres by flushing caches and compacting memory, then verify the allocation against HugePages_Total. Set huge_pages = 'on' so startup fails instead of silently falling back, and size shared_buffers in two passes using postgres -D -C shared_memory_size to account for the full shared-memory segment. The configuration uses the system-default 2MB huge pages and tunes overcommit against the remaining memory.
Takeaways
At 200 connections on the test system, page tables reached 6.12GB with 4KB pages but only 111MB with 2MB huge pages.
Huge pages must be reserved before memory fragmentation makes contiguous 2MB allocation unreliable; the allocation is checked through HugePages_Total.
The full shared-memory segment exceeds shared_buffers because it includes buffer descriptors, WAL buffers, and lock tables, so its size is measured with the Postgres binary before final sizing.
Source and freshness
- Source
- clickhouse.com
- Published
- Added to Yomu
- Last updated
Summaries are generated from the original by a language model. Check the original before relying on it.
Keep reading
Related reading
The Good Stuff
Paid picks we use ourselves. Links carry a referral code — a subscription through one earns us a commission at no extra cost to you.
The best engineering reads, once a week
One useful email. Unsubscribe anytime.