Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions fe/fe-core/src/main/java/org/apache/doris/catalog/MTMV.java
Original file line number Diff line number Diff line change
Expand Up @@ -255,8 +255,8 @@ public boolean isIvm() {
return getIvmInfo().isEnableIvm();
}

public long getNextRefreshVersion() {
return Config.isCloudMode() ? getNextVersion() : getIvmInfo().getRefreshVersion() + 1;
public long getNextSequencePrefix() {
return Config.isCloudMode() ? getNextVersion() : getIvmInfo().getSequencePrefix() + 1;
}

public boolean addTaskResult(AlterMTMV alterMTMV, boolean isReplay) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ __DORIS_IVM_ROW_ID_COL__ | k1 | cnt | sum_v1 | __DORIS_IVM_DML_FACTOR_COL__ | __

### Semantics

- **Read-only.** No insert transaction is built. Stream offsets, refresh version, and MV metadata
- **Read-only.** No insert transaction is built. Stream offsets, sequence prefix, and MV metadata

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.

Could you finish the terminology sweep? regression-test/plugins/plugin_planner.groovy:138 and regression-test/suites/mtmv_p0/ivm/test_ivm_refresh_dry_run.groovy:19 still say the sequence encodes a "refresh version", and the renamed transaction test still uses *_refresh_version_* fixture names. Since this refactor is specifically meant to remove that ambiguity, leaving these references keeps teaching the old concept.

are never modified.
- **Idempotent.** Repeating the same dry run returns identical rows as long as the base table data
has not changed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@ class IvmDeltaRewriteState {
private int nextDeltaScanIndex;

IvmDeltaRewriteState(Map<OlapTable, OlapTableStream> streams,
boolean includeExhaustedStreams, long refreshVersion, DataType sequenceType,
boolean includeExhaustedStreams, long sequencePrefix, DataType sequenceType,
Map<OlapTable, List<Long>> windowPartitionIdsByTable) {
this.streams = new HashMap<>(streams);
this.includeExhaustedStreams = includeExhaustedStreams;
this.sequenceCalculator = IvmSequenceCalculator.create(refreshVersion, sequenceType);
this.sequenceCalculator = IvmSequenceCalculator.create(sequencePrefix, sequenceType);
this.windowPartitionIdsByTable = windowPartitionIdsByTable;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ public Plan generateIncrRefreshPlan(Plan sinkChild, IvmRewriteResult rewriteResu
rewriteContext.isIncludeExhaustedStreams());
Pair<Plan, List<LogicalProject<?>>> prefixChain = helper.detachAdaptProjectChain(sinkChild);
Plan rootPlan = prefixChain.first;
long refreshVersion = refreshContext.getMtmv().getNextRefreshVersion();
IvmDeltaRewriteState rewriteState = createDeltaRewriteState(rootPlan, refreshContext, refreshVersion,
long sequencePrefix = refreshContext.getMtmv().getNextSequencePrefix();
IvmDeltaRewriteState rewriteState = createDeltaRewriteState(rootPlan, refreshContext, sequencePrefix,
rewriteContext.getIncrementalScopePartitionIds());
Optional<IvmDeltaRewriteResult> deltaResult = rewriteDelta(rootPlan, refreshContext, rewriteState);
if (!deltaResult.isPresent()) {
Expand Down Expand Up @@ -156,7 +156,7 @@ private static Pair<Plan, Map<Slot, Slot>> rewriteSnapshot(Plan plan, IvmDeltaRe
return IvmDeltaRewriteHelper.INSTANCE.freshPlan(rewritten);
}

private IvmDeltaRewriteState createDeltaRewriteState(Plan plan, IvmIncrRefreshContext ctx, long refreshVersion,
private IvmDeltaRewriteState createDeltaRewriteState(Plan plan, IvmIncrRefreshContext ctx, long sequencePrefix,
Map<BaseTableInfo, Set<Long>> scopePartitionIds) {
Map<OlapTable, OlapTableStream> streams = new HashMap<>();
// Window limits apply to every base table in the plan, including excluded
Expand Down Expand Up @@ -186,7 +186,7 @@ private IvmDeltaRewriteState createDeltaRewriteState(Plan plan, IvmIncrRefreshCo
}
}
applyScopePartitionIds(windowPartitionIdsByTable, planTables, scopePartitionIds);
return new IvmDeltaRewriteState(streams, ctx.isIncludeExhaustedStreams(), refreshVersion,
return new IvmDeltaRewriteState(streams, ctx.isIncludeExhaustedStreams(), sequencePrefix,
DataType.fromCatalogType(ctx.getMtmv().getColumn(Column.SEQUENCE_COL).getType()),
windowPartitionIdsByTable);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ public class IvmInfo {
@SerializedName("ps")
private String planSignature;

@SerializedName("rv")
private long refreshVersion;
/** The prefix of the sequence values this MV's rows are stamped with; see IvmSequenceCalculator. */
@SerializedName("sp")
private long sequencePrefix;

public IvmInfo() {
}
Expand All @@ -65,7 +66,7 @@ public IvmInfo(IvmInfo other) {
this.pendingBaselineRebuildPartitions = new HashSet<>(other.pendingBaselineRebuildPartitions);
this.useFullKeys = other.useFullKeys;
this.planSignature = other.planSignature;
this.refreshVersion = other.refreshVersion;
this.sequencePrefix = other.sequencePrefix;
}

public boolean isEnableIvm() {
Expand Down Expand Up @@ -121,12 +122,12 @@ public void setPlanSignature(String planSignature) {
this.planSignature = planSignature;
}

public long getRefreshVersion() {
return refreshVersion;
public long getSequencePrefix() {
return sequencePrefix;
}

public void advanceRefreshVersion() {
refreshVersion++;
public void advanceSequencePrefix() {
sequencePrefix++;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,32 +33,32 @@
/**
* Encodes IVM delta ordering into the MTMV sequence column.
*
* <p>BIGINT encodes {@code (refresh version, delta index, op)}. LARGEINT additionally encodes
* a 64-bit binlog sequence: {@code (refresh version, delta index, binlog sequence, op)}.
* <p>BIGINT encodes {@code (sequence prefix, delta index, op)}. LARGEINT additionally encodes
* a 64-bit binlog sequence: {@code (sequence prefix, delta index, binlog sequence, op)}.
*/
abstract class IvmSequenceCalculator {
static final int DELTA_INDEX_BITS = 10;
private static final int BIGINT_LOW_BITS = DELTA_INDEX_BITS + 1;
private static final int LARGEINT_BINLOG_BITS = 64;
private static final int LARGEINT_DELTA_INDEX_SHIFT = LARGEINT_BINLOG_BITS + 1;
private static final int LARGEINT_REFRESH_VERSION_SHIFT =
private static final int LARGEINT_SEQUENCE_PREFIX_SHIFT =
LARGEINT_DELTA_INDEX_SHIFT + DELTA_INDEX_BITS;
private static final int MAX_DELTA_INDEX = 1 << DELTA_INDEX_BITS;
private static final BigInteger MAX_BINLOG_SEQUENCE =
BigInteger.ONE.shiftLeft(LARGEINT_BINLOG_BITS).subtract(BigInteger.ONE);

final long refreshVersion;
final long sequencePrefix;

private IvmSequenceCalculator(long refreshVersion) {
this.refreshVersion = refreshVersion;
private IvmSequenceCalculator(long sequencePrefix) {
this.sequencePrefix = sequencePrefix;
}

static IvmSequenceCalculator create(long refreshVersion, DataType sequenceType) {
static IvmSequenceCalculator create(long sequencePrefix, DataType sequenceType) {
if (sequenceType.equals(BigIntType.INSTANCE)) {
return new BigIntSequenceCalculator(refreshVersion);
return new BigIntSequenceCalculator(sequencePrefix);
}
if (sequenceType.equals(LargeIntType.INSTANCE)) {
return new LargeIntSequenceCalculator(refreshVersion);
return new LargeIntSequenceCalculator(sequencePrefix);
}
throw new IvmException(IvmFailureReason.PLAN_REWRITE_FAILED,
"unsupported IVM sequence type: " + sequenceType.simpleString());
Expand Down Expand Up @@ -87,11 +87,11 @@ final void checkBinlogSequence(BigInteger binlogSequence) {
}

private static class BigIntSequenceCalculator extends IvmSequenceCalculator {
private BigIntSequenceCalculator(long refreshVersion) {
super(refreshVersion);
if (refreshVersion < 0 || refreshVersion > (Long.MAX_VALUE >>> BIGINT_LOW_BITS)) {
private BigIntSequenceCalculator(long sequencePrefix) {
super(sequencePrefix);
if (sequencePrefix < 0 || sequencePrefix > (Long.MAX_VALUE >>> BIGINT_LOW_BITS)) {
throw new IvmException(IvmFailureReason.PLAN_REWRITE_FAILED,
"IVM refresh version exceeds the BIGINT sequence encoding range: " + refreshVersion);
"IVM sequence prefix exceeds the BIGINT sequence encoding range: " + sequencePrefix);
}
}

Expand All @@ -102,26 +102,26 @@ Literal encode(int deltaIndex, BigInteger binlogSequence, boolean positive) {
throw new IvmException(IvmFailureReason.PLAN_REWRITE_FAILED,
"BIGINT IVM sequence does not support binlog sequence");
}
long sequence = (refreshVersion << BIGINT_LOW_BITS)
long sequence = (sequencePrefix << BIGINT_LOW_BITS)
| ((long) deltaIndex << 1) | (positive ? 1 : 0);
return new BigIntLiteral(sequence);
}
}

private static class LargeIntSequenceCalculator extends IvmSequenceCalculator {
private LargeIntSequenceCalculator(long refreshVersion) {
super(refreshVersion);
if (refreshVersion < 0 || refreshVersion > (Long.MAX_VALUE >>> BIGINT_LOW_BITS)) {
private LargeIntSequenceCalculator(long sequencePrefix) {
super(sequencePrefix);
if (sequencePrefix < 0 || sequencePrefix > (Long.MAX_VALUE >>> BIGINT_LOW_BITS)) {
throw new IvmException(IvmFailureReason.PLAN_REWRITE_FAILED,
"IVM refresh version exceeds the LARGEINT sequence encoding range: " + refreshVersion);
"IVM sequence prefix exceeds the LARGEINT sequence encoding range: " + sequencePrefix);
}
}

@Override
Literal encode(int deltaIndex, BigInteger binlogSequence, boolean positive) {
checkDeltaIndex(deltaIndex);
checkBinlogSequence(binlogSequence);
BigInteger sequence = BigInteger.valueOf(refreshVersion).shiftLeft(LARGEINT_REFRESH_VERSION_SHIFT)
BigInteger sequence = BigInteger.valueOf(sequencePrefix).shiftLeft(LARGEINT_SEQUENCE_PREFIX_SHIFT)
.or(BigInteger.valueOf(deltaIndex).shiftLeft(LARGEINT_DELTA_INDEX_SHIFT))
.or(binlogSequence.shiftLeft(1));
if (positive) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2418,15 +2418,15 @@ private void updateCatalogAfterCommitted(TransactionState transactionState, Data
// update table stream offset if necessary
if (!CollectionUtils.isEmpty(transactionState.getStreamUpdateInfos())) {
updateStreamOffset(transactionState, transactionState.getCommitTime());
updateIvmRefreshVersion(transactionState, db);
updateIvmSequencePrefix(transactionState, db);
}
}

private void updateIvmRefreshVersion(TransactionState transactionState, Database db) {
private void updateIvmSequencePrefix(TransactionState transactionState, Database db) {
for (Long tableId : transactionState.getTableIdList()) {
Table table = db.getTableNullable(tableId);
if (table instanceof MTMV && ((MTMV) table).isIvm()) {
((MTMV) table).getIvmInfo().advanceRefreshVersion();
((MTMV) table).getIvmInfo().advanceSequencePrefix();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ class IvmAggDeltaHandlerTest extends IvmDeltaTestBase {
private AggRewriteResult rewriteAgg(LogicalAggregate<? extends Plan> agg) {
PlanBundle bundle = normalizeAggPlan(agg);
MTMV mtmv = buildMtmvFromPlan(bundle.normalizedPlan.getOutput());
mtmv.getIvmInfo().advanceRefreshVersion();
mtmv.getIvmInfo().advanceRefreshVersion();
mtmv.getIvmInfo().advanceSequencePrefix();
mtmv.getIvmInfo().advanceSequencePrefix();
Plan rewritten = new IvmDeltaRewriter().generateIncrRefreshPlan(
bundle.normalizedPlan, bundle.rewriteResult,
IvmRewriteContext.incremental(mtmv), bundle.connectContext);
Expand All @@ -89,8 +89,8 @@ private AggRewriteResult rewriteAggWithIdentityKeys(LogicalAggregate<? extends P
PlanBundle bundle = normalizeAggPlan(agg);
bundle.rewriteResult.setIdentityKeySlots(identityKeys);
MTMV mtmv = buildMtmvFromPlan(bundle.normalizedPlan.getOutput());
mtmv.getIvmInfo().advanceRefreshVersion();
mtmv.getIvmInfo().advanceRefreshVersion();
mtmv.getIvmInfo().advanceSequencePrefix();
mtmv.getIvmInfo().advanceSequencePrefix();
Plan rewritten = new IvmDeltaRewriter().generateIncrRefreshPlan(
bundle.normalizedPlan, bundle.rewriteResult,
IvmRewriteContext.incremental(mtmv), bundle.connectContext);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
class IvmDeltaRewriteStateTest extends IvmDeltaTestBase {

@Test
void testSequenceEncodesRefreshVersionAndDeltaIndex() {
void testSequenceEncodesSequencePrefixAndDeltaIndex() {
IvmDeltaRewriteState state = new IvmDeltaRewriteState(
ImmutableMap.of(), false, 7L, BigIntType.INSTANCE, ImmutableMap.of());

Expand Down Expand Up @@ -172,7 +172,7 @@ private void addTablet(OlapTable table, int partitionIndex, long tabletId) {
}

@Test
void testLargeIntSequenceEncodesRefreshVersionAndDeltaIndex() {
void testLargeIntSequenceEncodesSequencePrefixAndDeltaIndex() {
IvmDeltaRewriteState state = new IvmDeltaRewriteState(
ImmutableMap.of(), false, 7L, LargeIntType.INSTANCE, ImmutableMap.of());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,31 @@

class IvmInfoTest {
@Test
void testRefreshVersionAdvancesAfterCommittedRefresh() {
void testSequencePrefixAdvancesAfterCommittedRefresh() {
IvmInfo info = new IvmInfo();

Assertions.assertEquals(0, info.getRefreshVersion());
info.advanceRefreshVersion();
Assertions.assertEquals(1, info.getRefreshVersion());
Assertions.assertEquals(0, info.getSequencePrefix());
info.advanceSequencePrefix();
Assertions.assertEquals(1, info.getSequencePrefix());
}

@Test
void testRefreshVersionPersistsThroughGson() {
void testSequencePrefixPersistsThroughGson() {
IvmInfo info = new IvmInfo();
info.advanceRefreshVersion();
info.advanceSequencePrefix();

IvmInfo recovered = GsonUtils.GSON.fromJson(GsonUtils.GSON.toJson(info), IvmInfo.class);
Assertions.assertEquals(1, recovered.getRefreshVersion());
Assertions.assertEquals(1, recovered.getSequencePrefix());
}

@Test
void testSequencePrefixIsPersistedAsSp() {
IvmInfo info = new IvmInfo();
info.advanceSequencePrefix();

String json = GsonUtils.GSON.toJson(info);
Assertions.assertTrue(json.contains("\"sp\":1"), json);
Assertions.assertFalse(json.contains("\"rv\""), json);
}

@Test
Expand All @@ -59,7 +69,7 @@ void testCopyConstructor() {
info.requireCompleteBaselineRebuild();
info.setUseFullKeys(true);
info.setPlanSignature("abc123");
info.advanceRefreshVersion();
info.advanceSequencePrefix();

IvmInfo copy = new IvmInfo(info);
info.clearBaselineRebuild();
Expand All @@ -68,7 +78,7 @@ void testCopyConstructor() {
Assertions.assertTrue(copy.isBaselineRebuildRequired());
Assertions.assertTrue(copy.isUseFullKeys());
Assertions.assertEquals("abc123", copy.getPlanSignature());
Assertions.assertEquals(1, copy.getRefreshVersion());
Assertions.assertEquals(1, copy.getSequencePrefix());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ void testLargeIntSequence() {

@Test
void testLargeIntSequenceUsesFullEncodingRange() {
long maxRefreshVersion = Long.MAX_VALUE >>> 11;
long maxSequencePrefix = Long.MAX_VALUE >>> 11;
IvmSequenceCalculator calculator = IvmSequenceCalculator.create(
maxRefreshVersion, LargeIntType.INSTANCE);
maxSequencePrefix, LargeIntType.INSTANCE);

LargeIntLiteral sequence = (LargeIntLiteral) calculator.encode(
1023, BigInteger.ONE.shiftLeft(64).subtract(BigInteger.ONE), true);
Expand All @@ -70,12 +70,12 @@ void testLargeIntSequenceUsesFullEncodingRange() {

@Test
void testSequenceRejectsValuesOutsideEncodingRanges() {
long maxRefreshVersion = Long.MAX_VALUE >>> 11;
IvmSequenceCalculator.create(maxRefreshVersion, LargeIntType.INSTANCE);
long maxSequencePrefix = Long.MAX_VALUE >>> 11;
IvmSequenceCalculator.create(maxSequencePrefix, LargeIntType.INSTANCE);

IvmException refreshVersionException = Assertions.assertThrows(IvmException.class,
() -> IvmSequenceCalculator.create(maxRefreshVersion + 1, LargeIntType.INSTANCE));
Assertions.assertTrue(refreshVersionException.getMessage().contains("refresh version"));
IvmException sequencePrefixException = Assertions.assertThrows(IvmException.class,
() -> IvmSequenceCalculator.create(maxSequencePrefix + 1, LargeIntType.INSTANCE));
Assertions.assertTrue(sequencePrefixException.getMessage().contains("sequence prefix"));

IvmSequenceCalculator calculator = IvmSequenceCalculator.create(1, LargeIntType.INSTANCE);
IvmException deltaIndexException = Assertions.assertThrows(IvmException.class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ public void testAbortTransactionWithNotFoundException() throws UserException {
}

@Test
public void testUpdateCatalogAfterCommittedAdvancesIvmRefreshVersionForNormalCommitAndReplay()
public void testUpdateCatalogAfterCommittedAdvancesIvmSequencePrefixForNormalCommitAndReplay()
throws Exception {
DatabaseTransactionMgr masterDbTransMgr = masterTransMgr.getDatabaseTransactionMgr(CatalogTestUtil.testDbId1);
Database masterDb = masterEnv.getInternalCatalog().getDbOrMetaException(CatalogTestUtil.testDbId1);
Expand All @@ -520,7 +520,7 @@ public void testUpdateCatalogAfterCommittedAdvancesIvmRefreshVersionForNormalCom
method.setAccessible(true);
method.invoke(masterDbTransMgr, normalCommitTxn, masterDb, false);

Assertions.assertEquals(1L, normalCommitIvmInfo.getRefreshVersion());
Assertions.assertEquals(1L, normalCommitIvmInfo.getSequencePrefix());
Mockito.verify(normalCommitStream).unprotectedUpdateStreamUpdate(
normalCommitTxn.getStreamUpdateInfos().get(0).getUpdate(), normalCommitTxn.getCommitTime());

Expand All @@ -535,7 +535,7 @@ public void testUpdateCatalogAfterCommittedAdvancesIvmRefreshVersionForNormalCom
slaveDb.getId(), 9001L, 10002L, replayStreamId, 456L);
method.invoke(slaveDbTransMgr, replayTxn, slaveDb, true);

Assertions.assertEquals(1L, replayIvmInfo.getRefreshVersion());
Assertions.assertEquals(1L, replayIvmInfo.getSequencePrefix());
Mockito.verify(replayStream).unprotectedUpdateStreamUpdate(
replayTxn.getStreamUpdateInfos().get(0).getUpdate(), replayTxn.getCommitTime());
}
Expand Down
Loading