State plainly that TimescaleDB leads the cross-engine table - #381
Conversation
The narrative I wrote for commandprompt#377 read more favourably than the numbers support, and one claim rested on a competitor crash. TimescaleDB is faster than pgColumnar on every query it completes: 1.6x on q4 and q5, 2.1x on q8, 2.7x on q7, 6.5x on q6, and 101x, 442x and 679x on q1, q2 and q3. The page did not say so. It said TimescaleDB "leads every query that filters one host", which is true and reads as though the rest were even. The claim that pgColumnar "leads the wide aggregate shapes with workers" was technically true and misleading. pgColumnar is first on q5 and q6 at four workers because TimescaleDB's parallel arm fails on this host. In serial, where TimescaleDB runs, it is ahead on both. The method section disclosed the failure; the paragraph making the claim did not repeat it, and that is where a reader forms the impression. The setup list said pgColumnar's storage is "in load order, which is time ascending". It is not. Measured correlation with physical order is 0.013 for time and -0.004 for hostname, so neither key is sorted. That last fact is also the explanation, which the page did not give. Measured on q2: 667 of 667 row groups read, none removed by filter, 99,995,680 rows filtered to return 4,320. Every stripe holds all 4,000 hosts, so each group's hostname minimum and maximum covers the whole set and no group can be skipped. TimescaleDB excludes all but one chunk on time and reads one hostname segment through an index, in about 2 ms. So the table measures pgColumnar in the layout that suits it least, and now says so. A user with this query shape would cluster on hostname, which is what segmentby does for TimescaleDB. That configuration is not measured, and the page now asks the reader not to treat the q1 to q3 gap as a property of columnar storage until it is. No numbers changed. This is the reading of them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
jdatcmd
left a comment
There was a problem hiding this comment.
Approved. I verified the three corrections on the bench rather than taking them.
This is the right call and it matters more than usual, because the 1.0-alpha release
notes link to this page.
Claim 3, the factual error, confirmed. The setup list said storage is "in load
order, which is time ascending". From pg_stats on cpu_pgc:
time correlation = 0.0133
hostname correlation = -0.0036
Neither key is sorted. The old sentence was not imprecise, it was wrong, and it was
the sentence a reader would have used to reason about why q1-q3 are slow.
The mechanism, confirmed. Ran q2 with EXPLAIN (ANALYZE) on the bench:
Columnar Chunk Groups Total: 667
Columnar Chunk Groups Read: 667
Columnar Chunk Groups Removed by Filter: 0
Columnar Vectors Skipped: 0
Rows Removed by Filter: 99995680
667 of 667 read, nothing skipped at either granularity, 99,995,680 rows filtered to
return 4,320. Exactly as the page now says.
Every multiplier checks out against the table: q1 403/4 = 101, q2 2,211/5 = 442,
q3 4,071/6 = 679, q4 1.60, q5 1.62, q6 6.46, q7 2.65, q8 2.09. All eight round to
what the prose claims.
One slip, and it is the kind this PR exists to catch
TimescaleDB answers the same query in about 2 milliseconds.
The table in the same file says 5 ms for q2, and the 442x figure depends on 5.
There is no 2 ms cell anywhere in that row; the closest is q1 at 4.
I am fixing it to 5 on merge rather than sending this back for one word.
On the judgement
The part I would have got wrong is what you did not do: re-measure a clustered
pgColumnar table so the numbers look better. Saying "this table measures pgColumnar in
the layout that suits it least, that configuration is not measured here, do not read
the gap as a property of columnar storage until it is" is harder to write and is the
honest version. A benchmark page that quietly picks the flattering layout is how
benchmark pages lose their value.
Same for putting TimescaleDB's parallel failure in the paragraph that makes the
claim rather than only in the method. A reader forms the impression at the claim.
The CI red was the Install PostgreSQL 18 step timing out at exit 124, the
package-fetch flake #352 addressed; it cleared on rerun. That is its fifth occurrence
today and probably deserves its own issue.
Merging.
What
The narrative I wrote for #377 read more favourably than the numbers support. This
corrects the reading. No number changes.
Raised by jd looking at the merged table and asking whether pgColumnar is considerably
slower. It is, and the page did not say so.
Three things were wrong
1. The page never stated the headline result. TimescaleDB is faster than
pgColumnar on every query it completes:
The page said TimescaleDB "leads every query that filters one host" — true, and it
reads as though the rest were close. Against heap we win q4/q5/q6/q8 by 20-50% and
lose the other four.
2. One claim rested on a competitor's crash. "pgColumnar leads the wide aggregate
shapes with workers... first on both" is true at P=4 only because TimescaleDB's
parallel arm fails on this host. In serial, where it runs, it beats us on both q5 and
q6. The method section disclosed the failure; the paragraph making the claim did not
repeat it, and that is where a reader forms the impression.
3. A factual error in the setup list. It said pgColumnar's storage is "in load
order, which is time ascending". It is not: measured correlation with physical order is
0.013 for
timeand -0.004 forhostname. Neither key is sorted.And that third point is the explanation, which was missing
Measured on q2 with
EXPLAIN (ANALYZE):Zero groups skipped. It reads all 667 and filters 99,995,680 rows to return 4,320.
The zone maps cannot help because every stripe holds all 4,000 hosts, so each group's
hostnamemin/max covers the whole set. TimescaleDB answers the same query in ~2 ms byexcluding all but one chunk on time, then reading one
hostnamesegment through anindex.
What I did not do
I did not re-measure a clustered pgColumnar table to make the numbers look better.
The page now says the table measures pgColumnar in the layout that suits it least, that
a user with this shape would cluster on
hostname(whatsegmentbydoes forTimescaleDB), that the configuration is unmeasured, and that the q1-q3 gap should not be
read as a property of columnar storage until it is.
Measuring the clustered variant is worth doing and belongs in its own change, with its
own method, rather than folded into a correction of my own framing.
test/ste_check.pypasses on every user-facing document.Conflict note
#380 also touches
docs/benchmarks.md. If that merges first I will rebase; the changesare in different parts of the file.
🤖 Generated with Claude Code