commit faae89039d43effa5ac30433c0843181e646eae1 Author: CenZheng Date: Mon Mar 23 13:57:19 2020 +0800 optimize getShardIdForRange for query range over[MinKey, Maxkey] diff --git a/src/mongo/bson/bsonobj.cpp b/src/mongo/bson/bsonobj.cpp index 5df0882cb7..970d31efb7 100644 --- a/src/mongo/bson/bsonobj.cpp +++ b/src/mongo/bson/bsonobj.cpp @@ -313,6 +313,19 @@ int BSONObj::getFieldNames(set& fields) const { return n; } +int BSONObj::areAllElemsOfType(BSONType type) const { + BSONObjIterator i(*this); + while (i.moreWithEOO()) { + BSONElement e = i.next(); + if (e.eoo()) + break; + if (e.type() != type) { + return false; + } + } + return true; +} + /* note: addFields always adds _id even if not specified returns n added not counting _id unless requested. */ diff --git a/src/mongo/bson/bsonobj.h b/src/mongo/bson/bsonobj.h index 2e3665ccbe..0ae7e8ed74 100644 --- a/src/mongo/bson/bsonobj.h +++ b/src/mongo/bson/bsonobj.h @@ -286,6 +286,9 @@ public: */ int nFields() const; + /** Are all elements of the specified type */ + int areAllElemsOfType(BSONType type) const ; + /** adds the field names to the fields set. does NOT clear it (appends). */ int getFieldNames(std::set& fields) const; diff --git a/src/mongo/s/chunk_manager.cpp b/src/mongo/s/chunk_manager.cpp index e1432fe408..166e5630f9 100644 --- a/src/mongo/s/chunk_manager.cpp +++ b/src/mongo/s/chunk_manager.cpp @@ -189,6 +189,16 @@ void ChunkManager::getShardIdsForQuery(OperationContext* opCtx, void ChunkManager::getShardIdsForRange(const BSONObj& min, const BSONObj& max, std::set* shardIds) const { + // This optimization does not apply when we are reading from a snapshot + // because _shardVersions contains shards with chunks and is built based on the last + // refresh. Therefore, it is possible for _shardVersions to have fewer entries if a shard + // no longer owns chunks when it used to at _clusterTime. + if (!_clusterTime && + min.areAllElemsOfType(BSONType::MinKey) && + max.areAllElemsOfType(BSONType::MaxKey)) { + getAllShardIds(shardIds); + return; + } const auto bounds = _rt->overlappingRanges(min, max, true); for (auto it = bounds.first; it != bounds.second; ++it) { shardIds->insert(it->second->getShardIdAt(_clusterTime));