PostgreSQL Index-Only Scans and the Visibility Map
An index-only scan is only index-only when the visibility map says the heap page is all-visible. How to read Heap Fetches in EXPLAIN, build covering indexes with INCLUDE, and keep vacuum honest.
Notes for the problems that show up after launch: bad plans, awkward migrations, index debt, vacuum pressure, replica lag, and the small decisions that make PostgreSQL easier to operate.
An index-only scan is only index-only when the visibility map says the heap page is all-visible. How to read Heap Fetches in EXPLAIN, build covering indexes with INCLUDE, and keep vacuum honest.
The planner is only as good as its statistics. When autoanalyze lags behind a bulk load, the bad plans arrive long before the next analyze run does.
The ORM-generated subquery in FROM looked harmless until it materialized two million rows into a temp table. How MySQL decides between merging and materializing a derived table, and the rewrites that actually fix it.
InnoDB FULLTEXT and PostgreSQL tsvector both promise search without a search engine. Here is how indexing, ranking, and language support actually compare, and when neither is enough.
Optimistic parallel replication bets that your transactions will not conflict and pays for the bet in rollbacks. Here is how the five slave_parallel_mode modes differ, when the bet wins, and how to measure real lag.
Your ORM will connect to PostgreSQL on day one and still surprise you for weeks. These are the behavior changes I watch for: case sensitivity, booleans, upserts, RETURNING, and transaction aborts.
Both engines have ENUM, and both implementations will eventually make you regret something. Field notes on the sorting traps, the ALTER pain, and why a lookup table often wins in either engine.
Four hundred requests a minute, three temp tables each: three months later pg_attribute weighed 9 GB with six million dead tuples. Why per-request DDL churns the catalogs, and the patterns that stop it.
The app said the database was down; the database said CPU was twelve percent and forty-three sessions were queued behind one sleeping connection holding a lock. How I walk a blocking chain to its head and decide whether to kill or wait.
The audit checkbox says 'encrypt data at rest'; the operations reality is key custody, background rotation threads, a binlog that stays plaintext until you say otherwise, and a recovery plan that dies with the key file. The honest field guide.
Triggers or binlog streaming? Field notes from running both gh-ost and pt-online-schema-change in production: cut-over risk, throttling behavior, foreign key walls, and when you need neither.
Parallel query makes big scans faster until forty concurrent queries all want workers at once. The knobs, the cost model, Gather vs Gather Merge, and why Workers Launched says zero.