Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
c17e4c6
GH-5672 introduce simple learned join optimization that tracks fanout…
hmottestad Jan 26, 2026
63ae8d3
GH-5672 improved handling of drift and also enabled for Memory Store …
hmottestad Jan 26, 2026
e65b41b
GH-5672 adaptive query evaluation and dynamic programming for join re…
hmottestad Jan 26, 2026
5d2af55
GH-5672 wip
hmottestad Jan 26, 2026
c70fc3b
GH-5672 wip
hmottestad Jan 27, 2026
518745a
GH-5672 wip
hmottestad Jan 27, 2026
f4ed4c4
GH-5672 wip
hmottestad Jan 27, 2026
7db45c2
remove adaptive hash join
hmottestad Jan 28, 2026
62b3744
more code cleanup
hmottestad Jan 28, 2026
4e983d0
more code cleanup
hmottestad Jan 28, 2026
1098214
more code cleanup
hmottestad Jan 28, 2026
1615b94
more fixes
hmottestad Jan 29, 2026
ec6a711
more fixes
hmottestad Jan 30, 2026
80fbb0a
more fixes
hmottestad Jan 30, 2026
b499549
more fixes
hmottestad Jan 30, 2026
3ae263a
more fixes
hmottestad Jan 30, 2026
023cfc3
more fixes
hmottestad Jan 30, 2026
39f7f99
more fixes
hmottestad Jan 30, 2026
ae8b379
more fixes
hmottestad Jan 30, 2026
2713fe0
more fixes
hmottestad Jan 31, 2026
1cf84a5
more fixes
hmottestad Jan 31, 2026
ed8b6ef
more fixes
hmottestad Jan 31, 2026
366391b
more fixes
hmottestad Jan 31, 2026
f89f6e0
more fixes
hmottestad Jan 31, 2026
9c9e0ac
wip improved dp plan
hmottestad Jan 31, 2026
e771222
wip improved dp plan
hmottestad Jan 31, 2026
5775175
tests for logging plans
hmottestad Feb 2, 2026
d831432
tests for logging plans
hmottestad Feb 2, 2026
6bc374d
tests for logging plans
hmottestad Feb 2, 2026
2ce2885
tests for logging plans
hmottestad Feb 2, 2026
cb6b0e2
tests for query plans
hmottestad Feb 2, 2026
74fea25
more tests and stuff
hmottestad Feb 2, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -1634,6 +1634,6 @@ public Supplier<CollectionFactory> getCollectionFactory() {

@Override
public void setCollectionFactory(Supplier<CollectionFactory> cf) {
this.collectionFactory = cf;
this.collectionFactory = cf != null ? cf : DefaultCollectionFactory::new;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*******************************************************************************
* Copyright (c) 2026 Eclipse RDF4J contributors.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
// Some portions generated by Codex
package org.eclipse.rdf4j.query.algebra.evaluation.impl;

import java.util.Objects;

import org.eclipse.rdf4j.query.Dataset;
import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy;
import org.eclipse.rdf4j.query.algebra.evaluation.RDFStarTripleSource;
import org.eclipse.rdf4j.query.algebra.evaluation.TripleSource;
import org.eclipse.rdf4j.query.algebra.evaluation.federation.FederatedServiceResolver;
import org.eclipse.rdf4j.query.algebra.evaluation.optimizer.JoinStatsProvider;
import org.eclipse.rdf4j.query.algebra.evaluation.optimizer.LearningQueryOptimizerPipeline;
import org.eclipse.rdf4j.query.algebra.evaluation.optimizer.LearningRdfStarTripleSource;
import org.eclipse.rdf4j.query.algebra.evaluation.optimizer.LearningTripleSource;
import org.eclipse.rdf4j.query.algebra.evaluation.optimizer.MemoryJoinStats;
import org.eclipse.rdf4j.query.algebra.evaluation.optimizer.learned.LearnedJoinConfig;

/**
* Evaluation strategy factory that injects a learned join optimizer.
*
* <p>
* Example enablement:
*
* <pre>{@code
* LearnedJoinConfig config = new LearnedJoinConfig(
* LearnedJoinConfig.DEFAULT_DP_THRESHOLD,
* true);
* LearningEvaluationStrategyFactory factory = new LearningEvaluationStrategyFactory(new MemoryJoinStats(), null,
* config);
* NativeStore store = new NativeStore(dataDir);
* store.setEvaluationStrategyFactory(factory);
* }</pre>
*/
public class LearningEvaluationStrategyFactory extends DefaultEvaluationStrategyFactory {

private final JoinStatsProvider statsProvider;
private final EvaluationStatistics optimizerStatisticsOverride;
private final LearnedJoinConfig joinConfig;

public LearningEvaluationStrategyFactory() {
this(new MemoryJoinStats(), null, new LearnedJoinConfig());
}

public LearningEvaluationStrategyFactory(FederatedServiceResolver resolver) {
this(new MemoryJoinStats(), null, new LearnedJoinConfig());
setFederatedServiceResolver(resolver);
}

public LearningEvaluationStrategyFactory(EvaluationStatistics optimizerStatisticsOverride) {
this(new MemoryJoinStats(), optimizerStatisticsOverride, new LearnedJoinConfig());
}

public LearningEvaluationStrategyFactory(JoinStatsProvider statsProvider) {
this(statsProvider, null, new LearnedJoinConfig());
}

public LearningEvaluationStrategyFactory(JoinStatsProvider statsProvider,
EvaluationStatistics optimizerStatisticsOverride) {
this(statsProvider, optimizerStatisticsOverride, new LearnedJoinConfig());
}

public LearningEvaluationStrategyFactory(LearnedJoinConfig joinConfig) {
this(new MemoryJoinStats(), null, joinConfig);
}

public LearningEvaluationStrategyFactory(JoinStatsProvider statsProvider, LearnedJoinConfig joinConfig) {
this(statsProvider, null, joinConfig);
}

public LearningEvaluationStrategyFactory(JoinStatsProvider statsProvider,
EvaluationStatistics optimizerStatisticsOverride, LearnedJoinConfig joinConfig) {
this.statsProvider = Objects.requireNonNull(statsProvider, "statsProvider");
this.optimizerStatisticsOverride = optimizerStatisticsOverride;
this.joinConfig = Objects.requireNonNull(joinConfig, "joinConfig");
}

public JoinStatsProvider getStatsProvider() {
return statsProvider;
}

public LearnedJoinConfig getJoinConfig() {
return joinConfig;
}

@Override
public EvaluationStrategy createEvaluationStrategy(Dataset dataset, TripleSource tripleSource,
EvaluationStatistics evaluationStatistics) {
TripleSource learningTripleSource = tripleSource instanceof RDFStarTripleSource
? new LearningRdfStarTripleSource((RDFStarTripleSource) tripleSource, statsProvider)
: new LearningTripleSource(tripleSource, statsProvider);
EvaluationStrategy strategy = super.createEvaluationStrategy(dataset, learningTripleSource,
evaluationStatistics);
EvaluationStatistics optimizerStatistics = optimizerStatisticsOverride != null
? optimizerStatisticsOverride
: evaluationStatistics;
strategy.setOptimizerPipeline(
new LearningQueryOptimizerPipeline(strategy, learningTripleSource, optimizerStatistics,
statsProvider, joinConfig));
return strategy;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*******************************************************************************
* Copyright (c) 2026 Eclipse RDF4J contributors.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
// Some portions generated by Codex
package org.eclipse.rdf4j.query.algebra.evaluation.optimizer;

/**
* Collects and supplies statistics about triple pattern evaluations.
*/
public interface JoinStatsProvider {

void reset();

void recordCall(PatternKey key);

void recordResults(PatternKey key, long resultCount);

/**
* Seeds statistics for the given key. Implementations may also invalidate or refresh existing entries if the
* supplied default cardinality has drifted significantly from the stored baseline.
*/
void seedIfAbsent(PatternKey key, double defaultCardinality, long priorCalls);

double getAverageResults(PatternKey key);

boolean hasStats(PatternKey key);

long getTotalCalls();

/**
* Records that statements have been added to the store. Implementations may use this to invalidate statistics when
* a write threshold is exceeded in a time window.
*/
default void recordStatementsAdded(long statementCount) {
// no-op by default
}
}
Loading