What
src/columnar_metadata.c makes 44 systable_beginscan calls. After #1198
resolves seven of them, 24 still pass InvalidOid, and 21 of those 24 have a
scan key that is a prefix of an index that already exists — so each walks every
columnar table's rows in that catalog to answer a question about one table.
#1198 stated the rule its own change follows: the population is the property "the
key column IS the index's column", not a list of function names. This issue is
the rest of that population.
The 21
Line numbers are on 6cb9f9a so the counts can be checked rather than believed.
| catalog |
key columns |
index it is a prefix of |
sites |
lines |
free_space |
storage_id |
free_space_pkey (storage_id, file_offset) |
6 |
747, 903, 1041, 1102, 1147, 1315 |
storage |
storage_id |
storage_pkey (storage_id) |
6 |
1896, 1934, 1966, 2256, 2328, 2399 |
projection_declaration |
rel |
projection_declaration_pkey (rel, name) |
4 |
3699, 3840, 3915, 3955 |
row_group |
storage_id |
row_group_pkey (storage_id, group_number) |
3 |
488, 567, 1020 |
row_group |
storage_id, group_number |
row_group_pkey exactly |
2 |
671, 1596 |
6 + 6 + 4 + 3 + 2 = 21.
The other three InvalidOid sites are not in the list: storage.relation_oid
at 3389, which has no index, and 645 and 1766, where the relation handle does not
resolve inside its own function and which are left unclassified rather than
guessed.
How it was derived, and why the method is the point
The relation handle is the ground truth. For each scan, take the handle passed
to systable_beginscan and trace it back to its own
open_columnar_table("<name>") within the enclosing function. Then collect that
scan's ScanKeyInit(&key[N], Anum_...) statements, ordered by N, stopping at
the previous systable_beginscan.
Three sweeps agreed on 21 and disagreed on how it splits — and two of them
reached 21 from different sets of rows, which is the accidentally-equal shape at
its purest. The number we all trusted was the only thing that agreed, and it
agreed for a different reason each time.
The discriminating site is 1041. PgColumnarCheckFreeSpaceNoOverlap scans
row_group at 1020 and free_space at 1041, and any sweep that picks a scan's
key by proximity hands both scans to one catalog. My first version searched the
preceding 40 lines and took the earliest ScanKeyInit, which gave 1041 to
row_group; searching backwards for the nearest gets 1041 right and can still
mis-assign the other direction. Only the handle settles it.
Two further traps this sweep had to survive, both caught by @jdatcmd:
native_storage is not a table. pgcolumnar--1.0-alpha5.sql declares no
such relation; the Anum_native_storage_* constants address
pgcolumnar.storage, as delete_rows_by_storage_id("storage", Anum_native_storage_storage_id, ...) shows. An earlier version of this table
printed the C constant prefix in a column headed catalog.
- A count of the string is not a count of the calls.
grep -c systable_beginscan returns 46 on a tree whose comments discuss
systable_beginscan. The call count is 44.
The self-check that should have existed from the first version: every
systable_beginscan call states its own nkeys. Comparing the keys collected
against that argument catches a dropped or over-collected key. On the table above
it reports 0 mismatches across all 24 sites.
What this issue does NOT claim
None of the 21 is measured, so none is called a defect. #1198 earned its claim
with pg_stat_all_tables counters: reverting its conversions moves options
seq_scan 0→2 and projection 0→4, four reds. Nothing equivalent has been run
for these. Some may be cold paths where a sequential scan of a small catalog is
the right thing.
Suggested next step
One catalog at a time, and establish the cost before the conversion — the
pg_stat_reset() / pg_stat_force_next_flush() probe in
test/catalog_plan_index.sh is the seam that answers it. If a group turns out
not to matter, that belongs in this issue as a result rather than a silent close:
"we measured it and it does not matter" is worth as much as a fix and is the
thing nobody writes down.
What
src/columnar_metadata.cmakes 44systable_beginscancalls. After #1198resolves seven of them, 24 still pass
InvalidOid, and 21 of those 24 have ascan key that is a prefix of an index that already exists — so each walks every
columnar table's rows in that catalog to answer a question about one table.
#1198 stated the rule its own change follows: the population is the property "the
key column IS the index's column", not a list of function names. This issue is
the rest of that population.
The 21
Line numbers are on
6cb9f9aso the counts can be checked rather than believed.free_spacestorage_idfree_space_pkey (storage_id, file_offset)storagestorage_idstorage_pkey (storage_id)projection_declarationrelprojection_declaration_pkey (rel, name)row_groupstorage_idrow_group_pkey (storage_id, group_number)row_groupstorage_id, group_numberrow_group_pkeyexactly6 + 6 + 4 + 3 + 2 = 21.
The other three
InvalidOidsites are not in the list:storage.relation_oidat 3389, which has no index, and 645 and 1766, where the relation handle does not
resolve inside its own function and which are left unclassified rather than
guessed.
How it was derived, and why the method is the point
The relation handle is the ground truth. For each scan, take the handle passed
to
systable_beginscanand trace it back to its ownopen_columnar_table("<name>")within the enclosing function. Then collect thatscan's
ScanKeyInit(&key[N], Anum_...)statements, ordered byN, stopping atthe previous
systable_beginscan.Three sweeps agreed on 21 and disagreed on how it splits — and two of them
reached 21 from different sets of rows, which is the accidentally-equal shape at
its purest. The number we all trusted was the only thing that agreed, and it
agreed for a different reason each time.
The discriminating site is 1041.
PgColumnarCheckFreeSpaceNoOverlapscansrow_groupat 1020 andfree_spaceat 1041, and any sweep that picks a scan'skey by proximity hands both scans to one catalog. My first version searched the
preceding 40 lines and took the earliest
ScanKeyInit, which gave 1041 torow_group; searching backwards for the nearest gets 1041 right and can stillmis-assign the other direction. Only the handle settles it.
Two further traps this sweep had to survive, both caught by @jdatcmd:
native_storageis not a table.pgcolumnar--1.0-alpha5.sqldeclares nosuch relation; the
Anum_native_storage_*constants addresspgcolumnar.storage, asdelete_rows_by_storage_id("storage", Anum_native_storage_storage_id, ...)shows. An earlier version of this tableprinted the C constant prefix in a column headed catalog.
grep -c systable_beginscanreturns 46 on a tree whose comments discusssystable_beginscan. The call count is 44.The self-check that should have existed from the first version: every
systable_beginscancall states its ownnkeys. Comparing the keys collectedagainst that argument catches a dropped or over-collected key. On the table above
it reports 0 mismatches across all 24 sites.
What this issue does NOT claim
None of the 21 is measured, so none is called a defect. #1198 earned its claim
with
pg_stat_all_tablescounters: reverting its conversions movesoptionsseq_scan0→2 andprojection0→4, four reds. Nothing equivalent has been runfor these. Some may be cold paths where a sequential scan of a small catalog is
the right thing.
Suggested next step
One catalog at a time, and establish the cost before the conversion — the
pg_stat_reset()/pg_stat_force_next_flush()probe intest/catalog_plan_index.shis the seam that answers it. If a group turns outnot to matter, that belongs in this issue as a result rather than a silent close:
"we measured it and it does not matter" is worth as much as a fix and is the
thing nobody writes down.