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