mirror of https://gitee.com/bigwinds/arangodb
Feature 3.3/mmfiles index lookup speedup (#5338)
This commit is contained in:
parent
2e840ee5d0
commit
ae73a9b475
|
@ -117,6 +117,57 @@ bool MMFilesEdgeIndexIterator::next(LocalDocumentIdCallback const& cb, size_t li
|
||||||
return true;
|
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() {
|
void MMFilesEdgeIndexIterator::reset() {
|
||||||
_posInBuffer = 0;
|
_posInBuffer = 0;
|
||||||
_buffer.clear();
|
_buffer.clear();
|
||||||
|
|
|
@ -123,6 +123,7 @@ class MMFilesEdgeIndexIterator final : public IndexIterator {
|
||||||
char const* typeName() const override { return "edge-index-iterator"; }
|
char const* typeName() const override { return "edge-index-iterator"; }
|
||||||
|
|
||||||
bool next(LocalDocumentIdCallback const& cb, size_t limit) override;
|
bool next(LocalDocumentIdCallback const& cb, size_t limit) override;
|
||||||
|
bool nextDocument(DocumentCallback const& cb, size_t limit) override;
|
||||||
|
|
||||||
void reset() override;
|
void reset() override;
|
||||||
|
|
||||||
|
@ -134,6 +135,7 @@ class MMFilesEdgeIndexIterator final : public IndexIterator {
|
||||||
size_t _posInBuffer;
|
size_t _posInBuffer;
|
||||||
size_t _batchSize;
|
size_t _batchSize;
|
||||||
MMFilesSimpleIndexElement _lastElement;
|
MMFilesSimpleIndexElement _lastElement;
|
||||||
|
std::vector<std::pair<LocalDocumentId, uint8_t const*>> _documentIds;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MMFilesEdgeIndex final : public MMFilesIndex {
|
class MMFilesEdgeIndex final : public MMFilesIndex {
|
||||||
|
|
|
@ -249,6 +249,39 @@ bool MMFilesHashIndexIterator::next(LocalDocumentIdCallback const& cb, size_t li
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MMFilesHashIndexIterator::nextDocument(DocumentCallback const& cb, size_t limit) {
|
||||||
|
_documentIds.clear();
|
||||||
|
_documentIds.reserve(limit);
|
||||||
|
|
||||||
|
bool done = false;
|
||||||
|
while (limit > 0) {
|
||||||
|
if (_posInBuffer >= _buffer.size()) {
|
||||||
|
if (!_lookups.hasAndGetNext()) {
|
||||||
|
// we're at the end of the lookup values
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have to refill the buffer
|
||||||
|
_buffer.clear();
|
||||||
|
_posInBuffer = 0;
|
||||||
|
|
||||||
|
_index->lookup(_trx, _lookups.lookup(), _buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_buffer.empty()) {
|
||||||
|
// 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 MMFilesHashIndexIterator::reset() {
|
void MMFilesHashIndexIterator::reset() {
|
||||||
_buffer.clear();
|
_buffer.clear();
|
||||||
_posInBuffer = 0;
|
_posInBuffer = 0;
|
||||||
|
|
|
@ -218,6 +218,7 @@ class MMFilesHashIndexIterator final : public IndexIterator {
|
||||||
char const* typeName() const override { return "hash-index-iterator"; }
|
char const* typeName() const override { return "hash-index-iterator"; }
|
||||||
|
|
||||||
bool next(LocalDocumentIdCallback const& cb, size_t limit) override;
|
bool next(LocalDocumentIdCallback const& cb, size_t limit) override;
|
||||||
|
bool nextDocument(DocumentCallback const& cb, size_t limit) override;
|
||||||
|
|
||||||
void reset() override;
|
void reset() override;
|
||||||
|
|
||||||
|
@ -226,6 +227,7 @@ class MMFilesHashIndexIterator final : public IndexIterator {
|
||||||
MMFilesHashIndexLookupBuilder _lookups;
|
MMFilesHashIndexLookupBuilder _lookups;
|
||||||
std::vector<MMFilesHashIndexElement*> _buffer;
|
std::vector<MMFilesHashIndexElement*> _buffer;
|
||||||
size_t _posInBuffer;
|
size_t _posInBuffer;
|
||||||
|
std::vector<std::pair<LocalDocumentId, uint8_t const*>> _documentIds;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MMFilesHashIndexIteratorVPack final : public IndexIterator {
|
class MMFilesHashIndexIteratorVPack final : public IndexIterator {
|
||||||
|
|
|
@ -202,6 +202,94 @@ bool MMFilesPersistentIndexIterator::next(LocalDocumentIdCallback const& cb,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MMFilesPersistentIndexIterator::nextDocument(DocumentCallback const& cb,
|
||||||
|
size_t limit) {
|
||||||
|
_documentIds.clear();
|
||||||
|
_documentIds.reserve(limit);
|
||||||
|
|
||||||
|
auto comparator = MMFilesPersistentIndexFeature::instance()->comparator();
|
||||||
|
bool done = false;
|
||||||
|
while (limit > 0) {
|
||||||
|
if (!_cursor->Valid()) {
|
||||||
|
// We are exhausted already, sorry
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rocksdb::Slice key = _cursor->key();
|
||||||
|
// LOG_TOPIC(TRACE, arangodb::Logger::FIXME) << "cursor key: " <<
|
||||||
|
// VPackSlice(key.data() +
|
||||||
|
// MMFilesPersistentIndex::keyPrefixSize()).toJson();
|
||||||
|
|
||||||
|
int res = comparator->Compare(
|
||||||
|
key, rocksdb::Slice(_leftEndpoint->data(), _leftEndpoint->size()));
|
||||||
|
// LOG_TOPIC(TRACE, arangodb::Logger::FIXME) << "comparing: " <<
|
||||||
|
// VPackSlice(key.data() + MMFilesPersistentIndex::keyPrefixSize()).toJson()
|
||||||
|
// << " with " << VPackSlice((char const*) _leftEndpoint->data() +
|
||||||
|
// MMFilesPersistentIndex::keyPrefixSize()).toJson() << " - res: " << res;
|
||||||
|
|
||||||
|
if (res < 0) {
|
||||||
|
if (_reverse) {
|
||||||
|
// We are done
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
_cursor->Next();
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = comparator->Compare(
|
||||||
|
key, rocksdb::Slice(_rightEndpoint->data(), _rightEndpoint->size()));
|
||||||
|
// LOG_TOPIC(TRACE, arangodb::Logger::FIXME) << "comparing: " <<
|
||||||
|
// VPackSlice(key.data() + MMFilesPersistentIndex::keyPrefixSize()).toJson()
|
||||||
|
// << " with " << VPackSlice((char const*) _rightEndpoint->data() +
|
||||||
|
// MMFilesPersistentIndex::keyPrefixSize()).toJson() << " - res: " << res;
|
||||||
|
|
||||||
|
if (res <= 0) {
|
||||||
|
// get the value for _key, which is the last entry in the key array
|
||||||
|
VPackSlice const keySlice = comparator->extractKeySlice(key);
|
||||||
|
TRI_ASSERT(keySlice.isArray());
|
||||||
|
VPackValueLength const n = keySlice.length();
|
||||||
|
TRI_ASSERT(n > 1); // one value + _key
|
||||||
|
|
||||||
|
// LOG_TOPIC(TRACE, arangodb::Logger::FIXME) << "looking up document with
|
||||||
|
// key: " << keySlice.toJson();
|
||||||
|
// LOG_TOPIC(TRACE, arangodb::Logger::FIXME) << "looking up document with
|
||||||
|
// primary key: " << keySlice[n - 1].toJson();
|
||||||
|
|
||||||
|
// use primary index to lookup the document
|
||||||
|
MMFilesSimpleIndexElement element =
|
||||||
|
_primaryIndex->lookupKey(_trx, keySlice[n - 1]);
|
||||||
|
if (element) {
|
||||||
|
LocalDocumentId doc = element.localDocumentId();
|
||||||
|
if (doc.isSet()) {
|
||||||
|
_documentIds.emplace_back(doc, nullptr);
|
||||||
|
--limit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_reverse) {
|
||||||
|
_cursor->Prev();
|
||||||
|
} else {
|
||||||
|
_cursor->Next();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res > 0) {
|
||||||
|
if (!_probe) {
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_probe = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto physical = static_cast<MMFilesCollection*>(_collection->getPhysical());
|
||||||
|
physical->readDocumentWithCallback(_trx, _documentIds, cb);
|
||||||
|
return !done;
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief create the index
|
/// @brief create the index
|
||||||
MMFilesPersistentIndex::MMFilesPersistentIndex(
|
MMFilesPersistentIndex::MMFilesPersistentIndex(
|
||||||
TRI_idx_iid_t iid, arangodb::LogicalCollection* collection,
|
TRI_idx_iid_t iid, arangodb::LogicalCollection* collection,
|
||||||
|
|
|
@ -78,6 +78,7 @@ class MMFilesPersistentIndexIterator final : public IndexIterator {
|
||||||
|
|
||||||
/// @brief Get the next limit many element in the index
|
/// @brief Get the next limit many element in the index
|
||||||
bool next(LocalDocumentIdCallback const& cb, size_t limit) override;
|
bool next(LocalDocumentIdCallback const& cb, size_t limit) override;
|
||||||
|
bool nextDocument(DocumentCallback const& cb, size_t limit) override;
|
||||||
|
|
||||||
/// @brief Reset the cursor
|
/// @brief Reset the cursor
|
||||||
void reset() override;
|
void reset() override;
|
||||||
|
@ -92,6 +93,7 @@ class MMFilesPersistentIndexIterator final : public IndexIterator {
|
||||||
_rightEndpoint; // Interval right border
|
_rightEndpoint; // Interval right border
|
||||||
bool const _reverse;
|
bool const _reverse;
|
||||||
bool _probe;
|
bool _probe;
|
||||||
|
std::vector<std::pair<LocalDocumentId, uint8_t const*>> _documentIds;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MMFilesPersistentIndex final : public MMFilesPathBasedIndex {
|
class MMFilesPersistentIndex final : public MMFilesPathBasedIndex {
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "Indexes/IndexLookupContext.h"
|
#include "Indexes/IndexLookupContext.h"
|
||||||
#include "Indexes/IndexResult.h"
|
#include "Indexes/IndexResult.h"
|
||||||
#include "Indexes/SimpleAttributeEqualityMatcher.h"
|
#include "Indexes/SimpleAttributeEqualityMatcher.h"
|
||||||
|
#include "MMFiles/MMFilesCollection.h"
|
||||||
#include "StorageEngine/PhysicalCollection.h"
|
#include "StorageEngine/PhysicalCollection.h"
|
||||||
#include "Transaction/Helpers.h"
|
#include "Transaction/Helpers.h"
|
||||||
#include "Transaction/Methods.h"
|
#include "Transaction/Methods.h"
|
||||||
|
@ -582,12 +583,52 @@ bool MMFilesSkiplistIterator::next(LocalDocumentIdCallback const& cb, size_t lim
|
||||||
}
|
}
|
||||||
TRI_ASSERT(tmp != nullptr);
|
TRI_ASSERT(tmp != nullptr);
|
||||||
TRI_ASSERT(tmp->document() != nullptr);
|
TRI_ASSERT(tmp->document() != nullptr);
|
||||||
|
|
||||||
cb(tmp->document()->localDocumentId());
|
cb(tmp->document()->localDocumentId());
|
||||||
limit--;
|
limit--;
|
||||||
}
|
}
|
||||||
return true;
|
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() {
|
void MMFilesSkiplistIterator::forwardCursor() {
|
||||||
_currentInterval++;
|
_currentInterval++;
|
||||||
if (_currentInterval < _intervals.size()) {
|
if (_currentInterval < _intervals.size()) {
|
||||||
|
|
|
@ -183,6 +183,7 @@ class MMFilesSkiplistIterator final : public IndexIterator {
|
||||||
size_t _currentInterval;
|
size_t _currentInterval;
|
||||||
|
|
||||||
MMFilesBaseSkiplistLookupBuilder* _builder;
|
MMFilesBaseSkiplistLookupBuilder* _builder;
|
||||||
|
std::vector<std::pair<LocalDocumentId, uint8_t const*>> _documentIds;
|
||||||
|
|
||||||
std::function<int(void*, MMFilesSkiplistIndexElement const*,
|
std::function<int(void*, MMFilesSkiplistIndexElement const*,
|
||||||
MMFilesSkiplistIndexElement const*, MMFilesSkiplistCmpType)>
|
MMFilesSkiplistIndexElement const*, MMFilesSkiplistCmpType)>
|
||||||
|
@ -210,6 +211,7 @@ class MMFilesSkiplistIterator final : public IndexIterator {
|
||||||
|
|
||||||
/// @brief Get the next elements in the skiplist
|
/// @brief Get the next elements in the skiplist
|
||||||
bool next(LocalDocumentIdCallback const& cb, size_t limit) override;
|
bool next(LocalDocumentIdCallback const& cb, size_t limit) override;
|
||||||
|
bool nextDocument(DocumentCallback const& cb, size_t limit) override;
|
||||||
|
|
||||||
/// @brief Reset the cursor
|
/// @brief Reset the cursor
|
||||||
void reset() override;
|
void reset() override;
|
||||||
|
|
Loading…
Reference in New Issue