Hi Tanmay,

Thanks, this is very helpful.


The field ID point makes sense. If we move forward with this design, we will 
avoid relying on a name-based mapping and revise it to use Iceberg field IDs 
instead.

One distinction we wanted to clarify is the pruning layer. We already have 
file-level spatial pruning in our planner using existing partition information. 
The main reason we are considering an explicit bbox covering column is to 
improve performance below the file level, especially for row-level prefiltering 
before evaluating exact geometry predicates.

We have seen row-group-level filtering mentioned in prior discussions, but we 
have not found much discussion around row-level bbox prefiltering or 
executor-side predicate rewrites using an associated bbox column.

If you are aware of any prior discussion or planned direction around that 
layer, pointers would be very helpful.


Thanks again,
Min


-----Original Message-----
From: "Tanmay Rauth" <[email protected]>
To: <[email protected]>;
Cc:
Sent: 2026-07-04 (토) 09:53:39 (UTC+09:00)
Subject: Re: [DISCUSS] Declaring row-level bbox covering columns in Iceberg 
metadata


Hi Min,


Thanks for raising this, spatial pruning is worth getting right while the geo 
types are still young in v3.


On Q1: there's no Iceberg-native "column X is the bbox covering for column Y" 
mechanism today. The native direction is different, the v3 spec defines 
bounding-box bounds for the geometry/geography columns themselves (the "Bounds 
for Geometry and Geography" section, stored as the geo_lower/geo_upper stat 
structs), and the plumbing is actively landing: Conversions already serializes 
geospatial bounds, and the API has bounding-box types plus an intersects 
evaluator (#12667). So the intended long-term path is pruning from the geometry 
column's own bounds, not a side column.


The key caveat is that this native path doesn't appear to be functional 
end-to-end yet. As of current main, the metrics path deliberately skips 
producing geometry/geography bounds, #16850 has ParquetMetrics emit counts only 
for  those types, since Parquet's lexicographic WKB min/max isn't meaningful, 
and as far as I can tell I don't see any spatial predicate or geo-bound-based 
pruning wired into the scan-planning/expression layer. Given that, your 
covering-column idea is a reasonable interim: a struct<xmin,ymin,xmax,ymax> of 
doubles gets ordinary min/max metrics and prunes via the numeric predicate 
pushdown Iceberg already supports, which is exactly the leverage GeoParquet's 
bbox covering exploits. The thing I'd flag is that it overlaps with where 
native geo bounds are clearly headed, so I'd design it to converge with that 
mechanism rather than as a permanent parallel convention. And honestly, given 
how fast this area is moving (WKB read/write and Spark geo types landed just 
this week), it may be higher-leverage to help push the native path, producing 
geo bounds and wiring the existing intersects evaluator into manifest/scan 
evaluation, than to build a separate covering convention. Worth pulling in the 
folks driving the geo work to confirm the current state and direction.


One correctness point regardless of route: the spec gives geography bounds 
antimeridian semantics where xmin may be greater than xmax (an OR match across 
the ±180 seam). A hand-rolled bbox pruned via ordinary min/max stats treats 
that as a normal interval and would prune incorrectly near the dateline, so a 
covering column would need to special-case geography.


On Q2's shape: Iceberg identifies columns by field ID, not name, so a 
name-keyed property like "geo.geom.covering.bbox": "geom_bbox" is brittle under 
rename/reorder. If a declared relationship is needed, anchoring it to field IDs 
fits the format better.


On Q4/Q5: native Parquet GEOMETRY/GEOGRAPHY logical types and GeoParquet's 
file-level geo metadata are separate conventions, so writer-side geo emission 
is its own question; I'm not aware of an existing covering-column proposal,  
and #12667 plus the geo-bounds spec work are the prior art I'd anchor on.


Net: reasonable as an interim while native geo-bound pruning doesn't appear to 
be available yet, but I'd coordinate it with that native path so it doesn't 
become a competing convention.


Thanks,
Tanmay Rauth


On Tue, Jun 30, 2026 at 11:43 PM 이선민 (Sunmin Lee) <[email protected]> 
wrote:
Hi everyone,

We are considering a design in which a separate bbox column is stored alongside 
a geometry column, similar to the GeoParquet 1.1 bbox covering pattern:

geom:      geometry
geom_bbox: struct<
  xmin: double,
  ymin: double,
  xmax: double,
  ymax: double
>

We would use `geom_bbox` as the row-level bbox covering for `geom`.

We are interested in thoughts on the following approach:

1. Is there already an Iceberg-native mechanism for declaring that one column 
is the bbox covering for a geometry or geography column?

2. If not, would a table property be a reasonable way to declare this 
relationship?
For example:
"geo.geom.covering.bbox": "geom_bbox"

3. If a table property is a reasonable direction, is there a preferred naming 
convention or value format? In particular, would it make sense to follow the 
relevant GeoParquet 1.1 `covering.bbox` semantics and field-path format?

4. When writing native Parquet `GEOMETRY` / `GEOGRAPHY` logical types, would it 
make sense to also write GeoParquet 1.1 `geo` metadata so that existing 
GeoParquet readers can discover the bbox covering column?

5. Are there any existing discussions or proposals related to row-level 
geometry covering columns, metadata mappings, or planner support for rewriting 
or pushing down geometry predicates through an associated bbox covering column?

We are mainly trying to understand whether this looks like a reasonable 
direction, and whether there are existing conventions or prior work that we 
should align with.

Thanks,
Min

Reply via email to