SERVER-3373 query optimizer optimizations, primarily for non or queries

This commit is contained in:
Aaron
2011-08-02 20:32:42 -07:00
parent 53a69ce6c9
commit d58c4c23f6
6 changed files with 119 additions and 99 deletions

View File

@@ -158,8 +158,10 @@ namespace mongo {
FieldRange::FieldRange( const BSONElement &e, bool singleKey, bool isNot, bool optimize )
: _singleKey( singleKey ) {
int op = e.getGtLtOp();
// NOTE with $not, we could potentially form a complementary set of intervals.
if ( !isNot && !e.eoo() && e.type() != RegEx && e.getGtLtOp() == BSONObj::opIN ) {
if ( !isNot && !e.eoo() && e.type() != RegEx && op == BSONObj::opIN ) {
set<BSONElement,element_lt> vals;
vector<FieldRange> regexes;
uassert( 12580 , "invalid query" , e.isABSONObj() );
@@ -196,7 +198,7 @@ namespace mongo {
// A document array may be indexed by its first element, by undefined
// if it is empty, or as a full array if it is embedded within another
// array.
if ( e.type() == Array && e.getGtLtOp() == BSONObj::Equality ) {
if ( e.type() == Array && op == BSONObj::Equality ) {
_intervals.push_back( FieldInterval(e) );
BSONElement temp = e.embeddedObject().firstElement();
@@ -227,8 +229,6 @@ namespace mongo {
if ( e.eoo() )
return;
int op = e.getGtLtOp();
bool existsSpec = false;
if ( op == BSONObj::opEXISTS ) {
existsSpec = e.trueValue();
@@ -785,30 +785,32 @@ namespace mongo {
}
void FieldRangeSet::processQueryField( const BSONElement &e, bool optimize ) {
if ( strcmp( e.fieldName(), "$and" ) == 0 ) {
uassert( 14816 , "$and expression must be a nonempty array" , e.type() == Array && e.embeddedObject().nFields() > 0 );
BSONObjIterator i( e.embeddedObject() );
while( i.more() ) {
BSONElement e = i.next();
uassert( 14817 , "$and elements must be objects" , e.type() == Object );
BSONObjIterator j( e.embeddedObject() );
while( j.more() ) {
processQueryField( j.next(), optimize );
}
}
}
if ( e.fieldName()[ 0 ] == '$' ) {
if ( strcmp( e.fieldName(), "$and" ) == 0 ) {
uassert( 14816 , "$and expression must be a nonempty array" , e.type() == Array && e.embeddedObject().nFields() > 0 );
BSONObjIterator i( e.embeddedObject() );
while( i.more() ) {
BSONElement e = i.next();
uassert( 14817 , "$and elements must be objects" , e.type() == Object );
BSONObjIterator j( e.embeddedObject() );
while( j.more() ) {
processQueryField( j.next(), optimize );
}
}
}
if ( strcmp( e.fieldName(), "$where" ) == 0 ) {
return;
}
if ( strcmp( e.fieldName(), "$where" ) == 0 ) {
return;
}
if ( strcmp( e.fieldName(), "$or" ) == 0 ) {
return;
}
if ( strcmp( e.fieldName(), "$or" ) == 0 ) {
return;
}
if ( strcmp( e.fieldName(), "$nor" ) == 0 ) {
return;
}
if ( strcmp( e.fieldName(), "$nor" ) == 0 ) {
return;
}
}
bool equality = ( getGtLtOp( e ) == BSONObj::Equality );
if ( equality && e.type() == Object ) {
@@ -1067,32 +1069,11 @@ namespace mongo {
return ret;
}
const FieldRangeSet &FieldRangeSetPair::frsForIndex( const NamespaceDetails* nsd, int idxNo ) const {
assertValidIndexOrNoIndex( nsd, idxNo );
if ( idxNo < 0 ) {
// An unindexed cursor cannot have a "single key" constraint.
return _multiKey;
}
return nsd->isMultikey( idxNo ) ? _multiKey : _singleKey;
}
bool FieldRangeSetPair::noNontrivialRanges() const {
return _singleKey.matchPossible() && _singleKey.nNontrivialRanges() == 0 &&
_multiKey.matchPossible() && _multiKey.nNontrivialRanges() == 0;
}
bool FieldRangeSetPair::matchPossibleForIndex( NamespaceDetails *d, int idxNo, const BSONObj &keyPattern ) const {
assertValidIndexOrNoIndex( d, idxNo );
if ( !matchPossible() ) {
return false;
}
if ( idxNo < 0 ) {
// multi key matchPossible() is true, so return true.
return true;
}
return frsForIndex( d, idxNo ).matchPossibleForIndex( keyPattern );
}
FieldRangeSetPair &FieldRangeSetPair::operator&=( const FieldRangeSetPair &other ) {
_singleKey &= other._singleKey;
_multiKey &= other._multiKey;
@@ -1105,21 +1086,23 @@ namespace mongo {
return *this;
}
void FieldRangeSetPair::assertValidIndex( const NamespaceDetails *d, int idxNo ) const {
massert( 14048, "FieldRangeSetPair invalid index specified", idxNo >= 0 && idxNo < d->nIndexes );
}
void FieldRangeSetPair::assertValidIndexOrNoIndex( const NamespaceDetails *d, int idxNo ) const {
massert( 14049, "FieldRangeSetPair invalid index specified", idxNo >= -1 );
if ( idxNo >= 0 ) {
assertValidIndex( d, idxNo );
}
}
BSONObj FieldRangeSetPair::simplifiedQueryForIndex( NamespaceDetails *d, int idxNo, const BSONObj &keyPattern ) const {
return frsForIndex( d, idxNo ).simplifiedQuery( keyPattern );
}
void FieldRangeSetPair::assertValidIndex( const NamespaceDetails *d, int idxNo ) const {
massert( 14048, "FieldRangeSetPair invalid index specified", idxNo >= 0 && idxNo < d->nIndexes );
}
const FieldRangeSet &FieldRangeSetPair::frsForIndex( const NamespaceDetails* nsd, int idxNo ) const {
assertValidIndexOrNoIndex( nsd, idxNo );
if ( idxNo < 0 ) {
// An unindexed cursor cannot have a "single key" constraint.
return _multiKey;
}
return nsd->isMultikey( idxNo ) ? _multiKey : _singleKey;
}
bool FieldRangeVector::matchesElement( const BSONElement &e, int i, bool forward ) const {
bool eq;
int l = matchingLowElement( e, i, forward, eq );