Search in sources :

Example 1 with Index

use of com.apple.foundationdb.record.metadata.Index in project fdb-record-layer by FoundationDB.

the class RecordQueryPlanner method planFilterForInJoin.

private ScoredPlan planFilterForInJoin(@Nonnull PlanContext planContext, @Nonnull QueryComponent filter, boolean needOrdering) {
    planContext.rankComparisons = new RankComparisons(filter, planContext.indexes);
    List<ScoredPlan> intersectionCandidates = new ArrayList<>();
    ScoredPlan bestPlan = null;
    Index bestIndex = null;
    if (planContext.commonPrimaryKey != null) {
        bestPlan = planIndex(planContext, filter, null, planContext.commonPrimaryKey, intersectionCandidates);
    }
    for (Index index : planContext.indexes) {
        KeyExpression indexKeyExpression = indexKeyExpressionForPlan(planContext.commonPrimaryKey, index);
        ScoredPlan p = planIndex(planContext, filter, index, indexKeyExpression, intersectionCandidates);
        if (p != null) {
            // * need for type filtering if row scan with multiple types.
            if (isBetterThanOther(planContext, p, index, bestPlan, bestIndex)) {
                bestPlan = p;
                bestIndex = index;
            }
        }
    }
    if (bestPlan != null) {
        if (bestPlan.getNumNonSargables() > 0) {
            bestPlan = handleNonSargables(bestPlan, intersectionCandidates, planContext);
        }
        if (needOrdering) {
            bestPlan.planOrderingKey = PlanOrderingKey.forPlan(metaData, bestPlan.plan, planContext.commonPrimaryKey);
        }
    }
    return bestPlan;
}
Also used : RankComparisons(com.apple.foundationdb.record.query.plan.planning.RankComparisons) ArrayList(java.util.ArrayList) RecordTypeKeyExpression(com.apple.foundationdb.record.metadata.expressions.RecordTypeKeyExpression) VersionKeyExpression(com.apple.foundationdb.record.metadata.expressions.VersionKeyExpression) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) FieldKeyExpression(com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression) NestingKeyExpression(com.apple.foundationdb.record.metadata.expressions.NestingKeyExpression) EmptyKeyExpression(com.apple.foundationdb.record.metadata.expressions.EmptyKeyExpression) ThenKeyExpression(com.apple.foundationdb.record.metadata.expressions.ThenKeyExpression) RecordQueryPlanWithIndex(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlanWithIndex) Index(com.apple.foundationdb.record.metadata.Index)

Example 2 with Index

use of com.apple.foundationdb.record.metadata.Index in project fdb-record-layer by FoundationDB.

the class RecordQueryPlanner method planNoFilter.

@Nullable
private RecordQueryPlan planNoFilter(PlanContext planContext, KeyExpression sort, boolean sortReverse) {
    ScoredPlan bestPlan = null;
    Index bestIndex = null;
    if (sort == null) {
        bestPlan = planNoFilterNoSort(planContext, null);
    } else if (planContext.commonPrimaryKey != null) {
        bestPlan = planSortOnly(new CandidateScan(planContext, null, sortReverse), planContext.commonPrimaryKey, sort);
    }
    for (Index index : planContext.indexes) {
        ScoredPlan p;
        if (sort == null) {
            p = planNoFilterNoSort(planContext, index);
        } else {
            p = planSortOnly(new CandidateScan(planContext, index, sortReverse), indexKeyExpressionForPlan(planContext.commonPrimaryKey, index), sort);
        }
        if (p != null) {
            if (bestPlan == null || p.score > bestPlan.score || (p.score == bestPlan.score && compareIndexes(planContext, index, bestIndex) > 0)) {
                bestPlan = p;
                bestIndex = index;
            }
        }
    }
    if (bestPlan != null) {
        bestPlan = planRemoveDuplicates(planContext, bestPlan);
        if (bestPlan == null) {
            throw new RecordCoreException("A common primary key is required to remove duplicates");
        }
        return bestPlan.plan;
    }
    return null;
}
Also used : RecordCoreException(com.apple.foundationdb.record.RecordCoreException) RecordQueryPlanWithIndex(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlanWithIndex) Index(com.apple.foundationdb.record.metadata.Index) Nullable(javax.annotation.Nullable)

Example 3 with Index

use of com.apple.foundationdb.record.metadata.Index in project fdb-record-layer by FoundationDB.

the class RecordQueryPlanner method computeIndexFilters.

private ScoredPlan computeIndexFilters(@Nonnull PlanContext planContext, @Nonnull final ScoredPlan plan) {
    if (plan.plan instanceof RecordQueryPlanWithIndex) {
        final RecordQueryPlanWithIndex indexPlan = (RecordQueryPlanWithIndex) plan.plan;
        final Index index = metaData.getIndex(indexPlan.getIndexName());
        final Collection<RecordType> recordTypes = metaData.recordTypesForIndex(index);
        if (recordTypes.size() != 1) {
            return plan;
        }
        final RecordType recordType = Iterables.getOnlyElement(recordTypes);
        final List<QueryComponent> unsatisfiedFilters = new ArrayList<>(plan.unsatisfiedFilters);
        final AvailableFields availableFieldsFromIndex = AvailableFields.fromIndex(recordType, index, indexTypes, planContext.commonPrimaryKey);
        final List<QueryComponent> indexFilters = Lists.newArrayListWithCapacity(unsatisfiedFilters.size());
        final List<QueryComponent> residualFilters = Lists.newArrayListWithCapacity(unsatisfiedFilters.size());
        FilterVisitor.partitionFilters(unsatisfiedFilters, availableFieldsFromIndex, indexFilters, residualFilters, null);
        if (!indexFilters.isEmpty()) {
            return plan.withFilters(residualFilters, indexFilters);
        }
    }
    return plan;
}
Also used : QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) RecordType(com.apple.foundationdb.record.metadata.RecordType) ArrayList(java.util.ArrayList) RecordQueryPlanWithIndex(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlanWithIndex) RecordQueryPlanWithIndex(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlanWithIndex) Index(com.apple.foundationdb.record.metadata.Index)

Example 4 with Index

use of com.apple.foundationdb.record.metadata.Index in project fdb-record-layer by FoundationDB.

the class IndexingCommon method fillTargetIndexers.

private void fillTargetIndexers(@Nonnull List<Index> targetIndexes, @Nullable Collection<RecordType> recordTypes) {
    boolean presetTypes = false;
    if (recordTypes != null) {
        if (targetIndexes.size() > 1) {
            throw new IndexingBase.ValidationException("Can't use preset record types with multi target indexing");
        }
        presetTypes = true;
    }
    if (recordStoreBuilder.getMetaDataProvider() == null) {
        throw new MetaDataException("record store builder must include metadata");
    }
    final RecordMetaData metaData = recordStoreBuilder.getMetaDataProvider().getRecordMetaData();
    for (Index targetIndex : targetIndexes) {
        Collection<RecordType> types;
        if (presetTypes) {
            types = recordTypes;
        } else {
            types = metaData.recordTypesForIndex(targetIndex);
        }
        boolean isSynthetic = false;
        if (types.stream().anyMatch(RecordType::isSynthetic)) {
            types = new SyntheticRecordPlanner(metaData, new RecordStoreState(null, null)).storedRecordTypesForIndex(targetIndex, types);
            isSynthetic = true;
        }
        targetIndexContexts.add(new IndexContext(targetIndex, types, isSynthetic));
        allRecordTypes.addAll(types);
    }
}
Also used : RecordMetaData(com.apple.foundationdb.record.RecordMetaData) RecordType(com.apple.foundationdb.record.metadata.RecordType) SyntheticRecordPlanner(com.apple.foundationdb.record.query.plan.synthetic.SyntheticRecordPlanner) Index(com.apple.foundationdb.record.metadata.Index) RecordStoreState(com.apple.foundationdb.record.RecordStoreState) MetaDataException(com.apple.foundationdb.record.metadata.MetaDataException)

Example 5 with Index

use of com.apple.foundationdb.record.metadata.Index in project fdb-record-layer by FoundationDB.

the class IndexingScrubMissing method getRecordIfMissingIndex.

@Nullable
private CompletableFuture<FDBStoredRecord<Message>> getRecordIfMissingIndex(FDBRecordStore store, final RecordCursorResult<FDBStoredRecord<Message>> currResult) {
    final FDBStoredRecord<Message> rec = currResult.get();
    // return true if an index is missing and updated
    if (!common.getAllRecordTypes().contains(rec.getRecordType())) {
        return CompletableFuture.completedFuture(null);
    }
    final Index index = common.getIndex();
    final IndexMaintainer maintainer = store.getIndexMaintainer(index);
    List<IndexEntry> indexEntryNoPKs = maintainer.filteredIndexEntries(rec);
    if (indexEntryNoPKs == null) {
        return CompletableFuture.completedFuture(null);
    }
    return AsyncUtil.getAll(indexEntryNoPKs.stream().map(entry -> {
        // should I convert it to a single nested statement?
        final IndexEntry indexEntry = new IndexEntry(index, FDBRecordStoreBase.indexEntryKey(index, entry.getKey(), rec.getPrimaryKey()), entry.getValue());
        final Tuple valueKey = indexEntry.getKey();
        final byte[] keyBytes = maintainer.getIndexSubspace().pack(valueKey);
        return maintainer.state.transaction.get(keyBytes).thenApply(indexVal -> indexVal == null ? valueKey : null);
    }).collect(Collectors.toList())).thenApply(list -> {
        List<Tuple> missingIndexesKeys = list.stream().filter(Objects::nonNull).collect(Collectors.toList());
        if (missingIndexesKeys.isEmpty()) {
            return null;
        }
        // (Maybe) report an error and (maybe) return this record to be index
        if (LOGGER.isWarnEnabled() && logWarningCounter > 0) {
            logWarningCounter--;
            LOGGER.warn(KeyValueLogMessage.build("Scrubber: missing index entry", LogMessageKeys.KEY, rec.getPrimaryKey().toString(), LogMessageKeys.INDEX_KEY, missingIndexesKeys.toString()).addKeysAndValues(common.indexLogMessageKeyValues()).toString());
        }
        missingCount.incrementAndGet();
        final FDBStoreTimer timer = getRunner().getTimer();
        timerIncrement(timer, FDBStoreTimer.Counts.INDEX_SCRUBBER_MISSING_ENTRIES);
        if (scrubbingPolicy.allowRepair()) {
            // record to be indexed
            return rec;
        }
        // report only mode
        return null;
    });
}
Also used : IndexEntry(com.apple.foundationdb.record.IndexEntry) RecordMetaData(com.apple.foundationdb.record.RecordMetaData) Arrays(java.util.Arrays) LogMessageKeys(com.apple.foundationdb.record.logging.LogMessageKeys) LoggerFactory(org.slf4j.LoggerFactory) AsyncIterator(com.apple.foundationdb.async.AsyncIterator) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) CompletableFuture(java.util.concurrent.CompletableFuture) AsyncUtil(com.apple.foundationdb.async.AsyncUtil) MetaDataException(com.apple.foundationdb.record.metadata.MetaDataException) RangeSet(com.apple.foundationdb.async.RangeSet) AtomicReference(java.util.concurrent.atomic.AtomicReference) Subspace(com.apple.foundationdb.subspace.Subspace) Transaction(com.apple.foundationdb.Transaction) ExecuteProperties(com.apple.foundationdb.record.ExecuteProperties) Tuple(com.apple.foundationdb.tuple.Tuple) Range(com.apple.foundationdb.Range) RecordCursorResult(com.apple.foundationdb.record.RecordCursorResult) KeyValueLogMessage(com.apple.foundationdb.record.logging.KeyValueLogMessage) ScanProperties(com.apple.foundationdb.record.ScanProperties) IndexBuildProto(com.apple.foundationdb.record.IndexBuildProto) Nonnull(javax.annotation.Nonnull) Nullable(javax.annotation.Nullable) IsolationLevel(com.apple.foundationdb.record.IsolationLevel) Logger(org.slf4j.Logger) IndexState(com.apple.foundationdb.record.IndexState) Collectors(java.util.stream.Collectors) TupleRange(com.apple.foundationdb.record.TupleRange) Objects(java.util.Objects) AtomicLong(java.util.concurrent.atomic.AtomicLong) List(java.util.List) RecordMetaDataProvider(com.apple.foundationdb.record.RecordMetaDataProvider) Index(com.apple.foundationdb.record.metadata.Index) Message(com.google.protobuf.Message) RecordCursor(com.apple.foundationdb.record.RecordCursor) IndexTypes(com.apple.foundationdb.record.metadata.IndexTypes) API(com.apple.foundationdb.annotation.API) KeyValueLogMessage(com.apple.foundationdb.record.logging.KeyValueLogMessage) Message(com.google.protobuf.Message) IndexEntry(com.apple.foundationdb.record.IndexEntry) Index(com.apple.foundationdb.record.metadata.Index) Tuple(com.apple.foundationdb.tuple.Tuple) Nullable(javax.annotation.Nullable)

Aggregations

Index (com.apple.foundationdb.record.metadata.Index)347 Test (org.junit.jupiter.api.Test)262 List (java.util.List)183 IndexTypes (com.apple.foundationdb.record.metadata.IndexTypes)178 Assertions.assertEquals (org.junit.jupiter.api.Assertions.assertEquals)171 Collections (java.util.Collections)168 Message (com.google.protobuf.Message)166 Tags (com.apple.test.Tags)156 Tag (org.junit.jupiter.api.Tag)156 Expressions.field (com.apple.foundationdb.record.metadata.Key.Expressions.field)155 Query (com.apple.foundationdb.record.query.expressions.Query)151 MatcherAssert.assertThat (org.hamcrest.MatcherAssert.assertThat)150 Nonnull (javax.annotation.Nonnull)147 Key (com.apple.foundationdb.record.metadata.Key)143 Tuple (com.apple.foundationdb.tuple.Tuple)142 Arrays (java.util.Arrays)139 RecordCoreException (com.apple.foundationdb.record.RecordCoreException)138 RecordQuery (com.apple.foundationdb.record.query.RecordQuery)138 ArrayList (java.util.ArrayList)135 Assertions.assertTrue (org.junit.jupiter.api.Assertions.assertTrue)134