Buffer Bulk Eviction
If bulk reads or writes are performed, there is a risk that one-time data can quickly oust useful pages from the buffer cache.
As a precaution, bulk operations use rather small buffer rings, and eviction is performed within their boundaries, without affecting other buffers.
A buffer ring of a particular size consists of an array of buffers that are used one after another. At first, the buffer ring is empty, and individual buffers join it one by one, after being selected from the buffer cache in the usual manner. Then eviction comes into play,but only within the ring limits
Buffers added into a ring are not excluded from the buffer cache and can still be used by other operations. So if the buffer to be reused turns out to be pinned, or its usage count is higher than one, it will be simply detached from the ring and replaced by another buffer.
PostgreSQL supports three eviction strategies.
| strategy | trigger | buffer ring |
|---|---|---|
| Bulk reads | sequential scans of large tables if their size exceeds 1/4 of the buffer cache(128MB:16384 page) | 256KB(32 page) |
| Bulk writes | applied by Copy from, create table as select , and create materialized view commands, as well as by those alter table flavors that cause table rewrites. | default: 16MB(2048 page) |
| Vacuuming | full table scan without taking the visibility map into account | 256KB(32 page) |
Buffer rings do not always prevent undesired eviction. If UPDATE or DELETE commands affect a lot of rows, the performed table scan applies the bulk reads strategy, but since the pages are constantly being modified, buffer rings virtually become useless.
Another example worth mentioning is storing oversized data in TOAST tables. In spite of a potentially large volume of data that has to be read, toasted values are always accessed via an index, so they bypass buffer rings.
Let’s take a closer look at the bulk reads strategy. For simplicity, we will create a table in such a way that an inserted row takes the whole page. By default, the buffer cache size is 16,384 pages, 8 kb each. So the table must take more than 4096 pages for the scan to use a buffer ring.
1 | test=# SHOW shared_buffers; |
参考书目
- Egor Rogov, PostgreSQL 14 Internals, https://postgrespro.com/community/books/internals