mirror of https://gitee.com/bigwinds/arangodb
Feature/mmfiles index lookup speedup (#5329)
This commit is contained in:
parent
4703049c4e
commit
4df1c81e9b
|
@ -118,6 +118,57 @@ bool MMFilesEdgeIndexIterator::next(LocalDocumentIdCallback const& cb, size_t li
|
|||
return true;
|
||||
}
|
||||
|
||||
bool MMFilesEdgeIndexIterator::nextDocument(DocumentCallback const& cb, size_t limit) {
|
||||
_documentIds.clear();
|
||||
_documentIds.reserve(limit);
|
||||
|
||||
if (limit == 0 || (_buffer.empty() && !_iterator.valid())) {
|
||||
// No limit no data, or we are actually done. The last call should have
|
||||
// returned false
|
||||
TRI_ASSERT(limit > 0); // Someone called with limit == 0. Api broken
|
||||
return false;
|
||||
}
|
||||
|
||||
bool done = false;
|
||||
while (limit > 0) {
|
||||
if (_buffer.empty()) {
|
||||
// We start a new lookup
|
||||
_posInBuffer = 0;
|
||||
|
||||
VPackSlice tmp = _iterator.value();
|
||||
if (tmp.isObject()) {
|
||||
tmp = tmp.get(StaticStrings::IndexEq);
|
||||
}
|
||||
_index->lookupByKey(&_context, &tmp, _buffer, _batchSize);
|
||||
} else if (_posInBuffer >= _buffer.size()) {
|
||||
// We have to refill the buffer
|
||||
_buffer.clear();
|
||||
|
||||
_posInBuffer = 0;
|
||||
_index->lookupByKeyContinue(&_context, _lastElement, _buffer, _batchSize);
|
||||
}
|
||||
|
||||
if (_buffer.empty()) {
|
||||
_iterator.next();
|
||||
_lastElement = MMFilesSimpleIndexElement();
|
||||
if (!_iterator.valid()) {
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
_lastElement = _buffer.back();
|
||||
// found something
|
||||
TRI_ASSERT(_posInBuffer < _buffer.size());
|
||||
_documentIds.emplace_back(std::make_pair(_buffer[_posInBuffer++].localDocumentId(), nullptr));
|
||||
limit--;
|
||||
}
|
||||
}
|
||||
|
||||
auto physical = static_cast<MMFilesCollection*>(_collection->getPhysical());
|
||||
physical->readDocumentWithCallback(_trx, _documentIds, cb);
|
||||
return !done;
|
||||
}
|
||||
|
||||
void MMFilesEdgeIndexIterator::reset() {
|
||||
_posInBuffer = 0;
|
||||
_buffer.clear();
|
||||
|
|
|
@ -125,6 +125,7 @@ class MMFilesEdgeIndexIterator final : public IndexIterator {
|
|||
char const* typeName() const override { return "edge-index-iterator"; }
|
||||
|
||||
bool next(LocalDocumentIdCallback const& cb, size_t limit) override;
|
||||
bool nextDocument(DocumentCallback const& cb, size_t limit) override;
|
||||
|
||||
void reset() override;
|
||||
|
||||
|
@ -138,6 +139,7 @@ class MMFilesEdgeIndexIterator final : public IndexIterator {
|
|||
size_t _posInBuffer;
|
||||
size_t _batchSize;
|
||||
MMFilesSimpleIndexElement _lastElement;
|
||||
std::vector<std::pair<LocalDocumentId, uint8_t const*>> _documentIds;
|
||||
};
|
||||
|
||||
class MMFilesEdgeIndex final : public MMFilesIndex {
|
||||
|
|
|
@ -249,68 +249,44 @@ bool MMFilesHashIndexIterator::next(LocalDocumentIdCallback const& cb, size_t li
|
|||
return true;
|
||||
}
|
||||
|
||||
void MMFilesHashIndexIterator::reset() {
|
||||
_buffer.clear();
|
||||
_posInBuffer = 0;
|
||||
_lookups.reset();
|
||||
_index->lookup(_trx, _lookups.lookup(), _buffer);
|
||||
}
|
||||
bool MMFilesHashIndexIterator::nextDocument(DocumentCallback const& cb, size_t limit) {
|
||||
_documentIds.clear();
|
||||
_documentIds.reserve(limit);
|
||||
|
||||
MMFilesHashIndexIteratorVPack::MMFilesHashIndexIteratorVPack(
|
||||
LogicalCollection* collection, transaction::Methods* trx,
|
||||
MMFilesHashIndex const* index,
|
||||
std::unique_ptr<arangodb::velocypack::Builder> searchValues)
|
||||
: IndexIterator(collection, trx, index),
|
||||
_index(index),
|
||||
_searchValues(std::move(searchValues)),
|
||||
_iterator(_searchValues->slice()),
|
||||
_buffer(),
|
||||
_posInBuffer(0) {
|
||||
}
|
||||
|
||||
MMFilesHashIndexIteratorVPack::~MMFilesHashIndexIteratorVPack() {
|
||||
if (_searchValues != nullptr) {
|
||||
// return the VPackBuilder to the transaction context
|
||||
_trx->transactionContextPtr()->returnBuilder(_searchValues.release());
|
||||
}
|
||||
}
|
||||
|
||||
bool MMFilesHashIndexIteratorVPack::next(LocalDocumentIdCallback const& cb,
|
||||
size_t limit) {
|
||||
bool done = false;
|
||||
while (limit > 0) {
|
||||
if (_posInBuffer >= _buffer.size()) {
|
||||
if (!_iterator.valid()) {
|
||||
if (!_lookups.hasAndGetNext()) {
|
||||
// we're at the end of the lookup values
|
||||
return false;
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// We have to refill the buffer
|
||||
_buffer.clear();
|
||||
_posInBuffer = 0;
|
||||
|
||||
int res = TRI_ERROR_NO_ERROR;
|
||||
_index->lookup(_trx, _iterator.value(), _buffer);
|
||||
_iterator.next();
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
THROW_ARANGO_EXCEPTION(res);
|
||||
}
|
||||
_index->lookup(_trx, _lookups.lookup(), _buffer);
|
||||
}
|
||||
|
||||
if (!_buffer.empty()) {
|
||||
// found something
|
||||
TRI_ASSERT(_posInBuffer < _buffer.size());
|
||||
cb(_buffer[_posInBuffer++]->localDocumentId());
|
||||
_documentIds.emplace_back(std::make_pair(_buffer[_posInBuffer++]->localDocumentId(), nullptr));
|
||||
--limit;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
auto physical = static_cast<MMFilesCollection*>(_collection->getPhysical());
|
||||
physical->readDocumentWithCallback(_trx, _documentIds, cb);
|
||||
return !done;
|
||||
}
|
||||
|
||||
void MMFilesHashIndexIteratorVPack::reset() {
|
||||
void MMFilesHashIndexIterator::reset() {
|
||||
_buffer.clear();
|
||||
_posInBuffer = 0;
|
||||
_iterator.reset();
|
||||
_lookups.reset();
|
||||
_index->lookup(_trx, _lookups.lookup(), _buffer);
|
||||
}
|
||||
|
||||
/// @brief create the unique array
|
||||
|
|
|
@ -217,6 +217,7 @@ class MMFilesHashIndexIterator final : public IndexIterator {
|
|||
char const* typeName() const override { return "hash-index-iterator"; }
|
||||
|
||||
bool next(LocalDocumentIdCallback const& cb, size_t limit) override;
|
||||
bool nextDocument(DocumentCallback const& cb, size_t limit) override;
|
||||
|
||||
void reset() override;
|
||||
|
||||
|
@ -225,35 +226,11 @@ class MMFilesHashIndexIterator final : public IndexIterator {
|
|||
MMFilesHashIndexLookupBuilder _lookups;
|
||||
std::vector<MMFilesHashIndexElement*> _buffer;
|
||||
size_t _posInBuffer;
|
||||
};
|
||||
|
||||
class MMFilesHashIndexIteratorVPack final : public IndexIterator {
|
||||
public:
|
||||
/// @brief Construct an MMFilesHashIndexIterator based on VelocyPack
|
||||
MMFilesHashIndexIteratorVPack(
|
||||
LogicalCollection* collection, transaction::Methods* trx,
|
||||
MMFilesHashIndex const* index,
|
||||
std::unique_ptr<arangodb::velocypack::Builder> searchValues);
|
||||
|
||||
~MMFilesHashIndexIteratorVPack();
|
||||
|
||||
char const* typeName() const override { return "hash-index-iterator-vpack"; }
|
||||
|
||||
bool next(LocalDocumentIdCallback const& cb, size_t limit) override;
|
||||
|
||||
void reset() override;
|
||||
|
||||
private:
|
||||
MMFilesHashIndex const* _index;
|
||||
std::unique_ptr<arangodb::velocypack::Builder> _searchValues;
|
||||
arangodb::velocypack::ArrayIterator _iterator;
|
||||
std::vector<MMFilesHashIndexElement*> _buffer;
|
||||
size_t _posInBuffer;
|
||||
std::vector<std::pair<LocalDocumentId, uint8_t const*>> _documentIds;
|
||||
};
|
||||
|
||||
class MMFilesHashIndex final : public MMFilesPathBasedIndex {
|
||||
friend class MMFilesHashIndexIterator;
|
||||
friend class MMFilesHashIndexIteratorVPack;
|
||||
|
||||
public:
|
||||
MMFilesHashIndex() = delete;
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "Indexes/IndexLookupContext.h"
|
||||
#include "Indexes/IndexResult.h"
|
||||
#include "Indexes/SimpleAttributeEqualityMatcher.h"
|
||||
#include "MMFiles/MMFilesCollection.h"
|
||||
#include "StorageEngine/PhysicalCollection.h"
|
||||
#include "Transaction/Helpers.h"
|
||||
#include "Transaction/Methods.h"
|
||||
|
@ -584,12 +585,52 @@ bool MMFilesSkiplistIterator::next(LocalDocumentIdCallback const& cb, size_t lim
|
|||
}
|
||||
TRI_ASSERT(tmp != nullptr);
|
||||
TRI_ASSERT(tmp->document() != nullptr);
|
||||
|
||||
cb(tmp->document()->localDocumentId());
|
||||
limit--;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MMFilesSkiplistIterator::nextDocument(DocumentCallback const& cb, size_t limit) {
|
||||
_documentIds.clear();
|
||||
_documentIds.reserve(limit);
|
||||
|
||||
bool done = false;
|
||||
while (limit > 0) {
|
||||
if (_cursor == nullptr) {
|
||||
// We are exhausted already, sorry
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
TRI_ASSERT(_currentInterval < _intervals.size());
|
||||
auto const& interval = _intervals[_currentInterval];
|
||||
Node* tmp = _cursor;
|
||||
if (_reverse) {
|
||||
if (_cursor == interval.first) {
|
||||
forwardCursor();
|
||||
} else {
|
||||
_cursor = _cursor->prevNode();
|
||||
}
|
||||
} else {
|
||||
if (_cursor == interval.second) {
|
||||
forwardCursor();
|
||||
} else {
|
||||
_cursor = _cursor->nextNode();
|
||||
}
|
||||
}
|
||||
TRI_ASSERT(tmp != nullptr);
|
||||
TRI_ASSERT(tmp->document() != nullptr);
|
||||
|
||||
_documentIds.emplace_back(std::make_pair(tmp->document()->localDocumentId(), nullptr));
|
||||
limit--;
|
||||
}
|
||||
|
||||
auto physical = static_cast<MMFilesCollection*>(_collection->getPhysical());
|
||||
physical->readDocumentWithCallback(_trx, _documentIds, cb);
|
||||
return !done;
|
||||
}
|
||||
|
||||
void MMFilesSkiplistIterator::forwardCursor() {
|
||||
_currentInterval++;
|
||||
if (_currentInterval < _intervals.size()) {
|
||||
|
|
|
@ -187,6 +187,7 @@ class MMFilesSkiplistIterator final : public IndexIterator {
|
|||
size_t _currentInterval;
|
||||
|
||||
MMFilesBaseSkiplistLookupBuilder* _builder;
|
||||
std::vector<std::pair<LocalDocumentId, uint8_t const*>> _documentIds;
|
||||
|
||||
std::function<int(void*, MMFilesSkiplistIndexElement const*,
|
||||
MMFilesSkiplistIndexElement const*, MMFilesSkiplistCmpType)>
|
||||
|
@ -214,6 +215,7 @@ class MMFilesSkiplistIterator final : public IndexIterator {
|
|||
|
||||
/// @brief Get the next elements in the skiplist
|
||||
bool next(LocalDocumentIdCallback const& cb, size_t limit) override;
|
||||
bool nextDocument(DocumentCallback const& cb, size_t limit) override;
|
||||
|
||||
/// @brief Reset the cursor
|
||||
void reset() override;
|
||||
|
|
Loading…
Reference in New Issue