From e16afa553aafb70157dfac477836b997391af426 Mon Sep 17 00:00:00 2001 From: ChronicallyJD Date: Sat, 25 Jul 2026 08:33:49 -0600 Subject: [PATCH] docs: record that ANALYZE collects no column statistics columnar_scan_analyze_next_block() and columnar_scan_analyze_next_tuple() both return false unconditionally, so ANALYZE on a columnar table samples zero rows and writes nothing to pg_statistic. It reports success, which makes this the one unsupported operation the user gets no signal about: TABLESAMPLE, whose callbacks sit next to these, raises through COLUMNAR_UNSUPPORTED instead. The planner's row count is unaffected because columnar_relation_estimate_size derives it from row-group metadata rather than from ANALYZE. What is lost is the per-column distribution, so predicates fall back to default selectivities. Documenting rather than changing behaviour: erroring would break autovacuum's periodic analyze, and a warning would be logged on every autoanalyze cycle. Implementing sampling properly is the real fix; this records the state until then. Co-Authored-By: Claude Opus 5 (1M context) --- docs/limitations.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/limitations.md b/docs/limitations.md index 9500a6b..3a34716 100644 --- a/docs/limitations.md +++ b/docs/limitations.md @@ -33,6 +33,28 @@ only. The rest of the extension runs on any architecture PostgreSQL supports. columns, which is proportional to rows times row group size and is not yet optimized. +## Planner statistics + +`ANALYZE` does not collect column statistics for a columnar table. It reports +success and leaves `pg_statistic` empty, so `pg_stats` shows no rows for the +table and autoanalyze has nothing to store either. + +The row count the planner uses is still accurate: it comes from row-group +metadata rather than from `ANALYZE`, so scan and join costs are sized correctly. +What is missing is everything `ANALYZE` would otherwise provide about the values +in a column: most-common values, histograms, distinct counts, null fraction and +average width. Predicates on a columnar table are therefore estimated with the +planner's defaults rather than from the data, which mostly shows up as poor +selectivity estimates for `WHERE` clauses and as join orders chosen from default +distinct counts. + +A table whose plans depend on those estimates is better served by keeping the +filtered columns in a heap table, or by checking `EXPLAIN` output rather than +assuming the planner knows the distribution. + +`TABLESAMPLE` is also unsupported, and unlike `ANALYZE` it says so: it raises an +error rather than returning no rows. + ## Vacuum and compaction - `VACUUM FULL` and `CLUSTER` are not supported on a columnar table; the