The list query no longer loads the article
News, notes, and cases store three HTML bodies in JSON. The grid needs titles and excerpts. It does not need the article.
Each news row keeps title, excerpt, and body as JSON with en, ru, and de. The public list used to select the row. Fifty articles pulled about 1.2 MB of HTML into the InnoDB buffer pool. The JSON API then threw most of it away before the response left PHP. The grid never printed a body.
The list query now asks for id, category, title, excerpt, image, size, dates, and sort. Body stays on the detail query. The same split landed on notes and cases. One pattern, three resources.
The index
Public lists filter is_published and order by sort_order or published_at. One composite index covers that in the right column order. Two indexes that duplicated the leading columns came off. They cost writes and gave nothing back.
Plan checks belong on production scale. On a small seed table MySQL picks a scan and looks healthy. The flip to a full scan is a row count, not a guess in development.
What Vue SSR stopped waiting on
The SSR grid no longer waits on a blob it never prints. Detail pages did not get slower in a way you can see. If they do, that is the one query worth caching, by id, with a TTL that dies on an admin save.
JSON is the admin format. The list path reads a short row. The article path reads the body. Mixing them was convenient and expensive.
