1
0
Fork 0

Feature/mmfiles index lookup speedup (#5329)

This commit is contained in:
Jan 2018-05-12 10:21:12 +02:00 committed by GitHub
parent 4703049c4e
commit 4df1c81e9b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 114 additions and 65 deletions

View File

@ -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();

View File

@ -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 {

View File

@ -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

View File

@ -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;

View File

@ -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()) {

View File

@ -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;