summaryrefslogtreecommitdiff
path: root/src/mongo/db/query/collection_query_info.cpp
diff options
context:
space:
mode:
authorAlberto Massari <alberto.massari@mongodb.com>2022-12-21 19:56:54 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-12-21 21:14:53 +0000
commit5977e706431fd5705b59115ec0e0d2d7a2203246 (patch)
tree2161b9d853c2e7453a19d12b88bd39bc9bf87dd5 /src/mongo/db/query/collection_query_info.cpp
parent9ac3279cc3459b31a597ed4659e07ad93f073d8f (diff)
downloadmongo-5977e706431fd5705b59115ec0e0d2d7a2203246.tar.gz
SERVER-65364 Allow fine-grained selection of indexes to update
Diffstat (limited to 'src/mongo/db/query/collection_query_info.cpp')
-rw-r--r--src/mongo/db/query/collection_query_info.cpp136
1 files changed, 71 insertions, 65 deletions
diff --git a/src/mongo/db/query/collection_query_info.cpp b/src/mongo/db/query/collection_query_info.cpp
index 55261978b21..1f689e766db 100644
--- a/src/mongo/db/query/collection_query_info.cpp
+++ b/src/mongo/db/query/collection_query_info.cpp
@@ -118,78 +118,84 @@ const UpdateIndexData& CollectionQueryInfo::getIndexKeys(OperationContext* opCtx
return _indexedPaths;
}
-void CollectionQueryInfo::computeIndexKeys(OperationContext* opCtx, const CollectionPtr& coll) {
- _indexedPaths.clear();
+void CollectionQueryInfo::computeUpdateIndexData(const IndexCatalogEntry* entry,
+ const IndexAccessMethod* accessMethod,
+ UpdateIndexData* outData) {
+ const IndexDescriptor* descriptor = entry->descriptor();
+ if (bool isWildcard = (descriptor->getAccessMethodName() == IndexNames::WILDCARD);
+ isWildcard || descriptor->getAccessMethodName() == IndexNames::COLUMN) {
+ // Obtain the projection used by the $** index's key generator.
+ const auto* pathProj = isWildcard
+ ? static_cast<const IndexPathProjection*>(
+ static_cast<const WildcardAccessMethod*>(accessMethod)->getWildcardProjection())
+ : static_cast<const IndexPathProjection*>(
+ static_cast<const ColumnStoreAccessMethod*>(accessMethod)
+ ->getColumnstoreProjection());
+ // If the projection is an exclusion, then we must check the new document's keys on all
+ // updates, since we do not exhaustively know the set of paths to be indexed.
+ if (pathProj->exec()->getType() ==
+ TransformerInterface::TransformerType::kExclusionProjection) {
+ outData->allPathsIndexed();
+ } else {
+ // If a subtree was specified in the keyPattern, or if an inclusion projection is
+ // present, then we need only index the path(s) preserved by the projection.
+ const auto& exhaustivePaths = pathProj->exhaustivePaths();
+ invariant(exhaustivePaths);
+ for (const auto& path : *exhaustivePaths) {
+ outData->addPath(path);
+ }
+ }
+ } else if (descriptor->getAccessMethodName() == IndexNames::TEXT) {
+ fts::FTSSpec ftsSpec(descriptor->infoObj());
- auto it = coll->getIndexCatalog()->getIndexIterator(
- opCtx, IndexCatalog::InclusionPolicy::kReady | IndexCatalog::InclusionPolicy::kUnfinished);
- while (it->more()) {
- const IndexCatalogEntry* entry = it->next();
- const IndexDescriptor* descriptor = entry->descriptor();
- const IndexAccessMethod* iam = entry->accessMethod();
-
- if (bool isWildcard = (descriptor->getAccessMethodName() == IndexNames::WILDCARD);
- isWildcard || descriptor->getAccessMethodName() == IndexNames::COLUMN) {
- // Obtain the projection used by the $** index's key generator.
- const auto* pathProj = isWildcard
- ? static_cast<const IndexPathProjection*>(
- static_cast<const WildcardAccessMethod*>(iam)->getWildcardProjection())
- : static_cast<const IndexPathProjection*>(
- static_cast<const ColumnStoreAccessMethod*>(iam)->getColumnstoreProjection());
- // If the projection is an exclusion, then we must check the new document's keys on all
- // updates, since we do not exhaustively know the set of paths to be indexed.
- if (pathProj->exec()->getType() ==
- TransformerInterface::TransformerType::kExclusionProjection) {
- _indexedPaths.allPathsIndexed();
- } else {
- // If a subtree was specified in the keyPattern, or if an inclusion projection is
- // present, then we need only index the path(s) preserved by the projection.
- const auto& exhaustivePaths = pathProj->exhaustivePaths();
- invariant(exhaustivePaths);
- for (const auto& path : *exhaustivePaths) {
- _indexedPaths.addPath(path);
- }
+ if (ftsSpec.wildcard()) {
+ outData->allPathsIndexed();
+ } else {
+ for (size_t i = 0; i < ftsSpec.numExtraBefore(); ++i) {
+ outData->addPath(FieldRef(ftsSpec.extraBefore(i)));
}
- } else if (descriptor->getAccessMethodName() == IndexNames::TEXT) {
- fts::FTSSpec ftsSpec(descriptor->infoObj());
-
- if (ftsSpec.wildcard()) {
- _indexedPaths.allPathsIndexed();
- } else {
- for (size_t i = 0; i < ftsSpec.numExtraBefore(); ++i) {
- _indexedPaths.addPath(FieldRef(ftsSpec.extraBefore(i)));
- }
- for (fts::Weights::const_iterator it = ftsSpec.weights().begin();
- it != ftsSpec.weights().end();
- ++it) {
- _indexedPaths.addPath(FieldRef(it->first));
- }
- for (size_t i = 0; i < ftsSpec.numExtraAfter(); ++i) {
- _indexedPaths.addPath(FieldRef(ftsSpec.extraAfter(i)));
- }
- // Any update to a path containing "language" as a component could change the
- // language of a subdocument. Add the override field as a path component.
- _indexedPaths.addPathComponent(ftsSpec.languageOverrideField());
+ for (fts::Weights::const_iterator it = ftsSpec.weights().begin();
+ it != ftsSpec.weights().end();
+ ++it) {
+ outData->addPath(FieldRef(it->first));
}
- } else {
- BSONObj key = descriptor->keyPattern();
- BSONObjIterator j(key);
- while (j.more()) {
- BSONElement e = j.next();
- _indexedPaths.addPath(FieldRef(e.fieldName()));
+ for (size_t i = 0; i < ftsSpec.numExtraAfter(); ++i) {
+ outData->addPath(FieldRef(ftsSpec.extraAfter(i)));
}
+ // Any update to a path containing "language" as a component could change the
+ // language of a subdocument. Add the override field as a path component.
+ outData->addPathComponent(ftsSpec.languageOverrideField());
+ }
+ } else {
+ BSONObj key = descriptor->keyPattern();
+ BSONObjIterator j(key);
+ while (j.more()) {
+ BSONElement e = j.next();
+ outData->addPath(FieldRef(e.fieldName()));
}
+ }
- // handle partial indexes
- const MatchExpression* filter = entry->getFilterExpression();
- if (filter) {
- stdx::unordered_set<std::string> paths;
- QueryPlannerIXSelect::getFields(filter, &paths);
- for (auto it = paths.begin(); it != paths.end(); ++it) {
- _indexedPaths.addPath(FieldRef(*it));
- }
+ // handle partial indexes
+ const MatchExpression* filter = entry->getFilterExpression();
+ if (filter) {
+ stdx::unordered_set<std::string> paths;
+ QueryPlannerIXSelect::getFields(filter, &paths);
+ for (auto it = paths.begin(); it != paths.end(); ++it) {
+ outData->addPath(FieldRef(*it));
}
}
+}
+
+void CollectionQueryInfo::computeUpdateIndexData(OperationContext* opCtx,
+ const CollectionPtr& coll) {
+ _indexedPaths.clear();
+
+ auto it = coll->getIndexCatalog()->getIndexIterator(
+ opCtx, IndexCatalog::InclusionPolicy::kReady | IndexCatalog::InclusionPolicy::kUnfinished);
+ while (it->more()) {
+ const IndexCatalogEntry* entry = it->next();
+ computeUpdateIndexData(entry, entry->accessMethod(), &_indexedPaths);
+ }
_keysComputed = true;
}
@@ -261,7 +267,7 @@ void CollectionQueryInfo::init(OperationContext* opCtx, const CollectionPtr& col
void CollectionQueryInfo::rebuildIndexData(OperationContext* opCtx, const CollectionPtr& coll) {
_keysComputed = false;
- computeIndexKeys(opCtx, coll);
+ computeUpdateIndexData(opCtx, coll);
updatePlanCacheIndexEntries(opCtx, coll);
}