morningman opened a new pull request, #69076:
URL: https://github.com/apache/doris/pull/69076

   ### What problem does this PR solve?
   
   Issue Number: None
   
   Related PR: #59487
   
   Problem Summary:
   
   **In short.** The Iceberg `rewrite_manifests` procedure committed a snapshot 
without rewriting any manifest, and still reported every targeted manifest as 
rewritten. This PR clusters the data files by their first partition field, so 
the rewrite actually merges manifests, and returns the numbers of manifests it 
replaced and wrote. A unit test written for #68902 turned this up; branch-4.2 
has the same code.
   
   **Background.** `ALTER TABLE ... EXECUTE rewrite_manifests(['spec_id' = 
...])` runs `RewriteManifestExecutor` on Iceberg's `RewriteManifests` API and 
returns `rewritten_manifests_count` and `added_manifests_count`. That API 
merges manifests only when a cluster function is set with `clusterBy`. Without 
one, `BaseRewriteManifests.requiresRewrite` returns false and the commit keeps 
every current manifest as it is.
   
   **The problem, and what it cost.** The executor never set a cluster 
function, so the procedure changed nothing while reporting that it had. On a 
local single-BE cluster with a file:// Iceberg hadoop catalog:
   
   | Table | master | with this PR |
   |---|---|---|
   | Unpartitioned, three INSERTs (3 manifests) | `[3, 0]`, still 3 manifests | 
`[3, 1]`, 1 manifest |
   | Partitioned by `(a, b)`, four INSERTs into `(1, x)`, `(1, y)`, `(2, x)`, 
`(2, y)` (4 manifests) | `[4, 0]`, still 4 manifests | `[4, 2]`, 2 manifests, 
one per value of `a` |
   | One INSERT (1 small manifest) | `[1, 0]`, plus a new snapshot that changes 
nothing | `[0, 0]`, no new snapshot |
   
   Running the procedure to compact metadata never reduced the number of 
manifests. Every run on a table with one manifest also added a snapshot.
   
   **How this PR fixes it.**
   
   - **Clustering.** The executor sets `clusterBy` to the value of the data 
file's first partition field, as Trino's `optimize_manifests` does. A 
multi-field partition is grouped by its first field only, so the rewrite does 
not write one manifest per partition, and an unpartitioned table is one group. 
Iceberg rolls each group over at `commit.manifest.target-size-bytes` (8 MB by 
default). The key is the value that `PartitionData` returns rather than the 
partition object, wrapped in a list because Iceberg rejects a null key, so a 
NULL first partition value forms its own group.
   - **Single small manifest.** As in Spark's `RewriteManifestsSparkAction` and 
in Trino, a single targeted manifest smaller than the target size is left 
alone: nothing is committed and the result is `[0, 0]`.
   - **Counts.** `rewritten_manifests_count` is now the number of targeted 
manifests that the rewrite replaced, and `added_manifests_count` the number of 
manifests it wrote: the difference between the manifest lists before and after 
the commit.
   - `spec_id` still limits the rewrite to the manifests of one spec, and 
delete manifests are kept as they are, as Iceberg's rewrite does.
   
   Spark's action instead sorts every entry by partition and splits the entries 
into `ceil(total size / target size)` manifests. In Spark that sort is 
distributed, but here the FE would have to read every entry into memory first, 
so this PR uses Iceberg's streaming cluster function, as Trino does. As with 
Trino, a rewrite produces at least one manifest per value of the first 
partition field, so a table with many such values but few manifests can end up 
with more manifests than before.
   
   **Results.**
   
   - **FE UT.** Five cases in `IcebergRewriteManifestsActionTest` fail on 
master and pass with this PR:
     - three appends become one manifest, `[3, 1]`;
     - a two-field partition is clustered by its first field, `[4, 2]`;
     - two partitions that one commit wrote into the same manifest are split by 
value, `[2, 2]`;
     - a NULL first partition value gets its own manifest, `[3, 2]`;
     - a single small manifest is left alone, `[0, 0]`, with no new snapshot.
   
     On master the first four return `[N, 0]` and the last returns `[1, 0]`. 
Keying by the partition object as Trino does fails the NULL case (`Key cannot 
be null`). All 113 tests under `org.apache.doris.connector.iceberg.action` and 
the `IcebergProcedureOps` tests pass.
   - **End to end.** The table above was produced on a local cluster. After the 
rewrite, the three tables still return 3, 4 and 1 rows.
   - **Regression.** `test_iceberg_rewrite_manifests` is unchanged. Its `.out` 
records only data rows, and its count checks still hold with the new counts: at 
least one manifest rewritten, no more added than rewritten, no more manifests 
after than before, and the exact rewritten count for `spec_id = 0`. The docker 
environment was not running locally, so it was not run here.
   
   ### Release note
   
   Iceberg `rewrite_manifests` now merges manifests, clustered by the first 
partition field, and returns the numbers of manifests it actually replaced and 
wrote. A table with a single manifest smaller than 
`commit.manifest.target-size-bytes` is left unchanged.
   
   ### Check List (For Author)
   
   - Test <!-- At least one of them must be included. -->
       - [ ] Regression test
       - [x] Unit Test
           - `IcebergRewriteManifestsActionTest`: the five cases above, which 
fail on master; all 113 tests under `org.apache.doris.connector.iceberg.action` 
and the `IcebergProcedureOps` tests pass.
       - [x] Manual test (add detailed scripts or steps below)
           - Local single-BE cluster with a file:// Iceberg hadoop catalog: the 
three tables in the table above, before and after this change.
       - [ ] No need to test or manual test. Explain why:
           - [ ] This is a refactor/code format and no logic has been changed.
           - [ ] Previous test can cover this change.
           - [ ] No code files have been changed.
           - [ ] Other reason <!-- Add your reason?  -->
   
   - Behavior changed:
       - [ ] No.
       - [x] Yes. <!-- Explain the behavior change -->
           - `rewrite_manifests` rewrites manifests, clustered by the first 
partition field, and reports the manifests it replaced and wrote; a single 
small manifest is left alone instead of being committed as a new snapshot.
   
   - Does this need documentation?
       - [x] No.
       - [ ] Yes. <!-- Add document PR link here. eg: 
https://github.com/apache/doris-website/pull/1214 -->
   
   ### Check List (For Reviewer who merge this PR)
   
   - [ ] Confirm the release note
   - [ ] Confirm test cases
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to