0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-12-01 09:32:32 +01:00

SERVER-802 some optimizations

This commit is contained in:
Aaron 2010-07-16 09:45:59 -07:00
parent 326babfe6d
commit 5e2fa26dd7
3 changed files with 86 additions and 47 deletions

View File

@ -63,8 +63,9 @@ namespace mongo {
audit();
startKey = bounds_->startKey();
bool found;
_boundsIterator->advance( startKey ); // handles initialization
bucket = indexDetails.head.btree()->
locate(indexDetails, indexDetails.head, startKey, _ordering, keyOfs, found, direction > 0 ? minDiskLoc : maxDiskLoc, direction);
locate(indexDetails, indexDetails.head, startKey, _ordering, keyOfs, found, direction > 0 ? minDiskLoc : maxDiskLoc, direction);
skipAndCheck();
DEV assert( dups.size() == 0 );
}
@ -165,16 +166,6 @@ namespace mongo {
}
void BtreeCursor::advanceTo( const BSONObj &keyBegin, int keyBeginLen, const vector< const BSONElement * > &keyEnd) {
// log() << "curr: " << currKey() << ", advancing to: ";
// BSONObjIterator boi( keyBegin );
// int i;
// for( i = 0; i < keyBeginLen; ++i ) {
// log() << ", " << boi.next();
// }
// for( ;i < (int)keyEnd.size(); ++i ) {
// log() << ", " << *keyEnd[ i ];
// }
// log() << endl;
bucket.btree()->advanceTo( indexDetails, bucket, keyOfs, keyBegin, keyBeginLen, keyEnd, _ordering, direction );
}

View File

@ -932,6 +932,11 @@ namespace mongo {
}
bool FieldRangeVector::matchesElement( const BSONElement &e, int i, bool forward ) const {
int l = matchingLowElement( e, i, forward );
return ( l % 2 == 0 ); // if we're inside an interval
}
int FieldRangeVector::matchingLowElement( const BSONElement &e, int i, bool forward ) const {
int l = -1;
int h = _ranges[ i ].intervals().size() * 2;
while( l + 1 < h ) {
@ -951,11 +956,11 @@ namespace mongo {
} else if ( cmp > 0 ) {
h = m;
} else {
return true;
return ( m % 2 == 0 ) ? m : m - 1;
}
}
assert( l + 1 == h );
return ( l % 2 == 0 ); // if we're inside an interval
return l;
}
bool FieldRangeVector::matches( const BSONObj &obj ) const {
@ -966,7 +971,7 @@ namespace mongo {
}
BSONElement kk = k.next();
int number = (int) kk.number();
bool forward = ( ( number >= 0 ? 1 : -1 ) * ( _direction >= 0 ? 1 : -1 ) > 0 );
bool forward = ( ( number >= 0 ? 1 : -1 ) * ( _direction >= 0 ? 1 : -1 ) > 0 ) >= 0;
BSONElement e = obj.getField( kk.fieldName() );
if ( e.eoo() ) {
e = staticNull.firstElement();
@ -990,53 +995,88 @@ namespace mongo {
return true;
}
// TODO optimize more
int FieldRangeVector::Iterator::advance( const BSONObj &curr ) {
BSONObjIterator j( curr );
BSONObjIterator o( _v._keyPattern );
int latestNonEndpoint = -1;
// log() << "direction: " << _v._direction << endl;
// log() << "curr: " << curr << endl;
// log() << "query: " << _v._queries[ 0 ] << endl;
for( int i = 0; i < (int)_i.size(); ++i ) {
// log() << "a i: " << i << endl;
if ( i > 0 && !_v._ranges[ i - 1 ].intervals()[ _i[ i - 1 ] ].equality() ) {
// TODO if possible avoid this certain cases when field in prev key is the same
setMinus( i );
}
bool eq = false;
BSONElement jj = j.next();
BSONElement oo = o.next();
while( _i[ i ] < (int)_v._ranges[ i ].intervals().size() ) {
// cout << "a _i[ i ]: " << _i[ i ] << endl;
// cout << "lower: " << _v._ranges[ i ].intervals()[ _i[ i ] ]._lower._bound << endl;
// cout << "upper: " << _v._ranges[ i ].intervals()[ _i[ i ] ]._upper._bound << endl;
int x = _v._ranges[ i ].intervals()[ _i[ i ] ]._lower._bound.woCompare( jj, false );
if ( ( oo.number() < 0 ) ^ ( _v._direction < 0 ) ) {
x = -x;
}
// cout << "x: " << x << endl;
if ( x > 0 ) {
setZero( i + 1 );
bool reverse = ( ( oo.number() < 0 ) ^ ( _v._direction < 0 ) );
BSONElement jj = j.next();
if ( _i[ i ] == -1 ) {
int l = _v.matchingLowElement( jj, i, !reverse );
if ( l % 2 == 0 ) {
_i[ i ] = l / 2;
int diff = (int)_v._ranges[ i ].intervals().size() - _i[ i ];
if ( diff > 1 ) {
latestNonEndpoint = i;
} else if ( diff == 1 ) {
int x = _v._ranges[ i ].intervals()[ _i[ i ] ]._upper._bound.woCompare( jj, false );
if ( x != 0 ) {
latestNonEndpoint = i;
}
}
continue;
} else {
if ( l == (int)_v._ranges[ i ].intervals().size() * 2 - 1 ) {
if ( latestNonEndpoint == -1 ) {
return -2;
}
setZero( latestNonEndpoint + 1 );
// skip to curr / latestNonEndpoint + 1 / superlative
for( int j = latestNonEndpoint + 1; j < (int)_i.size(); ++j ) {
_cmp[ j ] = _superlative[ j ];
}
return latestNonEndpoint + 1;
}
_i[ i ] = ( l + 1 ) / 2;
// skip to curr / i / nextbounds
_cmp[ i ] = &_v._ranges[ i ].intervals()[ _i[ i ] ]._lower._bound;
for( int j = i + 1; j < (int)_i.size(); ++j ) {
_cmp[ j ] = &_v._ranges[ j ].intervals().front()._lower._bound;
}
return i;
return i;
}
x = _v._ranges[ i ].intervals()[ _i[ i ] ]._upper._bound.woCompare( jj, false );
if ( ( oo.number() < 0 ) ^ ( _v._direction < 0 ) ) {
}
while( _i[ i ] < (int)_v._ranges[ i ].intervals().size() ) {
int x = _v._ranges[ i ].intervals()[ _i[ i ] ]._upper._bound.woCompare( jj, false );
if ( reverse ) {
x = -x;
}
// cout << "x: " << x << endl;
if ( x >= 0 ) {
if ( x == 0 ) {
eq = true;
}
if ( x == 0 ) {
eq = true;
break;
}
if ( x > 0 ) {
if ( !_v._ranges[ i ].intervals()[ _i[ i ] ].equality() ) {
x = _v._ranges[ i ].intervals()[ _i[ i ] ]._lower._bound.woCompare( jj, false );
if ( reverse ) {
x = -x;
}
}
if ( x > 0 ) {
setZero( i + 1 );
// skip to curr / i / nextbounds
_cmp[ i ] = &_v._ranges[ i ].intervals()[ _i[ i ] ]._lower._bound;
for( int j = i + 1; j < (int)_i.size(); ++j ) {
_cmp[ j ] = &_v._ranges[ j ].intervals().front()._lower._bound;
}
return i;
} else {
break;
}
}
++_i[ i ];
setZero( i + 1 );
// mark need to check lower bound?
}
int diff = (int)_v._ranges[ i ].intervals().size() - _i[ i ];
// log() << "a diff: " << diff << endl;
if ( diff > 1 || ( !eq && diff == 1 ) ) {
latestNonEndpoint = i;
} else if ( diff == 0 ) {
@ -1050,10 +1090,6 @@ namespace mongo {
}
return latestNonEndpoint + 1;
}
if ( !_v._ranges[ i ].intervals()[ _i[ i ] ].equality() ) {
// todo don't zero it if already have
setZero( i + 1 );
}
}
return -1;
}

View File

@ -32,8 +32,8 @@ namespace mongo {
};
struct FieldInterval {
FieldInterval(){}
FieldInterval( const BSONElement& e ){
FieldInterval() : _cachedEquality( -1 ) {}
FieldInterval( const BSONElement& e ) : _cachedEquality( -1 ) {
_lower._bound = _upper._bound = e;
_lower._inclusive = _upper._inclusive = true;
}
@ -43,7 +43,13 @@ namespace mongo {
int cmp = _lower._bound.woCompare( _upper._bound, false );
return ( cmp < 0 || ( cmp == 0 && _lower._inclusive && _upper._inclusive ) );
}
bool equality() const { return _lower._inclusive && _upper._inclusive && _lower._bound.woCompare( _upper._bound, false ) == 0; }
bool equality() const {
if ( _cachedEquality == -1 ) {
_cachedEquality = ( _lower._inclusive && _upper._inclusive && _lower._bound.woCompare( _upper._bound, false ) == 0 );
}
return _cachedEquality;
}
mutable int _cachedEquality;
};
// range of a field's value that may be determined from query -- used to
@ -346,7 +352,7 @@ namespace mongo {
bool matches( const BSONObj &obj ) const;
class Iterator {
public:
Iterator( const FieldRangeVector &v ) : _v( v ), _i( _v._ranges.size(), 0 ), _cmp( _v._ranges.size(), 0 ), _superlative( _v._ranges.size(), 0 ) {
Iterator( const FieldRangeVector &v ) : _v( v ), _i( _v._ranges.size(), -1 ), _cmp( _v._ranges.size(), 0 ), _superlative( _v._ranges.size(), 0 ) {
static BSONObj minObj = minObject();
static BSONElement minElt = minObj.firstElement();
static BSONObj maxObj = maxObject();
@ -394,6 +400,11 @@ namespace mongo {
_i[ j ] = 0;
}
}
void setMinus( int i ) {
for( int j = i; j < (int)_i.size(); ++j ) {
_i[ j ] = -1;
}
}
bool ok() {
return _i[ 0 ] < (int)_v._ranges[ 0 ].intervals().size();
}
@ -422,6 +433,7 @@ namespace mongo {
vector< const BSONElement* > _superlative;
};
private:
int matchingLowElement( const BSONElement &e, int i, bool direction ) const;
bool matchesElement( const BSONElement &e, int i, bool direction ) const;
vector< FieldRange > _ranges;
BSONObj _keyPattern;