Skip to content

Store extended statistics filename in Delta Lake CommitInfoEntry#29099

Open
chenjian2664 wants to merge 10 commits intotrinodb:masterfrom
chenjian2664:jack/extend-stats-delta-lake
Open

Store extended statistics filename in Delta Lake CommitInfoEntry#29099
chenjian2664 wants to merge 10 commits intotrinodb:masterfrom
chenjian2664:jack/extend-stats-delta-lake

Conversation

@chenjian2664
Copy link
Copy Markdown
Contributor

@chenjian2664 chenjian2664 commented Apr 14, 2026

Description

This change records the extended statistics filename in the commitInfo, when updating extended stats, we first write the statistics file, then leverage the commit log mechanism to handle concurrent conflicts - in other words it will allow the concurrent read/write if the log synchronizer support it.

This contribution ensures that there are unique stats files for each transaction log file (when the writing of the extended stats is enabled).

It is a fix for the existing flaky tests:

io.trino.testing.QueryFailedException: Failed to write Delta Lake transaction log entry
	at io.trino.testing.AbstractTestingTrinoClient.execute(AbstractTestingTrinoClient.java:138)
	at io.trino.testing.DistributedQueryRunner.executeInternal(DistributedQueryRunner.java:664)
	at io.trino.testing.DistributedQueryRunner.execute(DistributedQueryRunner.java:640)
	at io.trino.plugin.deltalake.TestDeltaLakeLocalConcurrentWritesTest.lambda$testConcurrentInsertsSelectingFromTheSameVersionedTable$2(TestDeltaLakeLocalConcurrentWritesTest.java:240)
	Suppressed: java.lang.Exception: SQL: INSERT INTO test_concurrent_inserts_select_from_same_versioned_table_jlty6w4qop SELECT 3, 'd' AS part FROM test_concurrent_inserts_select_from_same_versioned_table_jlty6w4qop FOR VERSION AS OF 0
Caused by: io.trino.spi.TrinoException: Failed to write Delta Lake transaction log entry
	at io.trino.plugin.deltalake.DeltaLakeMetadata.finishInsert(DeltaLakeMetadata.java:2696)
Caused by: io.trino.spi.TrinoException: Error reading statistics from cache
	at io.trino.plugin.deltalake.statistics.CachingExtendedStatisticsAccess.readExtendedStatistics(CachingExtendedStatisticsAccess.java:68)
	at io.trino.plugin.deltalake.DeltaLakeMetadata.updateTableStatistics(DeltaLakeMetadata.java:4818)
Caused by: java.lang.RuntimeException: Failed to decode JSON
	at io.trino.plugin.deltalake.statistics.MetaDirStatisticsAccess.decodeAndRethrowIfNotFound(MetaDirStatisticsAccess.java:142)
	at io.trino.plugin.deltalake.statistics.MetaDirStatisticsAccess.readExtendedStatistics(MetaDirStatisticsAccess.java:83)
Caused by: java.lang.IllegalArgumentException: Invalid JSON bytes for [simple type, class io.trino.plugin.deltalake.statistics.ExtendedStatistics]
	at io.airlift.json.JsonCodec.fromJson(JsonCodec.java:242)
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: No content to map due to end-of-input
 at [Source: REDACTED (StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION disabled); line: 1]

This is an alternative to #29006, but requires extensive modifications to the current implementation.

Design

According to the Delta Lake protocol specification:
https://github.com/delta-io/delta/blob/master/PROTOCOL.md#commit-provenance-information

Implementations are free to store any valid JSON-formatted data via the commitInfo action.

The commitInfo action is therefore the most appropriate place to persist additional metadata during a commit.
In Trino, the CommitInfoEntry is written for every data modification operation. This makes it a natural integration point for recording extended statistics. In contrast, MetadataEntry and ProtocolEntry are not suitable for this purpose, as they are intended for schema or protocol changes and should not be rewritten on every commit solely to update statistics.

The write flow for extended statistics follows the same pattern as data file writes:

  • First, write the statistics file.
  • Then, include the generated file path in the CommitInfoEntry.
    • Finally, rely on the commit mechanism to handle conflict resolution in concurrent scenarios.

Review

For reviewers:

  • Commits 1–7 primarily focus on code cleanup. They also expose CommitInfo via DeltaLakeMetadata#getTableHandle and cache it within TableSnapshot.
  • Commit 8 introduces the core change that persisting the extended statistics file path in CommitInfo.

Limitation

Concurrency guarantees

Conflict resolution is bounded by the capabilities of the underlying log synchronizer. In multi-cluster (e.g., cloud) deployments, this support is limited and depends on the guarantees provided by the underlying storage system.

Engine-specific visibility

Extended statistics are Trino-specific. When a table is written by other engines, these statistics will not be updated or recognized, which may lead to stale statistics being used by Trino.

Fixes:

Fixes #21725
Fixes #22455
Fixes #12032
Fixes #16088
Fixes #29064

Additional context and related issues

Release notes

(x) This is not user-visible or is docs only, and no release notes are required.

@cla-bot cla-bot Bot added the cla-signed label Apr 14, 2026
@github-actions github-actions Bot added the delta-lake Delta Lake connector label Apr 14, 2026
@chenjian2664 chenjian2664 force-pushed the jack/extend-stats-delta-lake branch from 41553dc to dca45cc Compare April 14, 2026 04:50
@chenjian2664 chenjian2664 requested review from homar and pajaks April 14, 2026 04:54
@chenjian2664 chenjian2664 force-pushed the jack/extend-stats-delta-lake branch from dca45cc to f617dae Compare April 14, 2026 08:55
@@ -212,7 +213,7 @@ public TableStatistics getTableStatistics(ConnectorSession session, DeltaLakeTab

Optional<ExtendedStatistics> statistics = Optional.empty();
if (isExtendedStatisticsEnabled(session)) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm missing integration test coverage for this new development

we should cover situations where a commit does extended stats writing and does not write extended stats, but they are retrieved nevertheless.

also vacuuming doesn't seem to be covered in the integration tests.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please elaborate more about "commit extended stats but not write"?

Simplify the code by adding a Builder to MetadataAndProtocolEntries to
incrementally collect `MetadataEntry` and `ProtocolEntry`.
Avoid multiple traversals of transaction log entries by using
`getMetadataAndProtocolEntry` to retrieve both metadata and protocol
entries in a single pass, instead of fetching them individually and
scanning the log multiple times.
Previously, extended statistics were always written to a fixed path
 (`_delta_log/_trino_meta/extended_stats.json`), which made updates
non-atomic with respect to the transaction log: a crash between writing
 the stats file and committing the transaction could leave stale or
  inconsistent statistics visible to readers.
This change records the extended statistics filename in the `commitInfo`,
when updating extended stats, we first write the statistics file, then leverage
the commit log mechanism to handle concurrent conflicts.
@chenjian2664 chenjian2664 force-pushed the jack/extend-stats-delta-lake branch from fa1d083 to 1857e83 Compare April 17, 2026 00:55
@chenjian2664
Copy link
Copy Markdown
Contributor Author

@findepi Would you mind to take a look when you are available :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed delta-lake Delta Lake connector

2 participants