Repository navigation
Conversation
Track stats tightness with a single file-level tight_stats flag on the tracked file instead of a per-column tight_bounds field. The flag covers all statistics (bounds and null, NaN, and value counts) for the file's live rows.
| When `tight_stats` is true: | ||
|
|
||
| * Counts are exact for all fields. | ||
| * Bounds are exact for fixed-width primitives and for `variant`. |
There was a problem hiding this comment.
do we consider the variant bounds to be exact?
There was a problem hiding this comment.
Good callout. I think variant is a bit different in the sense that some of the fields may not have stats, but any field level stats present has the same tightness guarantees. I will try to incorporate this.
| * Bounds are the minimum and maximum of the live values. | ||
| * `null_value_count` and `nan_value_count` are the counts across the live rows. | ||
|
|
||
| `value_count` and `total_bytes` are not part of tightness. `value_count` is the number of values across all rows written to the file and is not adjusted when rows are deleted; for a field with no repeated (`list` or `map`) ancestor, the live value count is `value_count` minus the deletion vector's cardinality. `total_bytes` is an estimate and is likewise not adjusted for deleted rows. |
There was a problem hiding this comment.
Verified against the implementation that computes the value_count:
value_countcounts every row, including rows where a parent struct is null- Parquet's per-column value count is one entry per row regardless of definition level, so a row whose parent struct is null still contributes to the leaf's value_count.
- Parquet marks a leaf null whenever its definition level is below max, which includes the case where an ancestor struct is null, so a null parent also increments the leaf's null_value_count.
Repeated (list/map) fields collect no stats at all
There was a problem hiding this comment.
So the derivation logic above to calculate value_count by subtracting dv cardinality is correct.
There was a problem hiding this comment.
Not spelled out here, but similarly non-null values can be calculated by value_count - dv_cardinality - null_count (assuming no repeated ancestors).
| - `column_files` may only be set if the tracked file is a data file or a v4 leaf manifest. | ||
| - A field ID may appear in `field_ids` of at most one column file in a tracked file's `column_files`. | ||
| - `tight_stats`: | ||
| - `tight_stats` may be true only if `content_stats` are tight; attaching or updating a `deletion_vector` without recomputing stats makes them no longer tight. See [Stats Tightness](#stats-tightness). |
There was a problem hiding this comment.
Do we need to mention a DV here? You don't necessarily need to recompute stats and getting into the nuance should be done in more detail below. I'd probably just remove that sentence.
|
|
||
| For `variant`, both bounds are unshredded `variant` that store variant field bounds by normalized JSON paths as field names. See [Bounds for Variant](#bounds-for-variant) for details on producing these bounds. | ||
|
|
||
| <a id="stats-tightness"></a> |
There was a problem hiding this comment.
Isn't this automatically generated by the heading on the next line?
There was a problem hiding this comment.
yeah we shouldn't need to generate this
There was a problem hiding this comment.
Looks like the anchor tag will be autogenerated for headings. I have removed it.
| <a id="stats-tightness"></a> | ||
| ###### Stats Tightness | ||
|
|
||
| Statistics are *tight* when they are exact for the live rows of a file: |
There was a problem hiding this comment.
When bounds, null count, and nan count are ...
Otherwise this is confusing for the other stats fields.
There was a problem hiding this comment.
Done. The definition now names them (bounds, null and NaN counts). The rest are clearly out.
| * Bounds are the minimum and maximum of the live values. | ||
| * `null_value_count` and `nan_value_count` are the counts across the live rows. | ||
|
|
||
| `value_count` and `total_bytes` are not part of tightness. `value_count` is the number of values across all rows written to the file and is not adjusted when rows are deleted; for a field with no repeated (`list` or `map`) ancestor, the live value count is `value_count` minus the deletion vector's cardinality. `total_bytes` is an estimate and is likewise not adjusted for deleted rows. |
There was a problem hiding this comment.
"Note that value_count is not included in tightness"
There was a problem hiding this comment.
We don't need to state that total bytes is excluded. We should take care of that with the definition of tightness that only mentions null and nan counts in addition to the bounds. All other fields are not tight and we can't require new ones to be included either.
There was a problem hiding this comment.
Done. Dropped the total_bytes sentence and reframed it as:
Statistics other than the bounds, null_value_count, and nan_value_count are not part of tightness.
|
|
||
| When `tight_stats` is true: | ||
|
|
||
| * `null_value_count` and `nan_value_count` are exact for the live rows. |
There was a problem hiding this comment.
This is restating the definition above and should be removed.
| When `tight_stats` is true: | ||
|
|
||
| * `null_value_count` and `nan_value_count` are exact for the live rows. | ||
| * Bounds are exact for primitive types other than `string` and `binary`, whose bounds may have been truncated when written. |
There was a problem hiding this comment.
I think this should also be part of the definition above. Bounds for string and binary fields are excluded and are never tight.
There was a problem hiding this comment.
Moved into the definition. I folded geo in there too, since it's the same kind of exception. Keeping it under the tight_stats was misleading.
| * `variant` bounds are stored per leaf field and are optional; a leaf field may have no bound, but any bound that is present is exact. | ||
| * `geometry` and `geography` bounds are a bounding box that contains the live values, not exact minimum and maximum values. | ||
|
|
||
| A `variant` value is null only when the variant itself is null; a non-null variant that encodes a variant null is not counted as a null value. Variants do not have a `nan_value_count`. |
There was a problem hiding this comment.
This is good. We don't need to specify that variants don't have a NaN count though.
There was a problem hiding this comment.
Thanks. I dropped the NaN-count line, kept the variant-null clause.
| - `column_files` may only be set if the tracked file is a data file or a v4 leaf manifest. | ||
| - A field ID may appear in `field_ids` of at most one column file in a tracked file's `column_files`. | ||
| - `tight_stats`: | ||
| - `tight_stats` may be true only if `content_stats` are tight. See [Stats Tightness](#stats-tightness). |
There was a problem hiding this comment.
This restates the description. I would remove it.
|
|
||
| ###### Stats Tightness | ||
|
|
||
| Statistics are *tight* when the bounds, `null_value_count`, and `nan_value_count` are exact for the live rows of a file: |
There was a problem hiding this comment.
Is the intent to use bold or italic? Most other places use _underscores_ for italic or **double asterisks** for bold.
|
|
||
| Statistics are *tight* when the bounds, `null_value_count`, and `nan_value_count` are exact for the live rows of a file: | ||
|
|
||
| * Bounds are the minimum and maximum of the live values. Bounds for `string` and `binary` are never tight because they may be truncated when written, and bounds for `geometry` and `geography` are a bounding box, not exact minimum and maximum values. |
There was a problem hiding this comment.
lower_boundandupper_boundfor fixed-width types are equal to the minimum and maximum live values
The second sentence should not be in the definition, it is a clarification that can come later. The idea is to be clear and direct and "fixed-width types" says what we need to. Leaving aside the specific cases makes this easier to understand.
|
|
||
| * Bounds are the minimum and maximum of the live values. Bounds for `string` and `binary` are never tight because they may be truncated when written, and bounds for `geometry` and `geography` are a bounding box, not exact minimum and maximum values. | ||
| * `variant` bounds are stored per leaf field and are optional; a leaf field may have no bound, but any bound that is present is exact. | ||
| * `null_value_count` and `nan_value_count` are the counts across the live rows. A `variant` value is null only when the variant itself is null; a non-null variant that encodes a variant null is not counted as a null value. |
There was a problem hiding this comment.
This should be the second bullet point.
Information about variant can be its own paragraph below. We don't need to bring exceptions in when defining what it means for bounds to be exact.
| Statistics are *tight* when the bounds, `null_value_count`, and `nan_value_count` are exact for the live rows of a file: | ||
|
|
||
| * Bounds are the minimum and maximum of the live values. Bounds for `string` and `binary` are never tight because they may be truncated when written, and bounds for `geometry` and `geography` are a bounding box, not exact minimum and maximum values. | ||
| * `variant` bounds are stored per leaf field and are optional; a leaf field may have no bound, but any bound that is present is exact. |
There was a problem hiding this comment.
Also move this to a separate paragraph about variants.
Track stats tightness with a single file-level
tight_statsflag on the tracked file instead of a per-columntight_bounds field. The flag covers all statistics (bounds andnull,NaN, and value counts) for the file's live rows.