How PostgreSQL stores rows
ketansingh.me
ketansingh.me
It's by no means a requirement to use the database
I wish
I agree, a fantastic resource.
Pretty sure the 8KB page size is not about atomicity. It's true old storage mostly promised 512B atomicity (AFAIK it depends on operation, but that's irrelevant here) and we rely on that in some places. But even if it was 4KB, it's still be just half of 8kB pages. So an 8KB page might still get torn, and we can't rely on that.
The simple truth is that this is a compromise - smaller pages benefit OLTP, larger pages benefit OLAP. And 8kB is somewhere in the middle. That's all.
You can get better performance from e.g. 4KB pages, especially if that aligns with filesystem / SSD pages, etc.
I recently (as in 6 hours ago) had to relay to my boss some information about the inner workings of postgres. studying this course helped me do that.
I wish Mongo/WT had a way to visualize the on disk structures...
Why some databases choose to use segment files as persistence and why some other databases choose to use key-value as persistence?
From my perspective, using key-value is very convenient because you can then outsource persistence to a distributed, fault tolerant, key-value storage.
Some SQL databases are backed by key-values stores, but they generally store large segments in the values rather than individual records. (e.g. Snowflake, Athena)
The chapter "Data Structures That Power Your Database" offers a great overview of various storage mechanisms of databases
> VACCUM as expected defragmented page by moving the tuples around.
I wasn't paying full attention to the code blocks initially so these two statements confused me until I went back. VACUUM FULL is what was actually run - VACUUM would not have moved tuples around, but if VACUUM was run before the INSERT, then that empty spot from the DELETE could have been reused.
[1] https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f...
VACUUM FULL essentially rebuilds the segment files - it creates new files and shovels all rows from the old ones. In the past it was implemented differently, by actually moving rows (a bit like defrag tools in Windows) but that was very expensive and inefficient.
[0] https://www.postgresql.org/docs/current/storage-toast.html
The problem with heap and compression is that it mixes a lot of different data (i.e. data from different columns), which is not great for compression ratio. To address that, it's necessary to use some variant of a columnar format, and allowing such stuff is one of the goals of the table AM API, zedstore AM etc.
[1]: https://www.postgresql.org/docs/current/storage-toast.html
But you'd better be sure that its storage guarantees match what Postgres needs, else you'll risk database corruption.
That said, there has been some progress in the general direction of allowing this: supporting new storage implementations, e.g. zheap (https://wiki.postgresql.org/wiki/Zheap). But it's a large effort. Consider it has to implement new crash recovery, for starters.