Skip to content

Commit 8861091

Browse files
albymassariMongoDB Bot
authored andcommitted
SERVER-96045 Remove non-QO code from CollectionQueryInfo (#31680)
GitOrigin-RevId: 3028589
1 parent 40e36f8 commit 8861091

20 files changed

+241
-198
lines changed

.github/CODEOWNERS

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1280,6 +1280,7 @@ WORKSPACE.bazel @10gen/devprod-build @svc-auto-approve-bot
12801280
/src/mongo/db/catalog/**/collection_yield_restore* @10gen/server-catalog-and-routing @svc-auto-approve-bot
12811281
/src/mongo/db/catalog/**/historical_catalogid_tracker* @10gen/server-catalog-and-routing @svc-auto-approve-bot
12821282
/src/mongo/db/catalog/**/index_catalog* @10gen/server-catalog-and-routing @svc-auto-approve-bot
1283+
/src/mongo/db/catalog/**/index_catalog_entry_helpers* @10gen/query-execution-write-exec @svc-auto-approve-bot
12831284
/src/mongo/db/catalog/**/index_signature_test.cpp @10gen/server-catalog-and-routing @svc-auto-approve-bot
12841285
/src/mongo/db/catalog/**/list_indexes* @10gen/server-catalog-and-routing @svc-auto-approve-bot
12851286
/src/mongo/db/catalog/**/snapshot_helper* @10gen/server-catalog-and-routing @svc-auto-approve-bot
@@ -1697,7 +1698,7 @@ WORKSPACE.bazel @10gen/devprod-build @svc-auto-approve-bot
16971698
/src/mongo/db/query/**/OWNERS.yml @10gen/query-execution-staff-leads @10gen/query-integration-staff-leads @10gen/query-optimization-staff-leads @svc-auto-approve-bot
16981699
/src/mongo/db/query/**/analyze* @10gen/query-optimization @svc-auto-approve-bot
16991700
/src/mongo/db/query/**/collection_index_usage_tracker* @10gen/query-execution-index-access-stats @svc-auto-approve-bot
1700-
/src/mongo/db/query/**/collection_query_info* @10gen/query @svc-auto-approve-bot
1701+
/src/mongo/db/query/**/collection_query_info* @10gen/query-optimization-plan-cache @svc-auto-approve-bot
17011702
/src/mongo/db/query/**/eof_node_type* @10gen/query-optimization @svc-auto-approve-bot
17021703
/src/mongo/db/query/**/explain* @10gen/query-optimization-explain @svc-auto-approve-bot
17031704
/src/mongo/db/query/**/expression_walker* @10gen/query-optimization-logical-models @svc-auto-approve-bot

src/mongo/db/catalog/BUILD.bazel

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,6 @@ mongo_cc_library(
147147
],
148148
deps = [
149149
"//src/mongo/db/query/plan_cache:query_plan_cache",
150-
"//src/mongo/db:update_index_data",
151150
"//src/mongo/db:collection_index_usage_tracker",
152151
"//src/mongo/db/fts:base_fts",
153152
"//src/mongo/db/query:query_planner",
@@ -545,6 +544,7 @@ mongo_cc_library(
545544
"collection_impl.cpp",
546545
"database_holder_impl.cpp",
547546
"database_impl.cpp",
547+
"index_catalog_entry_helpers.cpp",
548548
"index_catalog_entry_impl.cpp",
549549
"index_catalog_impl.cpp",
550550
"virtual_collection_impl.cpp",
@@ -553,6 +553,7 @@ mongo_cc_library(
553553
"collection_impl.h",
554554
"database_holder_impl.h",
555555
"database_impl.h",
556+
"index_catalog_entry_helpers.h",
556557
"index_catalog_entry_impl.h",
557558
"index_catalog_impl.h",
558559
"virtual_collection_impl.h",
@@ -561,7 +562,6 @@ mongo_cc_library(
561562
"catalog_helpers",
562563
"catalog_stats",
563564
"collection_options",
564-
"collection_query_info",
565565
"document_validation",
566566
"health_log_interface",
567567
"index_catalog",
@@ -694,6 +694,7 @@ mongo_cc_unit_test(
694694
"database_test.cpp",
695695
"drop_database_test.cpp",
696696
"historical_catalogid_tracker_test.cpp",
697+
"index_catalog_entry_impl_test.cpp",
697698
"index_catalog_impl_test.cpp",
698699
"index_key_validate_test.cpp",
699700
"index_signature_test.cpp",
@@ -718,7 +719,6 @@ mongo_cc_unit_test(
718719
":collection_catalog",
719720
":collection_mock",
720721
":collection_options",
721-
":collection_query_info",
722722
":database_holder",
723723
":index_key_validate",
724724
":storage_engine_collection_options_flags_parser",

src/mongo/db/catalog/OWNERS.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ filters:
8585
- "index_catalog*":
8686
approvers:
8787
- 10gen/server-catalog-and-routing
88+
- "index_catalog_entry_helpers*":
89+
approvers:
90+
- 10gen/query-execution-write-exec
8891
- "index_signature_test.cpp":
8992
approvers:
9093
- 10gen/server-catalog-and-routing
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/**
2+
* Copyright (C) 2025-present MongoDB, Inc.
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the Server Side Public License, version 1,
6+
* as published by MongoDB, Inc.
7+
*
8+
* This program is distributed in the hope that it will be useful,
9+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
* Server Side Public License for more details.
12+
*
13+
* You should have received a copy of the Server Side Public License
14+
* along with this program. If not, see
15+
* <http://www.mongodb.com/licensing/server-side-public-license>.
16+
*
17+
* As a special exception, the copyright holders give permission to link the
18+
* code of portions of this program with the OpenSSL library under certain
19+
* conditions as described in each individual source file and distribute
20+
* linked combinations including the program with the OpenSSL library. You
21+
* must comply with the Server Side Public License in all respects for
22+
* all of the code used other than as permitted herein. If you modify file(s)
23+
* with this exception, you may extend this exception to your version of the
24+
* file(s), but you are not obligated to do so. If you do not wish to do so,
25+
* delete this exception statement from your version. If you delete this
26+
* exception statement from all source files in the program, then also delete
27+
* it in the license file.
28+
*/
29+
30+
#include "mongo/db/catalog/index_catalog_entry_helpers.h"
31+
32+
#include "mongo/db/index/wildcard_access_method.h"
33+
#include "mongo/db/query/planner_ixselect.h"
34+
35+
namespace mongo::index_catalog_helpers {
36+
37+
void computeUpdateIndexData(const IndexCatalogEntry* entry,
38+
const IndexAccessMethod* accessMethod,
39+
UpdateIndexData* outData) {
40+
const IndexDescriptor* descriptor = entry->descriptor();
41+
if (descriptor->getAccessMethodName() == IndexNames::WILDCARD) {
42+
// Obtain the projection used by the $** index's key generator.
43+
const auto* pathProj = static_cast<const IndexPathProjection*>(
44+
static_cast<const WildcardAccessMethod*>(accessMethod)->getWildcardProjection());
45+
// If the projection is an exclusion, then we must check the new document's keys on all
46+
// updates, since we do not exhaustively know the set of paths to be indexed.
47+
if (pathProj->exec()->getType() ==
48+
TransformerInterface::TransformerType::kExclusionProjection) {
49+
outData->setAllPathsIndexed();
50+
} else {
51+
// If a subtree was specified in the keyPattern, or if an inclusion projection is
52+
// present, then we need only index the path(s) preserved by the projection.
53+
const auto& exhaustivePaths = pathProj->exhaustivePaths();
54+
invariant(exhaustivePaths);
55+
for (const auto& path : *exhaustivePaths) {
56+
outData->addPath(path);
57+
}
58+
59+
// Handle regular index fields of Compound Wildcard Index.
60+
BSONObj key = descriptor->keyPattern();
61+
BSONObjIterator j(key);
62+
while (j.more()) {
63+
StringData fieldName(j.next().fieldName());
64+
if (!fieldName.endsWith("$**"_sd)) {
65+
outData->addPath(FieldRef{fieldName});
66+
}
67+
}
68+
}
69+
} else if (descriptor->getAccessMethodName() == IndexNames::TEXT) {
70+
fts::FTSSpec ftsSpec(descriptor->infoObj());
71+
72+
if (ftsSpec.wildcard()) {
73+
outData->setAllPathsIndexed();
74+
} else {
75+
for (size_t i = 0; i < ftsSpec.numExtraBefore(); ++i) {
76+
outData->addPath(FieldRef(ftsSpec.extraBefore(i)));
77+
}
78+
for (fts::Weights::const_iterator it = ftsSpec.weights().begin();
79+
it != ftsSpec.weights().end();
80+
++it) {
81+
outData->addPath(FieldRef(it->first));
82+
}
83+
for (size_t i = 0; i < ftsSpec.numExtraAfter(); ++i) {
84+
outData->addPath(FieldRef(ftsSpec.extraAfter(i)));
85+
}
86+
// Any update to a path containing "language" as a component could change the
87+
// language of a subdocument. Add the override field as a path component.
88+
outData->addPathComponent(ftsSpec.languageOverrideField());
89+
}
90+
} else {
91+
BSONObj key = descriptor->keyPattern();
92+
BSONObjIterator j(key);
93+
while (j.more()) {
94+
BSONElement e = j.next();
95+
outData->addPath(FieldRef(e.fieldName()));
96+
}
97+
}
98+
99+
// handle partial indexes
100+
const MatchExpression* filter = entry->getFilterExpression();
101+
if (filter) {
102+
RelevantFieldIndexMap paths;
103+
QueryPlannerIXSelect::getFields(filter, &paths);
104+
for (auto it = paths.begin(); it != paths.end(); ++it) {
105+
outData->addPath(FieldRef(it->first));
106+
}
107+
}
108+
}
109+
110+
} // namespace mongo::index_catalog_helpers
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/**
2+
* Copyright (C) 2025-present MongoDB, Inc.
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the Server Side Public License, version 1,
6+
* as published by MongoDB, Inc.
7+
*
8+
* This program is distributed in the hope that it will be useful,
9+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
* Server Side Public License for more details.
12+
*
13+
* You should have received a copy of the Server Side Public License
14+
* along with this program. If not, see
15+
* <http://www.mongodb.com/licensing/server-side-public-license>.
16+
*
17+
* As a special exception, the copyright holders give permission to link the
18+
* code of portions of this program with the OpenSSL library under certain
19+
* conditions as described in each individual source file and distribute
20+
* linked combinations including the program with the OpenSSL library. You
21+
* must comply with the Server Side Public License in all respects for
22+
* all of the code used other than as permitted herein. If you modify file(s)
23+
* with this exception, you may extend this exception to your version of the
24+
* file(s), but you are not obligated to do so. If you do not wish to do so,
25+
* delete this exception statement from your version. If you delete this
26+
* exception statement from all source files in the program, then also delete
27+
* it in the license file.
28+
*/
29+
30+
#include "mongo/db/catalog/index_catalog_entry.h"
31+
#include "mongo/db/index/index_access_method.h"
32+
#include "mongo/db/update_index_data.h"
33+
34+
namespace mongo::index_catalog_helpers {
35+
36+
/**
37+
* Populate the outData structure using the index keys found in the index definition.
38+
*/
39+
void computeUpdateIndexData(const IndexCatalogEntry* entry,
40+
const IndexAccessMethod* accessMethod,
41+
UpdateIndexData* outData);
42+
43+
} // namespace mongo::index_catalog_helpers

src/mongo/db/catalog/index_catalog_entry_impl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include "mongo/bson/bsonobjbuilder.h"
4848
#include "mongo/bson/timestamp.h"
4949
#include "mongo/db/catalog/collection.h"
50+
#include "mongo/db/catalog/index_catalog_entry_helpers.h"
5051
#include "mongo/db/client.h"
5152
#include "mongo/db/concurrency/exception_util.h"
5253
#include "mongo/db/concurrency/lock_manager_defs.h"
@@ -149,7 +150,7 @@ IndexCatalogEntryImpl::~IndexCatalogEntryImpl() = default;
149150
void IndexCatalogEntryImpl::setAccessMethod(std::unique_ptr<IndexAccessMethod> accessMethod) {
150151
invariant(!_shared->_accessMethod);
151152
_shared->_accessMethod = std::move(accessMethod);
152-
CollectionQueryInfo::computeUpdateIndexData(
153+
index_catalog_helpers::computeUpdateIndexData(
153154
this, _shared->_accessMethod.get(), &_shared->_indexedPaths);
154155
}
155156

src/mongo/db/query/collection_query_info_test.cpp renamed to src/mongo/db/catalog/index_catalog_entry_impl_test.cpp

Lines changed: 10 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright (C) 2023-present MongoDB, Inc.
2+
* Copyright (C) 2025-present MongoDB, Inc.
33
*
44
* This program is free software: you can redistribute it and/or modify
55
* it under the terms of the Server Side Public License, version 1,
@@ -27,40 +27,13 @@
2727
* it in the license file.
2828
*/
2929

30-
#include <string>
31-
32-
#include <boost/move/utility_core.hpp>
33-
34-
#include "mongo/base/string_data.h"
35-
#include "mongo/bson/bsonmisc.h"
36-
#include "mongo/bson/bsonobj.h"
37-
#include "mongo/bson/bsonobjbuilder.h"
38-
#include "mongo/bson/ordering.h"
39-
#include "mongo/crypto/encryption_fields_gen.h"
40-
#include "mongo/db/catalog/clustered_collection_options_gen.h"
41-
#include "mongo/db/catalog/collection_options.h"
42-
#include "mongo/db/field_ref.h"
43-
#include "mongo/db/index/index_access_method.h"
44-
#include "mongo/db/index/index_descriptor.h"
45-
#include "mongo/db/index/multikey_paths.h"
30+
#include "mongo/db/catalog/catalog_test_fixture.h"
31+
#include "mongo/db/catalog/index_catalog_entry_helpers.h"
4632
#include "mongo/db/index/wildcard_access_method.h"
47-
#include "mongo/db/index_names.h"
48-
#include "mongo/db/matcher/expression.h"
49-
#include "mongo/db/namespace_string.h"
50-
#include "mongo/db/query/collation/collator_interface.h"
51-
#include "mongo/db/query/collection_query_info.h"
5233
#include "mongo/db/storage/devnull/devnull_kv_engine.h"
53-
#include "mongo/db/storage/ident.h"
54-
#include "mongo/db/storage/key_string/key_string.h"
55-
#include "mongo/db/storage/sorted_data_interface.h"
56-
#include "mongo/db/timeseries/timeseries_gen.h"
57-
#include "mongo/idl/server_parameter_test_util.h"
58-
#include "mongo/unittest/assert.h"
59-
#include "mongo/unittest/framework.h"
60-
#include "mongo/util/assert_util.h"
61-
#include "mongo/util/uuid.h"
6234

6335
namespace mongo {
36+
6437
namespace {
6538

6639
class IndexCatalogEntryMock : public IndexCatalogEntry {
@@ -195,7 +168,9 @@ std::unique_ptr<IndexDescriptor> makeIndexDescriptor(StringData indexName,
195168
return std::make_unique<IndexDescriptor>(accessMethodName, std::move(indexSpec));
196169
}
197170

198-
TEST(CollectionQueryInfoTest, computeUpdateIndexDataForCompoundWildcardIndex) {
171+
} // namespace
172+
173+
TEST(IndexCatalogEntryTest, computeUpdateIndexDataForCompoundWildcardIndex) {
199174
NamespaceString nss = NamespaceString::createNamespaceString_forTest("test"_sd);
200175
CollectionOptions collOptions{};
201176
DevNullKVEngine engine{};
@@ -211,7 +186,7 @@ TEST(CollectionQueryInfoTest, computeUpdateIndexDataForCompoundWildcardIndex) {
211186

212187
WildcardAccessMethod accessMethod{&indexCatalogEntry, std::move(sortedDataInterface)};
213188
UpdateIndexData outData{};
214-
CollectionQueryInfo::computeUpdateIndexData(&indexCatalogEntry, &accessMethod, &outData);
189+
index_catalog_helpers::computeUpdateIndexData(&indexCatalogEntry, &accessMethod, &outData);
215190

216191
// Asserting that expected fields are included.
217192
ASSERT_TRUE(outData.mightBeIndexed(FieldRef{"a"_sd}));
@@ -224,7 +199,7 @@ TEST(CollectionQueryInfoTest, computeUpdateIndexDataForCompoundWildcardIndex) {
224199
ASSERT_FALSE(outData.mightBeIndexed(FieldRef{"$**"_sd}));
225200
}
226201

227-
TEST(CollectionQueryInfoTest, computeUpdateIndexDataForCompoundWildcardIndex_ExcludeCase) {
202+
TEST(IndexCatalogEntryTest, computeUpdateIndexDataForCompoundWildcardIndex_ExcludeCase) {
228203
NamespaceString nss = NamespaceString::createNamespaceString_forTest("test"_sd);
229204
CollectionOptions collOptions{};
230205
DevNullKVEngine engine{};
@@ -240,7 +215,7 @@ TEST(CollectionQueryInfoTest, computeUpdateIndexDataForCompoundWildcardIndex_Exc
240215

241216
WildcardAccessMethod accessMethod{&indexCatalogEntry, std::move(sortedDataInterface)};
242217
UpdateIndexData outData{};
243-
CollectionQueryInfo::computeUpdateIndexData(&indexCatalogEntry, &accessMethod, &outData);
218+
index_catalog_helpers::computeUpdateIndexData(&indexCatalogEntry, &accessMethod, &outData);
244219

245220
// When wildcardProjection has exclusion, everything is "indexed", since we don't know for sure,
246221
// which fields are indexed.
@@ -251,5 +226,4 @@ TEST(CollectionQueryInfoTest, computeUpdateIndexDataForCompoundWildcardIndex_Exc
251226
ASSERT_TRUE(outData.mightBeIndexed(FieldRef{"_id"_sd}));
252227
}
253228

254-
} // namespace
255229
} // namespace mongo

src/mongo/db/collection_index_usage_tracker.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,19 @@ void CollectionIndexUsageTracker::unregisterIndex(StringData indexName) {
112112
_indexUsageStatsMap.erase(it);
113113
}
114114

115+
void CollectionIndexUsageTracker::recordCollectionIndexUsage(
116+
long long collectionScans,
117+
long long collectionScansNonTailable,
118+
const std::set<std::string>& indexesUsed) const {
119+
recordCollectionScans(collectionScans);
120+
recordCollectionScansNonTailable(collectionScansNonTailable);
121+
122+
// Record indexes used to fulfill query.
123+
for (auto it = indexesUsed.begin(); it != indexesUsed.end(); ++it) {
124+
recordIndexAccess(*it);
125+
}
126+
}
127+
115128
const CollectionIndexUsageTracker::CollectionIndexUsageMap&
116129
CollectionIndexUsageTracker::getUsageStats() const {
117130
return _indexUsageStatsMap;

src/mongo/db/collection_index_usage_tracker.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,13 @@ class CollectionIndexUsageTracker
170170
void recordCollectionScans(unsigned long long collectionScans) const;
171171
void recordCollectionScansNonTailable(unsigned long long collectionScansNonTailable) const;
172172

173+
/**
174+
* Helper method to notify all metrics of a collection in a single call.
175+
*/
176+
void recordCollectionIndexUsage(long long collectionScans,
177+
long long collectionScansNonTailable,
178+
const std::set<std::string>& indexesUsed) const;
179+
173180
private:
174181
// Maps index name to index usage statistics.
175182
CollectionIndexUsageMap _indexUsageStatsMap;

src/mongo/db/commands/query_cmd/count_cmd.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767
#include "mongo/db/pipeline/aggregation_request_helper.h"
6868
#include "mongo/db/pipeline/query_request_conversion.h"
6969
#include "mongo/db/query/client_cursor/collect_query_stats_mongod.h"
70-
#include "mongo/db/query/collection_query_info.h"
70+
#include "mongo/db/query/collection_index_usage_tracker_decoration.h"
7171
#include "mongo/db/query/count_command_gen.h"
7272
#include "mongo/db/query/explain.h"
7373
#include "mongo/db/query/explain_options.h"
@@ -410,7 +410,10 @@ class CmdCount : public CountCmdVersion1Gen<CmdCount> {
410410
PlanSummaryStats summaryStats;
411411
exec.getPlanExplainer().getSummaryStats(&summaryStats);
412412
if (collection) {
413-
CollectionQueryInfo::get(collection).notifyOfQuery(opCtx, collection, summaryStats);
413+
CollectionIndexUsageTrackerDecoration::get(collection.get())
414+
.recordCollectionIndexUsage(summaryStats.collectionScans,
415+
summaryStats.collectionScansNonTailable,
416+
summaryStats.indexesUsed);
414417
}
415418
curOp->debug().setPlanSummaryMetrics(std::move(summaryStats));
416419
curOp->setEndOfOpMetrics(kNReturned);

0 commit comments

Comments
 (0)