Implement truncate transform#766
Conversation
|
Thanks for the PR! |
|
Thanks for the feedback! How would you recommend testing manifest-level pruning? Looking at the tests in #737, it looks like they only verify the result of the query, and so would have passed even before bucket partition filtering was added. Or have I misunderstood the tests? |
|
I believe they check the amount of logged parquet files that are scanned, which is affected by file pruning query I
select count(distinct request.url) from duckdb_logs_parsed('HTTP') where request.url like '%.parquet';
----
6But you can also look at query I
select count(*) FROM duckdb_logs() where type = 'Iceberg' and message.contains('data_file')
----
4Which originates from here: // Check whether current data file is filtered out.
if (!table_filters.filters.empty() && !FileMatchesFilter(manifest_entry, IcebergDataFileType::DATA)) {
DUCKDB_LOG(context, IcebergLogType, "Iceberg Filter Pushdown, skipped 'data_file': '%s'",
data_file.file_path);
//! Skip this file
continue;
}There is also a query I
select count(*) FROM duckdb_logs() where type = 'Iceberg' and message.contains('manifest_file')
----
4Comes from here: if (!ManifestMatchesFilter(manifest_file)) {
DUCKDB_LOG(context, IcebergLogType, "Iceberg Filter Pushdown, skipped 'manifest_file': '%s'",
manifest_file.manifest_path);
//! Skip this manifest
continue;
} |
Note that we partition on a nested field to ensure that manifest-level filtering on TruncateTransform is the only way to prune a file from a scan. Filters on top-level columns will fall back to the column bounds in the manifest.
|
Tests were a good idea, and now implemented for integers, binary, and varchar. I also added a test generator for decimal data in eaaa2c5, but no test as yet, as reading the produced table with iceberg_scan results in: That appears to be triggered by an attempt to deserialize the partition key in the manifest, but I have no idea where that actually happens or how to fix it. Edit: this appears to happen because the partition type is written verbatim into the manifest schema: duckdb-iceberg/src/iceberg_manifest.cpp Line 70 in 5bbc6db and something else (duckdb-avro?) chokes on it. I can work around it for this specific case by replacing the partition type with the known serialized type ( STRUCT(r1000 BLOB)) in this specific case, but obviously that's not a solution.
|
Test generator currently produces a table that duckdb can't read.
eaaa2c5 to
50a8826
Compare
|
Your issue might be fixed as part of #744 |
iceberg_scan can't actually read manifests created with truncate(decimal) partitioning, but will be able to after duckdb#744
* use duckdb-iceberg from duckdb/duckdb-iceberg#766 * Explicitly install and load extensions in test setup
and tests for same. I'm not a huge fan of the way this is implemented (copying a potentially deeply nested filter expression and then replacing any StructExtracts with their direct children), but I can't think of a better way to support arbitrarily complex range selections at the moment. Suggestions welcome!
d04d3d5 to
c31e003
Compare
Retain parts of conjunction filters targeting the partition column, rather than dropping the whole filter if any part is unrelated.
Revert "Add primitive support for conjunction filters" This reverts commit 9584122. This reverts commit c31e003. Better implementation in duckdb#820
Tmonster
left a comment
There was a problem hiding this comment.
Thanks! looks really good to me. Can we also add a test where we make sure DuckDB can still correctly read a truncated table with no filters?
I think this is implicit in the first 2 assertions of all the new tests, e.g. https://github.com/duckdb/duckdb-iceberg/pull/766/changes#diff-6766e54322ca7bee8e0c361ec8dc79aeb08a115b99731d0e64426891c5e4337eR13-R16, no? Fun fact: these tests also pass against the head of #820, as for the truncate transform there's only one edge case where the difference between partition and range pruning is observable, namely BETWEEN with an upper bound exactly at the partition boundary. I'm loath to add that case, though, because it will break if #820 is merged. Actually testing whether the file pruned by partition or range would likely require #780. |
Tmonster
left a comment
There was a problem hiding this comment.
Thanks!
Sorry, must have missed that. Looks like the scans are tested.
I had one more comment about the placement of the files, but forgot to include it in my review.
| require iceberg | ||
|
|
||
| require-env DUCKDB_ICEBERG_HAVE_GENERATED_DATA | ||
|
|
There was a problem hiding this comment.
You can move the test files to test/sql/local/irc_any_catalog/reads/partitioned_reads. We have a test config that will automatically attach a catalog with the generated spark tables
There was a problem hiding this comment.
Can do. Currently these tests just use iceberg_scan; should they use an attached catalog instead?
There was a problem hiding this comment.
yea that would be great thanks 🙏
|
Thanks! |
I've been thoroughly enjoying the iceberg extension, but now find myself needing to partition my dataset on integer-valued columns. The extension handles this gracefully if inefficiently at the moment, simply matching all partitions based on unimplemented transforms, and kicking the filtering down to the parquet scan.
This PR adds support for the truncate transform, allowing iceberg_scan to prune partitions created with
truncateat the manifest level. Truncate is defined (and implemented here) for int, long, decimal, bytes, and string types. All other types raise an error.New sqllogic tests verify that scans return the correct results, and also skip files as intended.
It should be noted that
iceberg_scancan't actually read tables truncated-partitioned on decimal fields, but will be able to after #744.