# b-tree

Published articles for b-tree.

This is one page of public article previews, not the complete archive. Follow Next page to continue. Summaries are not the original full articles.

## Covering Indexes and Index-Only Scans in PostgreSQL

DevFeed: [Covering Indexes and Index-Only Scans in PostgreSQL](<https://devfeed.tech/articles/covering-indexes-the-cheap-10x-that-most-schemas-leave-on-the-table-39591.md>)

Original publisher: [Read original article](<https://ankit-rana.com/logs/39-covering-indexes-index-only-scans/>)

Author: hello@ankit-rana.com

Published: 2026-08-18T00:00:00Z

Content type: tutorial

Language: en

Sources: [Ankit Rana | Mechanical Sympathy](<https://devfeed.tech/sources/ankit-rana-mechanical-sympathy.md>)

Topics: [PostgreSQL](<https://devfeed.tech/topics/postgresql.md>), [Query (disambiguation)](<https://devfeed.tech/topics/query.md>), [data](<https://devfeed.tech/topics/data.md>)

Tags: [b-tree](<https://devfeed.tech/tags/b-tree.md>), [cache](<https://devfeed.tech/tags/cache.md>), [covering](<https://devfeed.tech/tags/covering.md>), [covering-index](<https://devfeed.tech/tags/covering-index.md>), [database-performance](<https://devfeed.tech/tags/database-performance.md>), [explain](<https://devfeed.tech/tags/explain.md>), [heap](<https://devfeed.tech/tags/heap.md>), [indexes](<https://devfeed.tech/tags/indexes.md>), [indexing](<https://devfeed.tech/tags/indexing.md>), [innodb](<https://devfeed.tech/tags/innodb.md>), [pages](<https://devfeed.tech/tags/pages.md>), [postgresql](<https://devfeed.tech/tags/postgresql.md>), [query](<https://devfeed.tech/tags/query.md>), [storage](<https://devfeed.tech/tags/storage.md>), [vacuum](<https://devfeed.tech/tags/vacuum.md>)

### AI overview

This tutorial explains why a normal index scan may still be slow: after finding matching entries, the database follows a pointer into the table for each row. Covering indexes store the selected columns in the index and can avoid those heap reads. In PostgreSQL, index-only scans also depend on the visibility map marking pages all-visible, while SELECT * prevents the technique from being fully effective.

### Source excerpt

A normal index scan finds matching rows and then follows a pointer into the table for every one of them, which is a random read per row. A covering index stores the columns the query selects, so the engine answers entirely from the index and skips those reads. In PostgreSQL this only works when the visibility map marks the pages all-visible, so an unvacuumed table will report Heap Fetches in EXPLAIN and give back most of the gain. SELECT star defeats the technique completely.

## How to Write to SSDs - Co-Designing DBMS and Flash Storage

DevFeed: [How to Write to SSDs - Co-Designing DBMS and Flash Storage](<https://devfeed.tech/articles/how-to-write-to-ssds-co-designing-dbms-and-flash-storage-39661.md>)

Original publisher: [Read original article](<https://www.gauravsarma.com/posts/2026-06-22_optimising-ssd-writes-for-dbms>)

Published: 2026-06-22T00:00:00Z

Content type: article

Language: en

Sources: [Gaurav Sarma's Blog](<https://devfeed.tech/sources/gaurav-sarma-s-blog.md>)

Topics: [Database](<https://devfeed.tech/topics/database.md>), [Databases](<https://devfeed.tech/topics/databases.md>), [systems](<https://devfeed.tech/topics/systems.md>), [optimize](<https://devfeed.tech/topics/optimize.md>), [Parallelism](<https://devfeed.tech/topics/parallelism.md>)

Tags: [b-tree](<https://devfeed.tech/tags/b-tree.md>), [checkpoint](<https://devfeed.tech/tags/checkpoint.md>), [cycles](<https://devfeed.tech/tags/cycles.md>), [database](<https://devfeed.tech/tags/database.md>), [databases](<https://devfeed.tech/tags/databases.md>), [latency](<https://devfeed.tech/tags/latency.md>), [mysql](<https://devfeed.tech/tags/mysql.md>), [optimize](<https://devfeed.tech/tags/optimize.md>), [optimizing](<https://devfeed.tech/tags/optimizing.md>), [postgresql](<https://devfeed.tech/tags/postgresql.md>), [ssd](<https://devfeed.tech/tags/ssd.md>), [storage](<https://devfeed.tech/tags/storage.md>), [systems](<https://devfeed.tech/tags/systems.md>), [wal](<https://devfeed.tech/tags/wal.md>), [write-amplification](<https://devfeed.tech/tags/write-amplification.md>)

### AI overview

The article explains how database management systems and SSDs jointly amplify writes. It reports that a 4 KiB logical page write can become about 18.85 KiB of flash writes on a Samsung PM9A3, and presents DBMS-SSD co-design, including avoiding in-place updates, as a way to address the combined amplification.

### Source excerpt

. [How to Write to SSDs](optimising-ssd-writes-for-dbms-cover...

## The RUM Conjecture: You Cannot Optimize Reads, Updates, and Memory at Once

DevFeed: [The RUM Conjecture: You Cannot Optimize Reads, Updates, and Memory at Once](<https://devfeed.tech/articles/the-rum-conjecture-you-cannot-optimize-reads-updates-and-memory-at-once-39565.md>)

Original publisher: [Read original article](<https://ankit-rana.com/logs/13-rum-conjecture-database-tradeoffs/>)

Author: hello@ankit-rana.com

Published: 2026-03-17T00:00:00Z

Content type: article

Language: en

Sources: [Ankit Rana | Mechanical Sympathy](<https://devfeed.tech/sources/ankit-rana-mechanical-sympathy.md>)

Topics: [systems](<https://devfeed.tech/topics/systems.md>), [Databases](<https://devfeed.tech/topics/databases.md>), [Apache Cassandra](<https://devfeed.tech/topics/cassandra.md>), [rocksdb](<https://devfeed.tech/topics/rocksdb.md>), [MySQL](<https://devfeed.tech/topics/mysql.md>), [PostgreSQL](<https://devfeed.tech/topics/postgresql.md>)

Tags: [b-tree](<https://devfeed.tech/tags/b-tree.md>), [capacity](<https://devfeed.tech/tags/capacity.md>), [cassandra](<https://devfeed.tech/tags/cassandra.md>), [database](<https://devfeed.tech/tags/database.md>), [databases](<https://devfeed.tech/tags/databases.md>), [dram](<https://devfeed.tech/tags/dram.md>), [indexing](<https://devfeed.tech/tags/indexing.md>), [latency](<https://devfeed.tech/tags/latency.md>), [memory](<https://devfeed.tech/tags/memory.md>), [mysql](<https://devfeed.tech/tags/mysql.md>), [node](<https://devfeed.tech/tags/node.md>), [performance](<https://devfeed.tech/tags/performance.md>), [rocksdb](<https://devfeed.tech/tags/rocksdb.md>), [storage-engine](<https://devfeed.tech/tags/storage-engine.md>), [system-design](<https://devfeed.tech/tags/system-design.md>)

### AI overview

The article explains the RUM Conjecture, which describes a tradeoff among read overhead, update overhead, and memory overhead in database indexes and storage engines. It compares B-Trees, LSM-Trees, and hash indexes to show how each optimizes different tradeoffs.

### Source excerpt

You can strictly optimise at most two of read overhead, update overhead, and memory overhead; the third will be expensive. B-Trees optimise reads and memory and pay on writes. LSM-Trees optimise writes and memory and pay on reads. Hash indexes optimise reads and writes and pay in RAM. The useful question is not whether a database is good but which corner it optimises and what you are willing to pay for the other two.

## Pagination at Scale: Why OFFSET and SKIP Will Eventually Break Your API

DevFeed: [Pagination at Scale: Why OFFSET and SKIP Will Eventually Break Your API](<https://devfeed.tech/articles/pagination-at-scale-why-offset-and-skip-will-eventually-break-your-api-39566.md>)

Original publisher: [Read original article](<https://ankit-rana.com/logs/14-pagination-offset-vs-cursor/>)

Author: hello@ankit-rana.com

Published: 2026-03-17T00:00:00Z

Content type: tutorial

Language: en

Sources: [Ankit Rana | Mechanical Sympathy](<https://devfeed.tech/sources/ankit-rana-mechanical-sympathy.md>)

Topics: [API](<https://devfeed.tech/topics/api.md>), [Database](<https://devfeed.tech/topics/database.md>), [MongoDB](<https://devfeed.tech/topics/mongodb.md>)

Tags: [api](<https://devfeed.tech/tags/api.md>), [api-design](<https://devfeed.tech/tags/api-design.md>), [b-tree](<https://devfeed.tech/tags/b-tree.md>), [cursor](<https://devfeed.tech/tags/cursor.md>), [database-performance](<https://devfeed.tech/tags/database-performance.md>), [latency](<https://devfeed.tech/tags/latency.md>), [mongodb](<https://devfeed.tech/tags/mongodb.md>), [pagination](<https://devfeed.tech/tags/pagination.md>), [scalability](<https://devfeed.tech/tags/scalability.md>), [scale](<https://devfeed.tech/tags/scale.md>), [sql](<https://devfeed.tech/tags/sql.md>)

### AI overview

This article explains why OFFSET and SKIP pagination become slower and more memory-intensive as page depth increases. It presents cursor-based, or keyset, pagination as an alternative that uses an indexed range seek and reads a fixed number of rows, keeping fetch cost largely constant with list depth. The trade-off is that cursor pagination does not provide reliable absolute page numbers.

### Source excerpt

OFFSET does not seek. The engine fetches offset plus limit rows, sorts them, and discards the first N, so cost grows linearly with page depth. Cursor pagination passes the last seen key instead of a page number, letting the B+ tree seek in logarithmic time and read a fixed number of rows, which keeps latency flat at any depth. The price is losing absolute page numbers.

## How UUIDv4 Primary Keys Affect Database Insert Performance

DevFeed: [How UUIDv4 Primary Keys Affect Database Insert Performance](<https://devfeed.tech/articles/why-uuid-primary-keys-quietly-destroy-database-performance-39564.md>)

Original publisher: [Read original article](<https://ankit-rana.com/logs/12-uuids-primary-keys-performance/>)

Author: hello@ankit-rana.com

Published: 2026-03-16T00:00:00Z

Content type: article

Language: en

Sources: [Ankit Rana | Mechanical Sympathy](<https://devfeed.tech/sources/ankit-rana-mechanical-sympathy.md>)

Topics: [Database](<https://devfeed.tech/topics/database.md>), [MySQL](<https://devfeed.tech/topics/mysql.md>), [ordering](<https://devfeed.tech/topics/ordering.md>)

Tags: [b-tree](<https://devfeed.tech/tags/b-tree.md>), [database](<https://devfeed.tech/tags/database.md>), [database-performance](<https://devfeed.tech/tags/database-performance.md>), [fragmentation](<https://devfeed.tech/tags/fragmentation.md>), [innodb](<https://devfeed.tech/tags/innodb.md>), [latency](<https://devfeed.tech/tags/latency.md>), [mysql](<https://devfeed.tech/tags/mysql.md>), [performance](<https://devfeed.tech/tags/performance.md>), [system-design](<https://devfeed.tech/tags/system-design.md>), [uuid](<https://devfeed.tech/tags/uuid.md>)

### AI overview

This article explains how random UUIDv4 primary keys can reduce insert performance in clustered indexes. Random inserts land in the middle of B+ tree pages, causing page splits, fragmentation, additional writes, and buffer-pool churn. It recommends UUIDv7 or ULID, or an auto-increment clustered key with UUIDs in a unique secondary index.

### Source excerpt

The problem with UUIDv4 primary keys is not uniqueness, it is that random keys fight the storage engine's physical layout. In a clustered index the primary key is the table, so random inserts land mid-page, trigger page splits, leave pages half-full, and can inflate a 50 GB dataset to roughly 100 GB while wasting buffer pool on empty space. Use UUIDv7 or ULID, or keep an auto-increment clustered key with the UUID in a unique secondary index.

## Cursor Pagination vs Offset Pagination: Which One Should You Use?

DevFeed: [Cursor Pagination vs Offset Pagination: Which One Should You Use?](<https://devfeed.tech/articles/cursor-pagination-vs-offset-pagination-which-one-should-you-use-39652.md>)

Original publisher: [Read original article](<https://www.gauravsarma.com/posts/2026-03-11_cursor-pagination-vs-offset-pagination>)

Published: 2026-03-11T00:00:00Z

Content type: tutorial

Language: en

Sources: [Gaurav Sarma's Blog](<https://devfeed.tech/sources/gaurav-sarma-s-blog.md>)

Topics: [API](<https://devfeed.tech/topics/api.md>), [Databases](<https://devfeed.tech/topics/databases.md>), [SQL](<https://devfeed.tech/topics/sql.md>), [Query (disambiguation)](<https://devfeed.tech/topics/query.md>)

Tags: [api](<https://devfeed.tech/tags/api.md>), [apis](<https://devfeed.tech/tags/apis.md>), [b-tree](<https://devfeed.tech/tags/b-tree.md>), [database](<https://devfeed.tech/tags/database.md>), [index](<https://devfeed.tech/tags/index.md>), [indexes](<https://devfeed.tech/tags/indexes.md>), [query-planner](<https://devfeed.tech/tags/query-planner.md>), [rest-apis](<https://devfeed.tech/tags/rest-apis.md>)

### AI overview

This tutorial compares offset, cursor, and keyset pagination for REST APIs. It explains that offset pagination becomes slower at deep pages because the database scans and discards preceding rows, while concurrent inserts can cause duplicates or skipped results. Cursor pagination uses an indexed position for more consistent performance but does not support random page access; keyset pagination generalizes the approach to arbitrary sort orders.

### Source excerpt

. [Cursor vs Offset Pagination](cursor-pagination-vs-offset-pagination-cover...

## SQLite Query Optimisation - How the Planner Thinks and Where It Goes Wrong

DevFeed: [SQLite Query Optimisation - How the Planner Thinks and Where It Goes Wrong](<https://devfeed.tech/articles/sqlite-query-optimisation-how-the-planner-thinks-and-where-it-goes-wrong-39650.md>)

Original publisher: [Read original article](<https://www.gauravsarma.com/posts/2026-03-08_sqlite-query-optimisation>)

Published: 2026-03-08T00:00:00Z

Content type: tutorial

Language: en

Sources: [Gaurav Sarma's Blog](<https://devfeed.tech/sources/gaurav-sarma-s-blog.md>)

Topics: [SQLite](<https://devfeed.tech/topics/sqlite.md>), [SQL](<https://devfeed.tech/topics/sql.md>), [Databases](<https://devfeed.tech/topics/databases.md>)

Tags: [b-tree](<https://devfeed.tech/tags/b-tree.md>), [index](<https://devfeed.tech/tags/index.md>), [optimisation](<https://devfeed.tech/tags/optimisation.md>), [planner](<https://devfeed.tech/tags/planner.md>), [query](<https://devfeed.tech/tags/query.md>), [query-planner](<https://devfeed.tech/tags/query-planner.md>), [sql](<https://devfeed.tech/tags/sql.md>), [sqlite](<https://devfeed.tech/tags/sqlite.md>)

### AI overview

A tutorial on how SQLite's query planner chooses between index searches and full table scans. It explains planner behavior, the effects of query patterns and data distribution, and how to avoid conditions that make indexes inaccessible or scans appear cheaper.

### Source excerpt

. [SQLite Query Optimisation](sqlite-query-optimisation-cover...

## SQLite Overflow Pages - When Your Rows Don't Fit

DevFeed: [SQLite Overflow Pages - When Your Rows Don't Fit](<https://devfeed.tech/articles/sqlite-overflow-pages-when-your-rows-don-t-fit-39648.md>)

Original publisher: [Read original article](<https://www.gauravsarma.com/posts/2026-03-06_sqlite-overflow-pages>)

Published: 2026-03-06T00:00:00Z

Content type: tutorial

Language: en

Sources: [Gaurav Sarma's Blog](<https://devfeed.tech/sources/gaurav-sarma-s-blog.md>)

Topics: [SQLite](<https://devfeed.tech/topics/sqlite.md>), [Databases](<https://devfeed.tech/topics/databases.md>), [Data structures](<https://devfeed.tech/topics/data-structures.md>)

Tags: [b-tree](<https://devfeed.tech/tags/b-tree.md>), [data-structure](<https://devfeed.tech/tags/data-structure.md>), [database](<https://devfeed.tech/tags/database.md>), [performance](<https://devfeed.tech/tags/performance.md>), [sqlite](<https://devfeed.tech/tags/sqlite.md>)

### AI overview

This tutorial explains how SQLite stores rows in fixed-size pages and uses overflow-page chains when a row does not fit within a single page. It describes how those chains are reconstructed during reads and why large rows can significantly increase query costs.

### Source excerpt

. [SQLite Overflow Pages](sqlite-overflow-pages-cover...

## Dear Postgres

DevFeed: [Dear Postgres](<https://devfeed.tech/articles/dear-postgres-41201.md>)

Original publisher: [Read original article](<https://www.craigkerstiens.com/2017/10/12/Dear-Postgres/>)

Author: Map

Published: 2017-10-12T20:55:56Z

Content type: opinion

Language: en

Sources: [Craig Kerstiens](<https://devfeed.tech/sources/craig-kerstiens.md>)

Topics: [Databases](<https://devfeed.tech/topics/databases.md>), [Database](<https://devfeed.tech/topics/database.md>), [data](<https://devfeed.tech/topics/data.md>), [Geographic Information System](<https://devfeed.tech/topics/gis.md>), [JSON](<https://devfeed.tech/topics/json.md>), [functions](<https://devfeed.tech/topics/functions.md>), [XML](<https://devfeed.tech/topics/xml.md>)

Tags: [b-tree](<https://devfeed.tech/tags/b-tree.md>), [database](<https://devfeed.tech/tags/database.md>), [databases](<https://devfeed.tech/tags/databases.md>), [gis](<https://devfeed.tech/tags/gis.md>), [indexes](<https://devfeed.tech/tags/indexes.md>), [json](<https://devfeed.tech/tags/json.md>), [jsonb](<https://devfeed.tech/tags/jsonb.md>), [location-based](<https://devfeed.tech/tags/location-based.md>), [postgres](<https://devfeed.tech/tags/postgres.md>), [postgresql](<https://devfeed.tech/tags/postgresql.md>), [window-functions](<https://devfeed.tech/tags/window-functions.md>)

### AI overview

An appreciative commentary on Postgres describes how it has expanded beyond traditional relational database capabilities while retaining a focus on data durability, standards, and steady improvement. The article discusses indexes, GIS and PostGIS, analytical features such as window functions and CTEs, and JSON and JSONB support.

### Source excerpt

Dear Postgres, I've always felt an affinity for you in my 9 years of working with you. I know others have known you longer, but that doesn't mean they love you more. Years ago when others complained about your rigidness or that you weren't as accommodating as others I found solace in your steadfast values: Don't lose data Adhere to standards Move forward with a balancing act between new fads of the day while still continuously improving You've been there and seen it all. Years ago you were being disrupted by XML databases. As companies made heavy investment into what such a document database would do for their organization you proceeded to "simply" add a datatype that accomplished the same and brought your years of progress along with it. In the early years you had the standard format of index b-tree that most database engines leveraged. Then quietly but confidently you started adding more. Then came K-nearest neighbor, generalized inverted indexes (GIN), and generalized search-tree (GiST), only to be followed by space partitioned GiST and block range indexes (BRIN). Now the only question is which do I use? All the while there was this other camp using for something that felt cool but outside my world: GIS. GIS, geographical information systems, I thought was something only civil engineers used. Then GPS came along, then the iPhone and location based devices came along and suddenly I wanted to find out the nearest path to my Peets, or manage geographical region for my grocery delivery service. PostGIS had been there all along building up this powerful feature set, sadly to this day I still mostly marvel from the sideline at this whole other feature set I long to take advantage of... one day... one day. A little over 5 years ago I fell in love with your fastly improving analytical capabilities. No you weren't an MPP system yet, but here came window functions and CTEs, then I almost understood recursive CTEs (still working on that one). I can iterate over data in a recurs