mirror of https://gitee.com/bigwinds/arangodb
clean up usage costs (#9237)
This commit is contained in:
parent
2fb159a8e2
commit
6f0c116130
|
@ -429,18 +429,11 @@ CostEstimate IndexNode::estimateCost() const {
|
||||||
auto root = _condition->root();
|
auto root = _condition->root();
|
||||||
|
|
||||||
for (size_t i = 0; i < _indexes.size(); ++i) {
|
for (size_t i = 0; i < _indexes.size(); ++i) {
|
||||||
arangodb::aql::AstNode const* condition;
|
Index::FilterCosts costs = Index::FilterCosts::defaultCosts(itemsInCollection);
|
||||||
if (root == nullptr || root->numMembers() <= i) {
|
|
||||||
condition = nullptr;
|
|
||||||
} else {
|
|
||||||
condition = root->getMember(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
Index::UsageCosts costs;
|
if (root != nullptr && root->numMembers() > i) {
|
||||||
if (condition != nullptr) {
|
arangodb::aql::AstNode const* condition = root->getMember(i);
|
||||||
costs = _indexes[i].getIndex()->supportsFilterCondition(std::vector<std::shared_ptr<Index>>(), condition, _outVariable, itemsInCollection);
|
costs = _indexes[i].getIndex()->supportsFilterCondition(std::vector<std::shared_ptr<Index>>(), condition, _outVariable, itemsInCollection);
|
||||||
} else {
|
|
||||||
costs = Index::UsageCosts::defaultsForFiltering(itemsInCollection);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
totalItems += costs.estimatedItems;
|
totalItems += costs.estimatedItems;
|
||||||
|
|
|
@ -219,7 +219,7 @@ bool ClusterIndex::matchesDefinition(VPackSlice const& info) const {
|
||||||
return Index::Compare(_info.slice(), info);
|
return Index::Compare(_info.slice(), info);
|
||||||
}
|
}
|
||||||
|
|
||||||
Index::UsageCosts ClusterIndex::supportsFilterCondition(
|
Index::FilterCosts ClusterIndex::supportsFilterCondition(
|
||||||
std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
||||||
arangodb::aql::AstNode const* node, arangodb::aql::Variable const* reference,
|
arangodb::aql::AstNode const* node, arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const {
|
size_t itemsInIndex) const {
|
||||||
|
@ -232,10 +232,14 @@ Index::UsageCosts ClusterIndex::supportsFilterCondition(
|
||||||
SortedIndexAttributeMatcher::matchAttributes(this, node, reference, found,
|
SortedIndexAttributeMatcher::matchAttributes(this, node, reference, found,
|
||||||
values, nonNullAttributes,
|
values, nonNullAttributes,
|
||||||
/*skip evaluation (during execution)*/ false);
|
/*skip evaluation (during execution)*/ false);
|
||||||
Index::UsageCosts costs;
|
|
||||||
costs.estimatedItems = values;
|
Index::FilterCosts costs = Index::FilterCosts::defaultCosts(itemsInIndex);
|
||||||
/// TODO: estimatedCost?
|
if (!found.empty()) {
|
||||||
costs.supportsCondition = !found.empty();
|
costs.supportsCondition = true;
|
||||||
|
costs.coveredAttributes = found.size();
|
||||||
|
costs.estimatedItems = values;
|
||||||
|
costs.estimatedCosts = static_cast<double>(values);
|
||||||
|
}
|
||||||
return costs;
|
return costs;
|
||||||
}
|
}
|
||||||
// MMFiles et al
|
// MMFiles et al
|
||||||
|
@ -280,12 +284,12 @@ Index::UsageCosts ClusterIndex::supportsFilterCondition(
|
||||||
}
|
}
|
||||||
|
|
||||||
TRI_ASSERT(_engineType == ClusterEngineType::MockEngine);
|
TRI_ASSERT(_engineType == ClusterEngineType::MockEngine);
|
||||||
return Index::UsageCosts();
|
return Index::FilterCosts::defaultCosts(itemsInIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
Index::UsageCosts ClusterIndex::supportsSortCondition(arangodb::aql::SortCondition const* sortCondition,
|
Index::SortCosts ClusterIndex::supportsSortCondition(arangodb::aql::SortCondition const* sortCondition,
|
||||||
arangodb::aql::Variable const* reference,
|
arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const {
|
size_t itemsInIndex) const {
|
||||||
switch (_indexType) {
|
switch (_indexType) {
|
||||||
case TRI_IDX_TYPE_PRIMARY_INDEX:
|
case TRI_IDX_TYPE_PRIMARY_INDEX:
|
||||||
case TRI_IDX_TYPE_HASH_INDEX: {
|
case TRI_IDX_TYPE_HASH_INDEX: {
|
||||||
|
@ -321,7 +325,7 @@ Index::UsageCosts ClusterIndex::supportsSortCondition(arangodb::aql::SortConditi
|
||||||
}
|
}
|
||||||
|
|
||||||
TRI_ASSERT(_engineType == ClusterEngineType::MockEngine);
|
TRI_ASSERT(_engineType == ClusterEngineType::MockEngine);
|
||||||
return Index::UsageCosts::defaultsForSorting(itemsInIndex, false);
|
return Index::SortCosts::defaultCosts(itemsInIndex, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief specializes the condition for use with the index
|
/// @brief specializes the condition for use with the index
|
||||||
|
|
|
@ -84,14 +84,14 @@ class ClusterIndex : public Index {
|
||||||
/// @brief Checks if this index is identical to the given definition
|
/// @brief Checks if this index is identical to the given definition
|
||||||
bool matchesDefinition(arangodb::velocypack::Slice const&) const override;
|
bool matchesDefinition(arangodb::velocypack::Slice const&) const override;
|
||||||
|
|
||||||
Index::UsageCosts supportsFilterCondition(std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
Index::FilterCosts supportsFilterCondition(std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
||||||
arangodb::aql::AstNode const* node,
|
arangodb::aql::AstNode const* node,
|
||||||
arangodb::aql::Variable const* reference,
|
arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const override;
|
size_t itemsInIndex) const override;
|
||||||
|
|
||||||
Index::UsageCosts supportsSortCondition(arangodb::aql::SortCondition const* sortCondition,
|
Index::SortCosts supportsSortCondition(arangodb::aql::SortCondition const* sortCondition,
|
||||||
arangodb::aql::Variable const* reference,
|
arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const override;
|
size_t itemsInIndex) const override;
|
||||||
|
|
||||||
/// @brief specializes the condition for use with the index
|
/// @brief specializes the condition for use with the index
|
||||||
arangodb::aql::AstNode* specializeCondition(arangodb::aql::AstNode* node,
|
arangodb::aql::AstNode* specializeCondition(arangodb::aql::AstNode* node,
|
||||||
|
|
|
@ -177,6 +177,45 @@ std::string defaultIndexName(VPackSlice const& slice) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
Index::FilterCosts Index::FilterCosts::zeroCosts() {
|
||||||
|
Index::FilterCosts costs;
|
||||||
|
costs.supportsCondition = true;
|
||||||
|
costs.coveredAttributes = 0;
|
||||||
|
costs.estimatedItems = 0;
|
||||||
|
costs.estimatedCosts = 0;
|
||||||
|
return costs;
|
||||||
|
}
|
||||||
|
|
||||||
|
Index::FilterCosts Index::FilterCosts::defaultCosts(size_t itemsInIndex) {
|
||||||
|
Index::FilterCosts costs;
|
||||||
|
costs.supportsCondition = false;
|
||||||
|
costs.coveredAttributes = 0;
|
||||||
|
costs.estimatedItems = itemsInIndex;
|
||||||
|
costs.estimatedCosts = static_cast<double>(itemsInIndex);
|
||||||
|
return costs;
|
||||||
|
}
|
||||||
|
|
||||||
|
Index::SortCosts Index::SortCosts::zeroCosts(size_t coveredAttributes) {
|
||||||
|
Index::SortCosts costs;
|
||||||
|
costs.coveredAttributes = coveredAttributes;
|
||||||
|
costs.supportsCondition = true;
|
||||||
|
costs.estimatedCosts = 0;
|
||||||
|
return costs;
|
||||||
|
}
|
||||||
|
|
||||||
|
Index::SortCosts Index::SortCosts::defaultCosts(size_t itemsInIndex, bool isPersistent) {
|
||||||
|
Index::SortCosts costs;
|
||||||
|
TRI_ASSERT(!costs.supportsCondition);
|
||||||
|
costs.coveredAttributes = 0;
|
||||||
|
costs.estimatedCosts = itemsInIndex > 0 ? (itemsInIndex * std::log2(static_cast<double>(itemsInIndex))) : 0.0;
|
||||||
|
if (isPersistent) {
|
||||||
|
// slightly penalize this type of index against other indexes which
|
||||||
|
// are in memory
|
||||||
|
costs.estimatedCosts *= 1.05;
|
||||||
|
}
|
||||||
|
return costs;
|
||||||
|
}
|
||||||
|
|
||||||
// If the Index is on a coordinator instance the index may not access the
|
// If the Index is on a coordinator instance the index may not access the
|
||||||
// logical collection because it could be gone!
|
// logical collection because it could be gone!
|
||||||
|
@ -630,20 +669,20 @@ Result Index::drop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief default implementation for supportsFilterCondition
|
/// @brief default implementation for supportsFilterCondition
|
||||||
Index::UsageCosts Index::supportsFilterCondition(std::vector<std::shared_ptr<arangodb::Index>> const&,
|
Index::FilterCosts Index::supportsFilterCondition(std::vector<std::shared_ptr<arangodb::Index>> const&,
|
||||||
arangodb::aql::AstNode const* /* node */,
|
arangodb::aql::AstNode const* /* node */,
|
||||||
arangodb::aql::Variable const* /* reference */,
|
arangodb::aql::Variable const* /* reference */,
|
||||||
size_t itemsInIndex) const {
|
size_t itemsInIndex) const {
|
||||||
// by default, no filter conditions are supported
|
// by default no filter conditions are supported
|
||||||
return Index::UsageCosts::defaultsForFiltering(itemsInIndex);
|
return Index::FilterCosts::defaultCosts(itemsInIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief default implementation for supportsSortCondition
|
/// @brief default implementation for supportsSortCondition
|
||||||
Index::UsageCosts Index::supportsSortCondition(arangodb::aql::SortCondition const* /* sortCondition */,
|
Index::SortCosts Index::supportsSortCondition(arangodb::aql::SortCondition const* /* sortCondition */,
|
||||||
arangodb::aql::Variable const* /* node */,
|
arangodb::aql::Variable const* /* node */,
|
||||||
size_t itemsInIndex) const {
|
size_t itemsInIndex) const {
|
||||||
// by default, no sort conditions are supported
|
// by default no sort conditions are supported
|
||||||
return Index::UsageCosts::defaultsForSorting(itemsInIndex, this->isPersistent());
|
return Index::SortCosts::defaultCosts(itemsInIndex, this->isPersistent());
|
||||||
}
|
}
|
||||||
|
|
||||||
arangodb::aql::AstNode* Index::specializeCondition(arangodb::aql::AstNode* /* node */,
|
arangodb::aql::AstNode* Index::specializeCondition(arangodb::aql::AstNode* /* node */,
|
||||||
|
|
|
@ -108,48 +108,40 @@ class Index {
|
||||||
enum OperationMode { normal, internal, rollback };
|
enum OperationMode { normal, internal, rollback };
|
||||||
|
|
||||||
/// @brief: helper struct returned by index methods that determine the costs
|
/// @brief: helper struct returned by index methods that determine the costs
|
||||||
/// of index usage
|
/// of index usage for filtering
|
||||||
struct UsageCosts {
|
struct FilterCosts {
|
||||||
/// @brief whether or not the index supports the filter condition/sort clause
|
/// @brief whether or not the index supports the filter condition
|
||||||
bool supportsCondition = false;
|
bool supportsCondition = false;
|
||||||
|
|
||||||
/// @brief number of attributes covered by this index
|
/// @brief number of attributes of filter condition covered by this index
|
||||||
size_t coveredAttributes = 0;
|
size_t coveredAttributes = 0;
|
||||||
|
|
||||||
/// @brief estimated items to be returned for this condition
|
/// @brief estimated items to be returned for this condition.
|
||||||
size_t estimatedItems = 0;
|
size_t estimatedItems = 0;
|
||||||
|
|
||||||
/// @brief estimated costs for this filter condition/sort clause
|
/// @brief estimated costs for this filter condition
|
||||||
double estimatedCosts = 0.0;
|
double estimatedCosts = 0.0;
|
||||||
|
|
||||||
static UsageCosts zeroCosts() {
|
static FilterCosts zeroCosts();
|
||||||
UsageCosts costs;
|
|
||||||
costs.estimatedItems = 0;
|
|
||||||
costs.estimatedCosts = 0;
|
|
||||||
costs.supportsCondition = true;
|
|
||||||
return costs;
|
|
||||||
}
|
|
||||||
|
|
||||||
static UsageCosts defaultsForFiltering(size_t itemsInIndex) {
|
static FilterCosts defaultCosts(size_t itemsInIndex);
|
||||||
UsageCosts costs;
|
};
|
||||||
costs.estimatedItems = itemsInIndex;
|
|
||||||
costs.estimatedCosts = static_cast<double>(itemsInIndex);
|
/// @brief: helper struct returned by index methods that determine the costs
|
||||||
TRI_ASSERT(!costs.supportsCondition);
|
/// of index usage
|
||||||
return costs;
|
struct SortCosts {
|
||||||
}
|
/// @brief whether or not the index supports the sort clause
|
||||||
|
bool supportsCondition = false;
|
||||||
|
|
||||||
|
/// @brief number of attributes of the sort clause covered by this index
|
||||||
|
size_t coveredAttributes = 0;
|
||||||
|
|
||||||
static UsageCosts defaultsForSorting(size_t itemsInIndex, bool isPersistent) {
|
/// @brief estimated costs for this sort clause
|
||||||
UsageCosts costs;
|
double estimatedCosts = 0.0;
|
||||||
costs.estimatedItems = itemsInIndex;
|
|
||||||
costs.estimatedCosts = itemsInIndex > 0 ? (itemsInIndex * std::log2(static_cast<double>(itemsInIndex))) : 0.0;
|
static SortCosts zeroCosts(size_t coveredAttributes);
|
||||||
if (isPersistent) {
|
|
||||||
// slightly penalize this type of index against other indexes which
|
static SortCosts defaultCosts(size_t itemsInIndex, bool isPersistent);
|
||||||
// are in memory
|
|
||||||
costs.estimatedCosts *= 1.05;
|
|
||||||
}
|
|
||||||
TRI_ASSERT(!costs.supportsCondition);
|
|
||||||
return costs;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -392,16 +384,16 @@ class Index {
|
||||||
|
|
||||||
/// @brief whether or not the filter condition is supported by the index
|
/// @brief whether or not the filter condition is supported by the index
|
||||||
/// returns detailed information about the costs associated with using this index
|
/// returns detailed information about the costs associated with using this index
|
||||||
virtual UsageCosts supportsFilterCondition(std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
virtual FilterCosts supportsFilterCondition(std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
||||||
arangodb::aql::AstNode const* node,
|
arangodb::aql::AstNode const* node,
|
||||||
arangodb::aql::Variable const* reference,
|
arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const;
|
size_t itemsInIndex) const;
|
||||||
|
|
||||||
/// @brief whether or not the sort condition is supported by the index
|
/// @brief whether or not the sort condition is supported by the index
|
||||||
/// returns detailed information about the costs associated with using this index
|
/// returns detailed information about the costs associated with using this index
|
||||||
virtual UsageCosts supportsSortCondition(arangodb::aql::SortCondition const* sortCondition,
|
virtual SortCosts supportsSortCondition(arangodb::aql::SortCondition const* sortCondition,
|
||||||
arangodb::aql::Variable const* reference,
|
arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const;
|
size_t itemsInIndex) const;
|
||||||
|
|
||||||
/// @brief specialize the condition for use with this index. this will remove all
|
/// @brief specialize the condition for use with this index. this will remove all
|
||||||
/// elements from the condition that are not supported by the index.
|
/// elements from the condition that are not supported by the index.
|
||||||
|
|
|
@ -34,62 +34,62 @@ using namespace arangodb;
|
||||||
|
|
||||||
SimpleAttributeEqualityMatcher::SimpleAttributeEqualityMatcher(
|
SimpleAttributeEqualityMatcher::SimpleAttributeEqualityMatcher(
|
||||||
std::vector<std::vector<arangodb::basics::AttributeName>> const& attributes)
|
std::vector<std::vector<arangodb::basics::AttributeName>> const& attributes)
|
||||||
: _attributes(attributes), _found() {}
|
: _attributes(attributes) {}
|
||||||
|
|
||||||
/// @brief match a single of the attributes
|
/// @brief match a single of the attributes
|
||||||
/// this is used for the primary index and the edge index
|
/// this is used for the primary index and the edge index
|
||||||
Index::UsageCosts SimpleAttributeEqualityMatcher::matchOne(arangodb::Index const* index,
|
Index::FilterCosts SimpleAttributeEqualityMatcher::matchOne(arangodb::Index const* index,
|
||||||
arangodb::aql::AstNode const* node,
|
arangodb::aql::AstNode const* node,
|
||||||
arangodb::aql::Variable const* reference,
|
arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) {
|
size_t itemsInIndex) {
|
||||||
std::unordered_set<std::string> nonNullAttributes;
|
std::unordered_set<std::string> nonNullAttributes;
|
||||||
_found.clear();
|
_found.clear();
|
||||||
|
|
||||||
size_t const n = node->numMembers();
|
size_t const n = node->numMembers();
|
||||||
|
|
||||||
for (size_t i = 0; i < n; ++i) {
|
for (size_t i = 0; i < n; ++i) {
|
||||||
|
arangodb::aql::AstNode const* which = nullptr;
|
||||||
|
size_t values = 1;
|
||||||
|
|
||||||
auto op = node->getMemberUnchecked(i);
|
auto op = node->getMemberUnchecked(i);
|
||||||
|
|
||||||
if (op->type == arangodb::aql::NODE_TYPE_OPERATOR_BINARY_EQ) {
|
if (op->type == arangodb::aql::NODE_TYPE_OPERATOR_BINARY_EQ) {
|
||||||
TRI_ASSERT(op->numMembers() == 2);
|
TRI_ASSERT(op->numMembers() == 2);
|
||||||
// EQ is symmetric
|
// EQ is symmetric
|
||||||
int which = -1;
|
if (accessFitsIndex(index, op->getMemberUnchecked(0), op->getMemberUnchecked(1), op,
|
||||||
if (accessFitsIndex(index, op->getMember(0), op->getMember(1), op,
|
|
||||||
reference, nonNullAttributes, false)) {
|
reference, nonNullAttributes, false)) {
|
||||||
which = 0;
|
which = op->getMemberUnchecked(0);
|
||||||
} else if (accessFitsIndex(index, op->getMember(1), op->getMember(0), op,
|
} else if (accessFitsIndex(index, op->getMemberUnchecked(1), op->getMemberUnchecked(0), op,
|
||||||
reference, nonNullAttributes, false)) {
|
reference, nonNullAttributes, false)) {
|
||||||
which = 1;
|
which = op->getMemberUnchecked(1);
|
||||||
}
|
|
||||||
if (which >= 0) {
|
|
||||||
// we can use the index
|
|
||||||
return calculateIndexCosts(index, op->getMember(which), itemsInIndex);
|
|
||||||
}
|
}
|
||||||
} else if (op->type == arangodb::aql::NODE_TYPE_OPERATOR_BINARY_IN) {
|
} else if (op->type == arangodb::aql::NODE_TYPE_OPERATOR_BINARY_IN) {
|
||||||
TRI_ASSERT(op->numMembers() == 2);
|
TRI_ASSERT(op->numMembers() == 2);
|
||||||
if (accessFitsIndex(index, op->getMember(0), op->getMember(1), op,
|
if (accessFitsIndex(index, op->getMemberUnchecked(0), op->getMemberUnchecked(1), op,
|
||||||
reference, nonNullAttributes, false)) {
|
reference, nonNullAttributes, false)) {
|
||||||
// we can use the index
|
// we can use the index
|
||||||
// use slightly different cost calculation for IN than for EQ
|
// use slightly different cost calculation for IN than for EQ
|
||||||
Index::UsageCosts costs = calculateIndexCosts(index, op->getMember(0), itemsInIndex);
|
which = op->getMemberUnchecked(0);
|
||||||
size_t values = estimateNumberOfArrayMembers(op->getMember(1));
|
values = estimateNumberOfArrayMembers(op->getMemberUnchecked(1));
|
||||||
costs.estimatedItems *= values;
|
|
||||||
costs.estimatedCosts *= values;
|
|
||||||
return costs;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (which != nullptr) {
|
||||||
|
// we can use the index
|
||||||
|
return calculateIndexCosts(index, which, itemsInIndex * values, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// set to defaults
|
// set to defaults
|
||||||
return Index::UsageCosts::defaultsForFiltering(itemsInIndex);
|
return Index::FilterCosts::defaultCosts(itemsInIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief match all of the attributes, in any order
|
/// @brief match all of the attributes, in any order
|
||||||
/// this is used for the hash index
|
/// this is used for the hash index
|
||||||
Index::UsageCosts SimpleAttributeEqualityMatcher::matchAll(arangodb::Index const* index,
|
Index::FilterCosts SimpleAttributeEqualityMatcher::matchAll(arangodb::Index const* index,
|
||||||
arangodb::aql::AstNode const* node,
|
arangodb::aql::AstNode const* node,
|
||||||
arangodb::aql::Variable const* reference,
|
arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) {
|
size_t itemsInIndex) {
|
||||||
std::unordered_set<std::string> nonNullAttributes;
|
std::unordered_set<std::string> nonNullAttributes;
|
||||||
_found.clear();
|
_found.clear();
|
||||||
arangodb::aql::AstNode const* which = nullptr;
|
arangodb::aql::AstNode const* which = nullptr;
|
||||||
|
@ -98,7 +98,7 @@ Index::UsageCosts SimpleAttributeEqualityMatcher::matchAll(arangodb::Index const
|
||||||
size_t const n = node->numMembers();
|
size_t const n = node->numMembers();
|
||||||
|
|
||||||
for (size_t i = 0; i < n; ++i) {
|
for (size_t i = 0; i < n; ++i) {
|
||||||
auto op = node->getMember(i);
|
auto op = node->getMemberUnchecked(i);
|
||||||
|
|
||||||
if (index->sparse() && (op->type == arangodb::aql::NODE_TYPE_OPERATOR_BINARY_NE ||
|
if (index->sparse() && (op->type == arangodb::aql::NODE_TYPE_OPERATOR_BINARY_NE ||
|
||||||
op->type == arangodb::aql::NODE_TYPE_OPERATOR_BINARY_GT)) {
|
op->type == arangodb::aql::NODE_TYPE_OPERATOR_BINARY_GT)) {
|
||||||
|
@ -136,13 +136,16 @@ Index::UsageCosts SimpleAttributeEqualityMatcher::matchAll(arangodb::Index const
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (values == 0) {
|
||||||
|
values = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Index::FilterCosts costs = Index::FilterCosts::defaultCosts(itemsInIndex * values);
|
||||||
|
|
||||||
if (_found.size() == _attributes.size()) {
|
if (_found.size() == _attributes.size()) {
|
||||||
// can only use this index if all index attributes are covered by the
|
// can only use this index if all index attributes are covered by the
|
||||||
// condition
|
// condition
|
||||||
if (values == 0) {
|
|
||||||
values = 1;
|
|
||||||
}
|
|
||||||
if (_found.size() == 1) {
|
if (_found.size() == 1) {
|
||||||
// single-attribute index
|
// single-attribute index
|
||||||
TRI_ASSERT(which != nullptr);
|
TRI_ASSERT(which != nullptr);
|
||||||
|
@ -151,14 +154,11 @@ Index::UsageCosts SimpleAttributeEqualityMatcher::matchAll(arangodb::Index const
|
||||||
which = nullptr;
|
which = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Index::UsageCosts costs = calculateIndexCosts(index, which, itemsInIndex);
|
costs = calculateIndexCosts(index, which, itemsInIndex * values, _found.size());
|
||||||
costs.estimatedItems *= values;
|
|
||||||
costs.estimatedCosts *= static_cast<double>(values);
|
|
||||||
return costs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// set to defaults
|
// return defaults
|
||||||
return Index::UsageCosts::defaultsForFiltering(itemsInIndex);
|
return costs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief specialize the condition for the index
|
/// @brief specialize the condition for the index
|
||||||
|
@ -298,14 +298,15 @@ arangodb::aql::AstNode* SimpleAttributeEqualityMatcher::specializeAll(
|
||||||
/// that will return in average
|
/// that will return in average
|
||||||
/// cost values have no special meaning, except that multiple cost values are
|
/// cost values have no special meaning, except that multiple cost values are
|
||||||
/// comparable, and lower values mean lower costs
|
/// comparable, and lower values mean lower costs
|
||||||
Index::UsageCosts SimpleAttributeEqualityMatcher::calculateIndexCosts(
|
Index::FilterCosts SimpleAttributeEqualityMatcher::calculateIndexCosts(
|
||||||
arangodb::Index const* index, arangodb::aql::AstNode const* attribute,
|
arangodb::Index const* index, arangodb::aql::AstNode const* attribute,
|
||||||
size_t itemsInIndex) const {
|
size_t itemsInIndex, size_t coveredAttributes) const {
|
||||||
// note: attribute will be set to the index attribute for single-attribute
|
// note: attribute will be set to the index attribute for single-attribute
|
||||||
// indexes such as the primary and edge indexes, and is a nullptr for the
|
// indexes such as the primary and edge indexes, and is a nullptr for the
|
||||||
// other indexes
|
// other indexes
|
||||||
Index::UsageCosts costs;
|
Index::FilterCosts costs;
|
||||||
costs.supportsCondition = true;
|
costs.supportsCondition = true;
|
||||||
|
costs.coveredAttributes = coveredAttributes;
|
||||||
|
|
||||||
if (index->unique() || index->implicitlyUnique()) {
|
if (index->unique() || index->implicitlyUnique()) {
|
||||||
// index is unique, and the condition covers all attributes
|
// index is unique, and the condition covers all attributes
|
||||||
|
|
|
@ -45,17 +45,17 @@ class SimpleAttributeEqualityMatcher {
|
||||||
public:
|
public:
|
||||||
/// @brief match a single of the attributes
|
/// @brief match a single of the attributes
|
||||||
/// this is used for the primary index and the edge index
|
/// this is used for the primary index and the edge index
|
||||||
Index::UsageCosts matchOne(arangodb::Index const* index,
|
Index::FilterCosts matchOne(arangodb::Index const* index,
|
||||||
arangodb::aql::AstNode const* node,
|
arangodb::aql::AstNode const* node,
|
||||||
arangodb::aql::Variable const* reference,
|
arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex);
|
size_t itemsInIndex);
|
||||||
|
|
||||||
/// @brief match all of the attributes, in any order
|
/// @brief match all of the attributes, in any order
|
||||||
/// this is used for the hash index
|
/// this is used for the hash index
|
||||||
Index::UsageCosts matchAll(arangodb::Index const* index,
|
Index::FilterCosts matchAll(arangodb::Index const* index,
|
||||||
arangodb::aql::AstNode const* node,
|
arangodb::aql::AstNode const* node,
|
||||||
arangodb::aql::Variable const* reference,
|
arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex);
|
size_t itemsInIndex);
|
||||||
|
|
||||||
/// @brief get the condition parts that the index is responsible for
|
/// @brief get the condition parts that the index is responsible for
|
||||||
/// this is used for the primary index and the edge index
|
/// this is used for the primary index and the edge index
|
||||||
|
@ -84,8 +84,9 @@ class SimpleAttributeEqualityMatcher {
|
||||||
/// that will return in average
|
/// that will return in average
|
||||||
/// cost values have no special meaning, except that multiple cost values are
|
/// cost values have no special meaning, except that multiple cost values are
|
||||||
/// comparable, and lower values mean lower costs
|
/// comparable, and lower values mean lower costs
|
||||||
Index::UsageCosts calculateIndexCosts(arangodb::Index const* index,
|
Index::FilterCosts calculateIndexCosts(arangodb::Index const* index,
|
||||||
arangodb::aql::AstNode const* attribute, size_t itemsInIndex) const;
|
arangodb::aql::AstNode const* attribute,
|
||||||
|
size_t itemsInIndex, size_t coveredAttributes) const;
|
||||||
|
|
||||||
/// @brief whether or not the access fits
|
/// @brief whether or not the access fits
|
||||||
bool accessFitsIndex(arangodb::Index const*, arangodb::aql::AstNode const*,
|
bool accessFitsIndex(arangodb::Index const*, arangodb::aql::AstNode const*,
|
||||||
|
|
|
@ -187,7 +187,7 @@ void SortedIndexAttributeMatcher::matchAttributes(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Index::UsageCosts SortedIndexAttributeMatcher::supportsFilterCondition(
|
Index::FilterCosts SortedIndexAttributeMatcher::supportsFilterCondition(
|
||||||
std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
||||||
arangodb::Index const* idx, arangodb::aql::AstNode const* node,
|
arangodb::Index const* idx, arangodb::aql::AstNode const* node,
|
||||||
arangodb::aql::Variable const* reference, size_t itemsInIndex) {
|
arangodb::aql::Variable const* reference, size_t itemsInIndex) {
|
||||||
|
@ -198,8 +198,6 @@ Index::UsageCosts SortedIndexAttributeMatcher::supportsFilterCondition(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Index::UsageCosts costs;
|
|
||||||
|
|
||||||
std::unordered_map<size_t, std::vector<arangodb::aql::AstNode const*>> found;
|
std::unordered_map<size_t, std::vector<arangodb::aql::AstNode const*>> found;
|
||||||
std::unordered_set<std::string> nonNullAttributes;
|
std::unordered_set<std::string> nonNullAttributes;
|
||||||
size_t values = 0;
|
size_t values = 0;
|
||||||
|
@ -209,7 +207,7 @@ Index::UsageCosts SortedIndexAttributeMatcher::supportsFilterCondition(
|
||||||
size_t attributesCovered = 0;
|
size_t attributesCovered = 0;
|
||||||
size_t attributesCoveredByEquality = 0;
|
size_t attributesCoveredByEquality = 0;
|
||||||
double equalityReductionFactor = 20.0;
|
double equalityReductionFactor = 20.0;
|
||||||
costs.estimatedCosts = static_cast<double>(itemsInIndex);
|
double estimatedCosts = static_cast<double>(itemsInIndex);
|
||||||
|
|
||||||
for (size_t i = 0; i < idx->fields().size(); ++i) {
|
for (size_t i = 0; i < idx->fields().size(); ++i) {
|
||||||
auto it = found.find(i);
|
auto it = found.find(i);
|
||||||
|
@ -238,7 +236,7 @@ Index::UsageCosts SortedIndexAttributeMatcher::supportsFilterCondition(
|
||||||
++attributesCovered;
|
++attributesCovered;
|
||||||
if (containsEquality) {
|
if (containsEquality) {
|
||||||
++attributesCoveredByEquality;
|
++attributesCoveredByEquality;
|
||||||
costs.estimatedCosts /= equalityReductionFactor;
|
estimatedCosts /= equalityReductionFactor;
|
||||||
|
|
||||||
// decrease the effect of the equality reduction factor
|
// decrease the effect of the equality reduction factor
|
||||||
equalityReductionFactor *= 0.25;
|
equalityReductionFactor *= 0.25;
|
||||||
|
@ -251,10 +249,10 @@ Index::UsageCosts SortedIndexAttributeMatcher::supportsFilterCondition(
|
||||||
if (nodes.size() >= 2) {
|
if (nodes.size() >= 2) {
|
||||||
// at least two (non-equality) conditions. probably a range with lower
|
// at least two (non-equality) conditions. probably a range with lower
|
||||||
// and upper bound defined
|
// and upper bound defined
|
||||||
costs.estimatedCosts /= 7.5;
|
estimatedCosts /= 7.5;
|
||||||
} else {
|
} else {
|
||||||
// one (non-equality). this is either a lower or a higher bound
|
// one (non-equality). this is either a lower or a higher bound
|
||||||
costs.estimatedCosts /= 2.0;
|
estimatedCosts /= 2.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,26 +262,27 @@ Index::UsageCosts SortedIndexAttributeMatcher::supportsFilterCondition(
|
||||||
if (values == 0) {
|
if (values == 0) {
|
||||||
values = 1;
|
values = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Index::FilterCosts costs = Index::FilterCosts::defaultCosts(itemsInIndex);
|
||||||
|
costs.coveredAttributes = attributesCovered;
|
||||||
|
|
||||||
if (attributesCoveredByEquality == idx->fields().size() &&
|
if (attributesCoveredByEquality == idx->fields().size() &&
|
||||||
(idx->unique() || idx->implicitlyUnique())) {
|
(idx->unique() || idx->implicitlyUnique())) {
|
||||||
// index is unique and condition covers all attributes by equality
|
// index is unique and condition covers all attributes by equality
|
||||||
costs.coveredAttributes = attributesCovered;
|
|
||||||
costs.supportsCondition = true;
|
costs.supportsCondition = true;
|
||||||
|
|
||||||
if (itemsInIndex == 0) {
|
if (itemsInIndex == 0) {
|
||||||
costs.estimatedItems = 0;
|
costs.estimatedItems = 0;
|
||||||
costs.estimatedCosts = 0.0;
|
costs.estimatedCosts = 0.0;
|
||||||
return costs;
|
} else {
|
||||||
|
costs.estimatedItems = values;
|
||||||
|
// ALTERNATIVE: estimatedCost = static_cast<double>(estimatedItems * values);
|
||||||
|
costs.estimatedCosts = (std::max)(static_cast<double>(1),
|
||||||
|
std::log2(static_cast<double>(itemsInIndex)) * values);
|
||||||
|
|
||||||
|
// cost is already low... now slightly prioritize unique indexes
|
||||||
|
costs.estimatedCosts *= 0.995 - 0.05 * (idx->fields().size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
costs.estimatedItems = values;
|
|
||||||
// ALTERNATIVE: estimatedCost = static_cast<double>(estimatedItems * values);
|
|
||||||
costs.estimatedCosts = (std::max)(static_cast<double>(1),
|
|
||||||
std::log2(static_cast<double>(itemsInIndex)) * values);
|
|
||||||
|
|
||||||
// cost is already low... now slightly prioritize unique indexes
|
|
||||||
costs.estimatedCosts *= 0.995 - 0.05 * (idx->fields().size() - 1);
|
|
||||||
return costs;
|
return costs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,8 +292,9 @@ Index::UsageCosts SortedIndexAttributeMatcher::supportsFilterCondition(
|
||||||
// or the index is sparse and all attributes are covered by the condition,
|
// or the index is sparse and all attributes are covered by the condition,
|
||||||
// then it can be used (note: additional checks for condition parts in
|
// then it can be used (note: additional checks for condition parts in
|
||||||
// sparse indexes are contained in Index::canUseConditionPart)
|
// sparse indexes are contained in Index::canUseConditionPart)
|
||||||
|
costs.supportsCondition = true;
|
||||||
costs.estimatedItems = static_cast<size_t>(
|
costs.estimatedItems = static_cast<size_t>(
|
||||||
(std::max)(static_cast<size_t>(costs.estimatedCosts * values), static_cast<size_t>(1)));
|
(std::max)(static_cast<size_t>(estimatedCosts * values), static_cast<size_t>(1)));
|
||||||
|
|
||||||
// check if the index has a selectivity estimate ready
|
// check if the index has a selectivity estimate ready
|
||||||
if (idx->hasSelectivityEstimate() &&
|
if (idx->hasSelectivityEstimate() &&
|
||||||
|
@ -357,21 +357,20 @@ Index::UsageCosts SortedIndexAttributeMatcher::supportsFilterCondition(
|
||||||
// slightly prefer indexes that cover more attributes
|
// slightly prefer indexes that cover more attributes
|
||||||
costs.estimatedCosts -= (attributesCovered - 1) * 0.02;
|
costs.estimatedCosts -= (attributesCovered - 1) * 0.02;
|
||||||
}
|
}
|
||||||
costs.coveredAttributes = attributesCovered;
|
|
||||||
costs.supportsCondition = true;
|
|
||||||
return costs;
|
return costs;
|
||||||
}
|
}
|
||||||
|
|
||||||
// index does not help for this condition
|
// index does not help for this condition
|
||||||
return Index::UsageCosts::defaultsForFiltering(itemsInIndex);
|
TRI_ASSERT(!costs.supportsCondition);
|
||||||
|
return costs;
|
||||||
}
|
}
|
||||||
|
|
||||||
Index::UsageCosts SortedIndexAttributeMatcher::supportsSortCondition(
|
Index::SortCosts SortedIndexAttributeMatcher::supportsSortCondition(
|
||||||
arangodb::Index const* idx, arangodb::aql::SortCondition const* sortCondition,
|
arangodb::Index const* idx, arangodb::aql::SortCondition const* sortCondition,
|
||||||
arangodb::aql::Variable const* reference, size_t itemsInIndex) {
|
arangodb::aql::Variable const* reference, size_t itemsInIndex) {
|
||||||
TRI_ASSERT(sortCondition != nullptr);
|
TRI_ASSERT(sortCondition != nullptr);
|
||||||
|
|
||||||
Index::UsageCosts costs;
|
Index::SortCosts costs = Index::SortCosts::defaultCosts(itemsInIndex, idx->isPersistent());
|
||||||
|
|
||||||
if (!idx->sparse() ||
|
if (!idx->sparse() ||
|
||||||
sortCondition->onlyUsesNonNullSortAttributes(idx->fields())) {
|
sortCondition->onlyUsesNonNullSortAttributes(idx->fields())) {
|
||||||
|
@ -390,7 +389,6 @@ Index::UsageCosts SortedIndexAttributeMatcher::supportsSortCondition(
|
||||||
costs.estimatedCosts *= 4;
|
costs.estimatedCosts *= 4;
|
||||||
}
|
}
|
||||||
costs.supportsCondition = true;
|
costs.supportsCondition = true;
|
||||||
return costs;
|
|
||||||
} else if (costs.coveredAttributes > 0) {
|
} else if (costs.coveredAttributes > 0) {
|
||||||
costs.estimatedCosts = (itemsInIndex / costs.coveredAttributes) *
|
costs.estimatedCosts = (itemsInIndex / costs.coveredAttributes) *
|
||||||
std::log2(static_cast<double>(itemsInIndex));
|
std::log2(static_cast<double>(itemsInIndex));
|
||||||
|
@ -399,12 +397,11 @@ Index::UsageCosts SortedIndexAttributeMatcher::supportsSortCondition(
|
||||||
costs.estimatedCosts *= 4;
|
costs.estimatedCosts *= 4;
|
||||||
}
|
}
|
||||||
costs.supportsCondition = true;
|
costs.supportsCondition = true;
|
||||||
return costs;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Index::UsageCosts::defaultsForSorting(itemsInIndex, idx->isPersistent());
|
return costs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief specializes the condition for use with the index
|
/// @brief specializes the condition for use with the index
|
||||||
|
|
|
@ -39,16 +39,16 @@ class Index;
|
||||||
|
|
||||||
namespace SortedIndexAttributeMatcher {
|
namespace SortedIndexAttributeMatcher {
|
||||||
|
|
||||||
Index::UsageCosts supportsFilterCondition(std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
Index::FilterCosts supportsFilterCondition(std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
||||||
arangodb::Index const* index,
|
arangodb::Index const* index,
|
||||||
arangodb::aql::AstNode const* node,
|
arangodb::aql::AstNode const* node,
|
||||||
arangodb::aql::Variable const* reference,
|
arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex);
|
size_t itemsInIndex);
|
||||||
|
|
||||||
Index::UsageCosts supportsSortCondition(arangodb::Index const* index,
|
Index::SortCosts supportsSortCondition(arangodb::Index const* index,
|
||||||
arangodb::aql::SortCondition const* sortCondition,
|
arangodb::aql::SortCondition const* sortCondition,
|
||||||
arangodb::aql::Variable const* reference,
|
arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex);
|
size_t itemsInIndex);
|
||||||
|
|
||||||
/// @brief specializes the condition for use with the index
|
/// @brief specializes the condition for use with the index
|
||||||
arangodb::aql::AstNode* specializeCondition(arangodb::Index const* index,
|
arangodb::aql::AstNode* specializeCondition(arangodb::Index const* index,
|
||||||
|
|
|
@ -384,7 +384,7 @@ Result MMFilesEdgeIndex::sizeHint(transaction::Methods& trx, size_t size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief checks whether the index supports the condition
|
/// @brief checks whether the index supports the condition
|
||||||
Index::UsageCosts MMFilesEdgeIndex::supportsFilterCondition(
|
Index::FilterCosts MMFilesEdgeIndex::supportsFilterCondition(
|
||||||
std::vector<std::shared_ptr<arangodb::Index>> const&,
|
std::vector<std::shared_ptr<arangodb::Index>> const&,
|
||||||
arangodb::aql::AstNode const* node, arangodb::aql::Variable const* reference,
|
arangodb::aql::AstNode const* node, arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const {
|
size_t itemsInIndex) const {
|
||||||
|
|
|
@ -180,10 +180,10 @@ class MMFilesEdgeIndex final : public MMFilesIndex {
|
||||||
|
|
||||||
TRI_MMFilesEdgeIndexHash_t* to() const { return _edgesTo.get(); }
|
TRI_MMFilesEdgeIndexHash_t* to() const { return _edgesTo.get(); }
|
||||||
|
|
||||||
Index::UsageCosts supportsFilterCondition(std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
Index::FilterCosts supportsFilterCondition(std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
||||||
arangodb::aql::AstNode const* node,
|
arangodb::aql::AstNode const* node,
|
||||||
arangodb::aql::Variable const* reference,
|
arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const override;
|
size_t itemsInIndex) const override;
|
||||||
|
|
||||||
std::unique_ptr<IndexIterator> iteratorForCondition(transaction::Methods* trx,
|
std::unique_ptr<IndexIterator> iteratorForCondition(transaction::Methods* trx,
|
||||||
arangodb::aql::AstNode const* node,
|
arangodb::aql::AstNode const* node,
|
||||||
|
|
|
@ -845,7 +845,7 @@ int MMFilesHashIndex::removeMultiElement(transaction::Methods* trx,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief checks whether the index supports the condition
|
/// @brief checks whether the index supports the condition
|
||||||
Index::UsageCosts MMFilesHashIndex::supportsFilterCondition(
|
Index::FilterCosts MMFilesHashIndex::supportsFilterCondition(
|
||||||
std::vector<std::shared_ptr<arangodb::Index>> const&,
|
std::vector<std::shared_ptr<arangodb::Index>> const&,
|
||||||
arangodb::aql::AstNode const* node, arangodb::aql::Variable const* reference,
|
arangodb::aql::AstNode const* node, arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const {
|
size_t itemsInIndex) const {
|
||||||
|
|
|
@ -268,10 +268,10 @@ class MMFilesHashIndex final : public MMFilesPathBasedIndex {
|
||||||
|
|
||||||
Result sizeHint(transaction::Methods& trx, size_t size) override;
|
Result sizeHint(transaction::Methods& trx, size_t size) override;
|
||||||
|
|
||||||
Index::UsageCosts supportsFilterCondition(std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
Index::FilterCosts supportsFilterCondition(std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
||||||
arangodb::aql::AstNode const* node,
|
arangodb::aql::AstNode const* node,
|
||||||
arangodb::aql::Variable const* reference,
|
arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const override;
|
size_t itemsInIndex) const override;
|
||||||
|
|
||||||
std::unique_ptr<IndexIterator> iteratorForCondition(transaction::Methods* trx,
|
std::unique_ptr<IndexIterator> iteratorForCondition(transaction::Methods* trx,
|
||||||
arangodb::aql::AstNode const* node,
|
arangodb::aql::AstNode const* node,
|
||||||
|
|
|
@ -669,16 +669,16 @@ std::unique_ptr<MMFilesPersistentIndexIterator> MMFilesPersistentIndex::lookup(t
|
||||||
reverse, leftBorder, rightBorder);
|
reverse, leftBorder, rightBorder);
|
||||||
}
|
}
|
||||||
|
|
||||||
Index::UsageCosts MMFilesPersistentIndex::supportsFilterCondition(
|
Index::FilterCosts MMFilesPersistentIndex::supportsFilterCondition(
|
||||||
std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
||||||
arangodb::aql::AstNode const* node, arangodb::aql::Variable const* reference,
|
arangodb::aql::AstNode const* node, arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const {
|
size_t itemsInIndex) const {
|
||||||
return SortedIndexAttributeMatcher::supportsFilterCondition(allIndexes, this, node, reference, itemsInIndex);
|
return SortedIndexAttributeMatcher::supportsFilterCondition(allIndexes, this, node, reference, itemsInIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
Index::UsageCosts MMFilesPersistentIndex::supportsSortCondition(arangodb::aql::SortCondition const* sortCondition,
|
Index::SortCosts MMFilesPersistentIndex::supportsSortCondition(arangodb::aql::SortCondition const* sortCondition,
|
||||||
arangodb::aql::Variable const* reference,
|
arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const {
|
size_t itemsInIndex) const {
|
||||||
return SortedIndexAttributeMatcher::supportsSortCondition(this, sortCondition, reference, itemsInIndex);
|
return SortedIndexAttributeMatcher::supportsSortCondition(this, sortCondition, reference, itemsInIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -161,14 +161,14 @@ class MMFilesPersistentIndex final : public MMFilesPathBasedIndex {
|
||||||
arangodb::velocypack::Slice const,
|
arangodb::velocypack::Slice const,
|
||||||
bool reverse) const;
|
bool reverse) const;
|
||||||
|
|
||||||
Index::UsageCosts supportsFilterCondition(std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
Index::FilterCosts supportsFilterCondition(std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
||||||
arangodb::aql::AstNode const* node,
|
arangodb::aql::AstNode const* node,
|
||||||
arangodb::aql::Variable const* reference,
|
arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const override;
|
size_t itemsInIndex) const override;
|
||||||
|
|
||||||
Index::UsageCosts supportsSortCondition(arangodb::aql::SortCondition const* sortCondition,
|
Index::SortCosts supportsSortCondition(arangodb::aql::SortCondition const* sortCondition,
|
||||||
arangodb::aql::Variable const* reference,
|
arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const override;
|
size_t itemsInIndex) const override;
|
||||||
|
|
||||||
std::unique_ptr<IndexIterator> iteratorForCondition(transaction::Methods* trx,
|
std::unique_ptr<IndexIterator> iteratorForCondition(transaction::Methods* trx,
|
||||||
arangodb::aql::AstNode const* node,
|
arangodb::aql::AstNode const* node,
|
||||||
|
|
|
@ -449,7 +449,7 @@ void MMFilesPrimaryIndex::invokeOnAllElementsForRemoval(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief checks whether the index supports the condition
|
/// @brief checks whether the index supports the condition
|
||||||
Index::UsageCosts MMFilesPrimaryIndex::supportsFilterCondition(
|
Index::FilterCosts MMFilesPrimaryIndex::supportsFilterCondition(
|
||||||
std::vector<std::shared_ptr<arangodb::Index>> const&,
|
std::vector<std::shared_ptr<arangodb::Index>> const&,
|
||||||
arangodb::aql::AstNode const* node, arangodb::aql::Variable const* reference,
|
arangodb::aql::AstNode const* node, arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const {
|
size_t itemsInIndex) const {
|
||||||
|
|
|
@ -269,10 +269,10 @@ class MMFilesPrimaryIndex final : public MMFilesIndex {
|
||||||
void invokeOnAllElements(std::function<bool(LocalDocumentId const&)>);
|
void invokeOnAllElements(std::function<bool(LocalDocumentId const&)>);
|
||||||
void invokeOnAllElementsForRemoval(std::function<bool(MMFilesSimpleIndexElement const&)>);
|
void invokeOnAllElementsForRemoval(std::function<bool(MMFilesSimpleIndexElement const&)>);
|
||||||
|
|
||||||
Index::UsageCosts supportsFilterCondition(std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
Index::FilterCosts supportsFilterCondition(std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
||||||
arangodb::aql::AstNode const* node,
|
arangodb::aql::AstNode const* node,
|
||||||
arangodb::aql::Variable const* reference,
|
arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const override;
|
size_t itemsInIndex) const override;
|
||||||
|
|
||||||
std::unique_ptr<IndexIterator> iteratorForCondition(transaction::Methods* trx,
|
std::unique_ptr<IndexIterator> iteratorForCondition(transaction::Methods* trx,
|
||||||
arangodb::aql::AstNode const* node,
|
arangodb::aql::AstNode const* node,
|
||||||
|
|
|
@ -1179,7 +1179,7 @@ std::unique_ptr<IndexIterator> MMFilesSkiplistIndex::iteratorForCondition(
|
||||||
!opts.ascending, builder.release());
|
!opts.ascending, builder.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
Index::UsageCosts MMFilesSkiplistIndex::supportsFilterCondition(
|
Index::FilterCosts MMFilesSkiplistIndex::supportsFilterCondition(
|
||||||
std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
||||||
arangodb::aql::AstNode const* node, arangodb::aql::Variable const* reference,
|
arangodb::aql::AstNode const* node, arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const {
|
size_t itemsInIndex) const {
|
||||||
|
@ -1188,9 +1188,9 @@ Index::UsageCosts MMFilesSkiplistIndex::supportsFilterCondition(
|
||||||
itemsInIndex);
|
itemsInIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
Index::UsageCosts MMFilesSkiplistIndex::supportsSortCondition(arangodb::aql::SortCondition const* sortCondition,
|
Index::SortCosts MMFilesSkiplistIndex::supportsSortCondition(arangodb::aql::SortCondition const* sortCondition,
|
||||||
arangodb::aql::Variable const* reference,
|
arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const {
|
size_t itemsInIndex) const {
|
||||||
return SortedIndexAttributeMatcher::supportsSortCondition(this, sortCondition, reference, itemsInIndex);
|
return SortedIndexAttributeMatcher::supportsSortCondition(this, sortCondition, reference, itemsInIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -285,14 +285,14 @@ class MMFilesSkiplistIndex : public MMFilesPathBasedIndex {
|
||||||
|
|
||||||
void unload() override;
|
void unload() override;
|
||||||
|
|
||||||
Index::UsageCosts supportsFilterCondition(std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
Index::FilterCosts supportsFilterCondition(std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
||||||
arangodb::aql::AstNode const* node,
|
arangodb::aql::AstNode const* node,
|
||||||
arangodb::aql::Variable const* reference,
|
arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const override;
|
size_t itemsInIndex) const override;
|
||||||
|
|
||||||
Index::UsageCosts supportsSortCondition(arangodb::aql::SortCondition const* sortCondition,
|
Index::SortCosts supportsSortCondition(arangodb::aql::SortCondition const* sortCondition,
|
||||||
arangodb::aql::Variable const* reference,
|
arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInindex) const override;
|
size_t itemsInindex) const override;
|
||||||
|
|
||||||
std::unique_ptr<IndexIterator> iteratorForCondition(transaction::Methods* trx,
|
std::unique_ptr<IndexIterator> iteratorForCondition(transaction::Methods* trx,
|
||||||
arangodb::aql::AstNode const* node,
|
arangodb::aql::AstNode const* node,
|
||||||
|
|
|
@ -519,7 +519,7 @@ Result RocksDBEdgeIndex::remove(transaction::Methods& trx, RocksDBMethods* mthd,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief checks whether the index supports the condition
|
/// @brief checks whether the index supports the condition
|
||||||
Index::UsageCosts RocksDBEdgeIndex::supportsFilterCondition(
|
Index::FilterCosts RocksDBEdgeIndex::supportsFilterCondition(
|
||||||
std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
||||||
arangodb::aql::AstNode const* node, arangodb::aql::Variable const* reference,
|
arangodb::aql::AstNode const* node, arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const {
|
size_t itemsInIndex) const {
|
||||||
|
|
|
@ -92,10 +92,10 @@ class RocksDBEdgeIndex final : public RocksDBIndex {
|
||||||
|
|
||||||
void toVelocyPack(VPackBuilder&, std::underlying_type<Index::Serialize>::type) const override;
|
void toVelocyPack(VPackBuilder&, std::underlying_type<Index::Serialize>::type) const override;
|
||||||
|
|
||||||
Index::UsageCosts supportsFilterCondition(std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
Index::FilterCosts supportsFilterCondition(std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
||||||
arangodb::aql::AstNode const* node,
|
arangodb::aql::AstNode const* node,
|
||||||
arangodb::aql::Variable const* reference,
|
arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const override;
|
size_t itemsInIndex) const override;
|
||||||
|
|
||||||
std::unique_ptr<IndexIterator> iteratorForCondition(transaction::Methods* trx,
|
std::unique_ptr<IndexIterator> iteratorForCondition(transaction::Methods* trx,
|
||||||
arangodb::aql::AstNode const* node,
|
arangodb::aql::AstNode const* node,
|
||||||
|
|
|
@ -669,7 +669,7 @@ Result RocksDBPrimaryIndex::remove(transaction::Methods& trx, RocksDBMethods* mt
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief checks whether the index supports the condition
|
/// @brief checks whether the index supports the condition
|
||||||
Index::UsageCosts RocksDBPrimaryIndex::supportsFilterCondition(
|
Index::FilterCosts RocksDBPrimaryIndex::supportsFilterCondition(
|
||||||
std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
||||||
arangodb::aql::AstNode const* node, arangodb::aql::Variable const* reference,
|
arangodb::aql::AstNode const* node, arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const {
|
size_t itemsInIndex) const {
|
||||||
|
@ -681,16 +681,19 @@ Index::UsageCosts RocksDBPrimaryIndex::supportsFilterCondition(
|
||||||
values, nonNullAttributes,
|
values, nonNullAttributes,
|
||||||
/*skip evaluation (during execution)*/ false);
|
/*skip evaluation (during execution)*/ false);
|
||||||
|
|
||||||
Index::UsageCosts costs;
|
Index::FilterCosts costs = Index::FilterCosts::defaultCosts(itemsInIndex);
|
||||||
costs.estimatedItems = values;
|
if (!found.empty()) {
|
||||||
// TODO: estimatedCost??
|
costs.supportsCondition = true;
|
||||||
costs.supportsCondition = !found.empty();
|
costs.coveredAttributes = 1; // always a single attribute
|
||||||
|
costs.estimatedItems = values;
|
||||||
|
costs.estimatedCosts = static_cast<double>(values);
|
||||||
|
}
|
||||||
return costs;
|
return costs;
|
||||||
}
|
}
|
||||||
|
|
||||||
Index::UsageCosts RocksDBPrimaryIndex::supportsSortCondition(arangodb::aql::SortCondition const* sortCondition,
|
Index::SortCosts RocksDBPrimaryIndex::supportsSortCondition(arangodb::aql::SortCondition const* sortCondition,
|
||||||
arangodb::aql::Variable const* reference,
|
arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const {
|
size_t itemsInIndex) const {
|
||||||
return SortedIndexAttributeMatcher::supportsSortCondition(this, sortCondition, reference, itemsInIndex);
|
return SortedIndexAttributeMatcher::supportsSortCondition(this, sortCondition, reference, itemsInIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,14 +90,14 @@ class RocksDBPrimaryIndex final : public RocksDBIndex {
|
||||||
bool lookupRevision(transaction::Methods* trx, arangodb::velocypack::StringRef key,
|
bool lookupRevision(transaction::Methods* trx, arangodb::velocypack::StringRef key,
|
||||||
LocalDocumentId& id, TRI_voc_rid_t& revisionId) const;
|
LocalDocumentId& id, TRI_voc_rid_t& revisionId) const;
|
||||||
|
|
||||||
Index::UsageCosts supportsFilterCondition(std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
Index::FilterCosts supportsFilterCondition(std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
||||||
arangodb::aql::AstNode const* node,
|
arangodb::aql::AstNode const* node,
|
||||||
arangodb::aql::Variable const* reference,
|
arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const override;
|
size_t itemsInIndex) const override;
|
||||||
|
|
||||||
Index::UsageCosts supportsSortCondition(arangodb::aql::SortCondition const* node,
|
Index::SortCosts supportsSortCondition(arangodb::aql::SortCondition const* node,
|
||||||
arangodb::aql::Variable const* reference,
|
arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const override;
|
size_t itemsInIndex) const override;
|
||||||
|
|
||||||
std::unique_ptr<IndexIterator> iteratorForCondition(transaction::Methods* trx,
|
std::unique_ptr<IndexIterator> iteratorForCondition(transaction::Methods* trx,
|
||||||
arangodb::aql::AstNode const* node,
|
arangodb::aql::AstNode const* node,
|
||||||
|
|
|
@ -1030,16 +1030,16 @@ std::unique_ptr<IndexIterator> RocksDBVPackIndex::lookup(transaction::Methods* t
|
||||||
return std::make_unique<RocksDBVPackIndexIterator>(&_collection, trx, this, reverse, std::move(bounds));
|
return std::make_unique<RocksDBVPackIndexIterator>(&_collection, trx, this, reverse, std::move(bounds));
|
||||||
}
|
}
|
||||||
|
|
||||||
Index::UsageCosts RocksDBVPackIndex::supportsFilterCondition(
|
Index::FilterCosts RocksDBVPackIndex::supportsFilterCondition(
|
||||||
std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
||||||
arangodb::aql::AstNode const* node, arangodb::aql::Variable const* reference,
|
arangodb::aql::AstNode const* node, arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const {
|
size_t itemsInIndex) const {
|
||||||
return SortedIndexAttributeMatcher::supportsFilterCondition(allIndexes, this, node, reference, itemsInIndex);
|
return SortedIndexAttributeMatcher::supportsFilterCondition(allIndexes, this, node, reference, itemsInIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
Index::UsageCosts RocksDBVPackIndex::supportsSortCondition(arangodb::aql::SortCondition const* sortCondition,
|
Index::SortCosts RocksDBVPackIndex::supportsSortCondition(arangodb::aql::SortCondition const* sortCondition,
|
||||||
arangodb::aql::Variable const* reference,
|
arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const {
|
size_t itemsInIndex) const {
|
||||||
return SortedIndexAttributeMatcher::supportsSortCondition(this, sortCondition, reference, itemsInIndex);
|
return SortedIndexAttributeMatcher::supportsSortCondition(this, sortCondition, reference, itemsInIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,14 +97,14 @@ class RocksDBVPackIndex : public RocksDBIndex {
|
||||||
std::unique_ptr<IndexIterator> lookup(transaction::Methods*,
|
std::unique_ptr<IndexIterator> lookup(transaction::Methods*,
|
||||||
arangodb::velocypack::Slice const, bool reverse) const;
|
arangodb::velocypack::Slice const, bool reverse) const;
|
||||||
|
|
||||||
Index::UsageCosts supportsFilterCondition(std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
Index::FilterCosts supportsFilterCondition(std::vector<std::shared_ptr<arangodb::Index>> const& allIndexes,
|
||||||
arangodb::aql::AstNode const* node,
|
arangodb::aql::AstNode const* node,
|
||||||
arangodb::aql::Variable const* reference,
|
arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const override;
|
size_t itemsInIndex) const override;
|
||||||
|
|
||||||
Index::UsageCosts supportsSortCondition(arangodb::aql::SortCondition const* sortCondition,
|
Index::SortCosts supportsSortCondition(arangodb::aql::SortCondition const* sortCondition,
|
||||||
arangodb::aql::Variable const* reference,
|
arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const override;
|
size_t itemsInIndex) const override;
|
||||||
|
|
||||||
arangodb::aql::AstNode* specializeCondition(arangodb::aql::AstNode* node,
|
arangodb::aql::AstNode* specializeCondition(arangodb::aql::AstNode* node,
|
||||||
arangodb::aql::Variable const* reference) const override;
|
arangodb::aql::Variable const* reference) const override;
|
||||||
|
|
|
@ -568,12 +568,13 @@ std::pair<bool, bool> transaction::Methods::findIndexHandleForAndNode(
|
||||||
double filterCost = 0.0;
|
double filterCost = 0.0;
|
||||||
double sortCost = 0.0;
|
double sortCost = 0.0;
|
||||||
size_t itemsInIndex = itemsInCollection;
|
size_t itemsInIndex = itemsInCollection;
|
||||||
|
size_t coveredAttributes = 0;
|
||||||
|
|
||||||
bool supportsFilter = false;
|
bool supportsFilter = false;
|
||||||
bool supportsSort = false;
|
bool supportsSort = false;
|
||||||
|
|
||||||
// check if the index supports the filter condition
|
// check if the index supports the filter condition
|
||||||
Index::UsageCosts costs = idx->supportsFilterCondition(indexes, node, reference, itemsInIndex);
|
Index::FilterCosts costs = idx->supportsFilterCondition(indexes, node, reference, itemsInIndex);
|
||||||
|
|
||||||
if (costs.supportsCondition) {
|
if (costs.supportsCondition) {
|
||||||
// index supports the filter condition
|
// index supports the filter condition
|
||||||
|
@ -594,12 +595,12 @@ std::pair<bool, bool> transaction::Methods::findIndexHandleForAndNode(
|
||||||
// general be supported by an index. for this, a sort condition must not
|
// general be supported by an index. for this, a sort condition must not
|
||||||
// be empty, must consist only of attribute access, and all attributes
|
// be empty, must consist only of attribute access, and all attributes
|
||||||
// must be sorted in the direction
|
// must be sorted in the direction
|
||||||
Index::UsageCosts costs = idx->supportsSortCondition(sortCondition, reference, itemsInIndex);
|
Index::SortCosts costs = idx->supportsSortCondition(sortCondition, reference, itemsInIndex);
|
||||||
if (costs.supportsCondition) {
|
if (costs.supportsCondition) {
|
||||||
supportsSort = true;
|
supportsSort = true;
|
||||||
}
|
}
|
||||||
sortCost = costs.estimatedCosts;
|
sortCost = costs.estimatedCosts;
|
||||||
// TODO: fill coveredAttributes so we don't need to determine it later on
|
coveredAttributes = costs.coveredAttributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!supportsSort && isOnlyAttributeAccess && node->isOnlyEqualityMatch()) {
|
if (!supportsSort && isOnlyAttributeAccess && node->isOnlyEqualityMatch()) {
|
||||||
|
@ -607,9 +608,7 @@ std::pair<bool, bool> transaction::Methods::findIndexHandleForAndNode(
|
||||||
// only of equality lookups (==)
|
// only of equality lookups (==)
|
||||||
// now check if the index fields are the same as the sort condition fields
|
// now check if the index fields are the same as the sort condition fields
|
||||||
// e.g. FILTER c.value1 == 1 && c.value2 == 42 SORT c.value1, c.value2
|
// e.g. FILTER c.value1 == 1 && c.value2 == 42 SORT c.value1, c.value2
|
||||||
size_t coveredFields = sortCondition->coveredAttributes(reference, idx->fields());
|
if (coveredAttributes == sortCondition->numAttributes() &&
|
||||||
|
|
||||||
if (coveredFields == sortCondition->numAttributes() &&
|
|
||||||
(idx->isSorted() || idx->fields().size() == sortCondition->numAttributes())) {
|
(idx->isSorted() || idx->fields().size() == sortCondition->numAttributes())) {
|
||||||
// no sorting needed
|
// no sorting needed
|
||||||
sortCost = 0.0;
|
sortCost = 0.0;
|
||||||
|
@ -627,7 +626,7 @@ std::pair<bool, bool> transaction::Methods::findIndexHandleForAndNode(
|
||||||
if (supportsSort) {
|
if (supportsSort) {
|
||||||
totalCost += sortCost;
|
totalCost += sortCost;
|
||||||
} else {
|
} else {
|
||||||
totalCost += Index::UsageCosts::defaultsForSorting(itemsInIndex, idx->isPersistent()).estimatedCosts;
|
totalCost += Index::SortCosts::defaultCosts(itemsInIndex, idx->isPersistent()).estimatedCosts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -703,7 +702,7 @@ bool transaction::Methods::findIndexHandleForAndNode(
|
||||||
auto considerIndex = [&bestIndex, &bestCost, itemsInCollection, &indexes, &node,
|
auto considerIndex = [&bestIndex, &bestCost, itemsInCollection, &indexes, &node,
|
||||||
reference](std::shared_ptr<Index> const& idx) -> void {
|
reference](std::shared_ptr<Index> const& idx) -> void {
|
||||||
// check if the index supports the filter expression
|
// check if the index supports the filter expression
|
||||||
Index::UsageCosts costs = idx->supportsFilterCondition(indexes, node, reference, itemsInCollection);
|
Index::FilterCosts costs = idx->supportsFilterCondition(indexes, node, reference, itemsInCollection);
|
||||||
|
|
||||||
// enable the following line to see index candidates considered with their
|
// enable the following line to see index candidates considered with their
|
||||||
// abilities and scores
|
// abilities and scores
|
||||||
|
@ -2938,7 +2937,7 @@ bool transaction::Methods::getIndexForSortCondition(
|
||||||
|
|
||||||
auto considerIndex = [reference, sortCondition, itemsInIndex, &bestCost, &bestIndex,
|
auto considerIndex = [reference, sortCondition, itemsInIndex, &bestCost, &bestIndex,
|
||||||
&coveredAttributes](std::shared_ptr<Index> const& idx) -> void {
|
&coveredAttributes](std::shared_ptr<Index> const& idx) -> void {
|
||||||
Index::UsageCosts costs = idx->supportsSortCondition(sortCondition, reference, itemsInIndex);
|
Index::SortCosts costs = idx->supportsSortCondition(sortCondition, reference, itemsInIndex);
|
||||||
if (costs.supportsCondition &&
|
if (costs.supportsCondition &&
|
||||||
(bestIndex == nullptr || costs.estimatedCosts < bestCost)) {
|
(bestIndex == nullptr || costs.estimatedCosts < bestCost)) {
|
||||||
bestCost = costs.estimatedCosts;
|
bestCost = costs.estimatedCosts;
|
||||||
|
|
|
@ -248,10 +248,10 @@ class EdgeIndexMock final : public arangodb::Index {
|
||||||
return {}; // ok
|
return {}; // ok
|
||||||
}
|
}
|
||||||
|
|
||||||
Index::UsageCosts supportsFilterCondition(std::vector<std::shared_ptr<arangodb::Index>> const& /*allIndexes*/,
|
Index::FilterCosts supportsFilterCondition(std::vector<std::shared_ptr<arangodb::Index>> const& /*allIndexes*/,
|
||||||
arangodb::aql::AstNode const* node,
|
arangodb::aql::AstNode const* node,
|
||||||
arangodb::aql::Variable const* reference,
|
arangodb::aql::Variable const* reference,
|
||||||
size_t itemsInIndex) const override {
|
size_t itemsInIndex) const override {
|
||||||
arangodb::SimpleAttributeEqualityMatcher matcher(IndexAttributes);
|
arangodb::SimpleAttributeEqualityMatcher matcher(IndexAttributes);
|
||||||
return matcher.matchOne(this, node, reference, itemsInIndex);
|
return matcher.matchOne(this, node, reference, itemsInIndex);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue