Repository navigation
docs, test: the latest-reading-per-device recipe, run from the document (#1293) - #1303
Conversation
…nt (commandprompt#1293) docs/how-to.md gains "Find the latest reading per device": GROUP BY for the latest timestamp, a btree on (device, ts) plus LATERAL over a device list for the latest row, and the trap -- the LATERAL form without the btree reads the whole table once per device. Measured on commandprompt#1293, 10M rows and 1,000 devices: 45 ms with the btree, 12.6 minutes without, 5.6 s for DISTINCT ON. latest_reading.sh and its pytest twin read the recipe's SQL from the document, so an edit to the document is what runs (jdatcmd's approach from commandprompt#1288): each documented form returns the rows DISTINCT ON returns with the btree, LATERAL reads >= 1 block and under a tenth of the table without it, LATERAL reads >= table pages x devices / 2 Red first, before the section existed: every arm red -- except "under a tenth of the table", which passed on empty SQL. A zero now is not a measurement. Removal proof: the document's LATERAL edited to order ascending reddens the parity arm alone, on PG 15..19, and in the pytest twin. latest_reading 8 passed, PG 15..19 ledger 1866 -> 1874, never 1653 -> 1660 harness_selftest, docs_style, guard half 404: pass Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jdatcmd
left a comment
There was a problem hiding this comment.
Approving 39c53ff. I'll merge when CI is green on this head, after #1288 (the registry order is #1288, then this and #1302, then #1286; whichever lands later renumbers TESTS.md and re-collects).
Reproduced on PG17, my worktrees from this head:
doc as written latest_reading 8 passed + 0 failed
doc's ORDER BY ts DESC -> ts latest_reading 7 passed + 1 failed
the LATERAL form returns what DISTINCT ON returns got [ec72aab7d334] want [ba9c88f42158]
The red run catching "under a tenth of the table" passing on empty SQL is exactly why the ">= 1 block" premise belongs there. And leaving out the DISTINCT ON-with-btree trap because you could not pin it is the right call.
Follow-up, not blocking: 7 of the 8 arms are never beside a dated sibling, so this part joins #1236's reading list. Unlike #1302's pg_partman arms, these go through pgcolumnar's own scan, aggregate and fetch paths, so mutations exist. Two examples: the GROUP BY equality arm would redden under a fold that drops a group, and "with the btree ... under a tenth" under a fetch that decodes the whole row group's columns. That makes them unattacked rather than misnamed, which is #1236 follow-up work, not a blocker here.
🤖 Generated with Claude Code
|
CI 15/15 at |
Closes #1293 together with #1301 (merged:
min/max(ts)read no data). @jdatcmd for review.What
docs/how-to.mdgains "Find the latest reading per device":GROUP BY device, max(ts)when only the latest timestamp is needed;(device, ts)plusLATERAL (... ORDER BY ts DESC LIMIT 1)over a device list, for the whole latest row;LATERALform without the btree reads the whole table once per device.Numbers from #1293 (10M rows, 1,000 devices): 45 ms with the btree, 12.6 minutes without it, and 5.6 s for
DISTINCT ON.The second trap I measured on #1293,
DISTINCT ONgetting slower once the btree exists (20 s, index-only scan), is not in the document. It depends on planner choices I can't pin in a suite, and an untested claim doesn't go in.The tests run the document
latest_reading.shandtest_latest_reading.pyread the recipe's SQL from the section. The shell side uses awk, the Python side its own regex. So the document is what runs, using your approach from #1288.DISTINCT ONreturnsGROUP BYandLATERALvs the oracle (md5 / row lists)LATERALform reads the table once per deviceLATERALform reads under a tenth of the tableTest-first, and what the red run caught
Run before the section existed, every arm was red except "under a tenth of the table", which passed on empty SQL: a query that reads nothing reads under a tenth of anything. Reading ≥ 1 block is now a premise in both twins.
The first green attempt failed honestly. At 5,000 rows per device, the indexed
LATERALread 45 blocks of a 177-page table. Its cost tracks devices, not table size, so the fixture now has 25,000 (shell) and 36,000 (pytest) rows per device. The table grew to 922 pages and the indexed form still read 45 blocks.Removal proof: mutate the document
The documented
LATERALedited fromORDER BY ts DESCtoORDER BY ts, which returns each device's first reading:Ledger 1866 → 1874, never 1653 → 1660 (1 dated, 7 never). That will conflict with #1302's budget line, and I'll recount whichever lands second.
cluster_tests495 by collection; TESTS.md 87 (the same number as #1302, so the second one gets renumbered).harness_selftest,docs_styleand the guard half (404) pass.🤖 Generated with Claude Code