mirror of https://gitee.com/bigwinds/arangodb
check filter condition and sort condition support for all index types
This commit is contained in:
parent
27bcd7ee84
commit
67de5480e8
|
@ -197,52 +197,54 @@ bool Condition::findIndexForAndNode (AstNode const* node,
|
|||
SortCondition const& sortCondition) {
|
||||
// We can only iterate through a proper DNF
|
||||
TRI_ASSERT(node->type == NODE_TYPE_OPERATOR_NARY_AND);
|
||||
|
||||
static double const MaxFilterCost = 2.0;
|
||||
static double const MaxSortCost = 2.0;
|
||||
|
||||
// This code is never responsible for the content of this pointer.
|
||||
Index const* bestIndex = nullptr;
|
||||
double bestCost = MaxFilterCost + MaxSortCost + std::numeric_limits<double>::epsilon();
|
||||
|
||||
static double const MaxFilterCost = 10.0;
|
||||
static double const MaxSortCost = 10.0;
|
||||
|
||||
double bestCost = -1.0; // All costs are > 0, so if we have found one we can use it.
|
||||
std::vector<Index const*> indexes = colNode->collection()->getIndexes();
|
||||
|
||||
for (auto& idx : indexes) {
|
||||
double filterCost = 0.0;
|
||||
double sortCost = 0.0;
|
||||
|
||||
std::cout << "CHECKING INDEX : " << triagens::basics::JsonHelper::toString(idx->getInternals()->toJson(TRI_UNKNOWN_MEM_ZONE, false).json()) << "\n";
|
||||
|
||||
// check if the index supports the filter expression
|
||||
double estimatedCost;
|
||||
if (idx->supportsFilterCondition(node, reference, estimatedCost)) {
|
||||
std::cout << "- INDEX SUPPORTS FILTER CONDITION\n";
|
||||
// index supports the filter expression
|
||||
// index supports the filter condition
|
||||
filterCost = estimatedCost;
|
||||
}
|
||||
else {
|
||||
std::cout << "- INDEX DOES NOT SUPPORT FILTER CONDITION\n";
|
||||
// index does not support the filter condition
|
||||
filterCost = MaxFilterCost;
|
||||
}
|
||||
|
||||
if (! sortCondition.isEmpty() &&
|
||||
sortCondition.isOnlyAttributeAccess()) {
|
||||
sortCondition.isOnlyAttributeAccess() &&
|
||||
sortCondition.isUnidirectional()) {
|
||||
// only go in here if we actually have a sort condition and it can in
|
||||
// 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
|
||||
double estimatedCost;
|
||||
if (idx->isSorted() &&
|
||||
idx->supportsSortCondition(&sortCondition, reference, estimatedCost)) {
|
||||
std::cout << "- INDEX SUPPORTS SORT CONDITION\n";
|
||||
// index supports the sort condition
|
||||
sortCost = estimatedCost;
|
||||
}
|
||||
else {
|
||||
std::cout << "- INDEX DOES NOT SUPPORT SORT CONDITION\n";
|
||||
// index does not support the sort condition
|
||||
sortCost = MaxSortCost;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "- INDEX FILTER COST: " << filterCost << ", SORT COST: " << sortCost << "\n";
|
||||
// std::cout << "INDEX: " << triagens::basics::JsonHelper::toString(idx->getInternals()->toJson(TRI_UNKNOWN_MEM_ZONE, false).json()) << ", FILTER COST: " << filterCost << ", SORT COST: " << sortCost << "\n";
|
||||
double const totalCost = filterCost + sortCost;
|
||||
|
||||
if (bestCost < totalCost) {
|
||||
if (totalCost < bestCost) {
|
||||
bestIndex = idx;
|
||||
bestCost = totalCost;
|
||||
}
|
||||
|
@ -252,8 +254,6 @@ bool Condition::findIndexForAndNode (AstNode const* node,
|
|||
return false;
|
||||
}
|
||||
|
||||
std::cout << "We can use indexes for var: " << reference->name << " in collection " << colNode->collection()->getName() << ":" << std::endl;
|
||||
std::cout << "We use: " << bestIndex->toJson() << std::endl;
|
||||
usedIndexes.emplace_back(bestIndex);
|
||||
|
||||
return true;
|
||||
|
|
|
@ -44,7 +44,7 @@ SortCondition::SortCondition (std::vector<std::pair<AstNode const*, bool>> const
|
|||
: _expressions(expressions),
|
||||
_unidirectional(true),
|
||||
_onlyAttributeAccess(true) {
|
||||
|
||||
|
||||
size_t const n = _expressions.size();
|
||||
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
|
@ -65,15 +65,19 @@ SortCondition::SortCondition (std::vector<std::pair<AstNode const*, bool>> const
|
|||
if (node->type == NODE_TYPE_REFERENCE) {
|
||||
handled = true;
|
||||
|
||||
_fields.emplace_back(std::make_pair(static_cast<Variable const*>(node->getData())->name, fieldNames));
|
||||
_fields.emplace_back(std::make_pair(static_cast<Variable const*>(node->getData()), fieldNames));
|
||||
}
|
||||
}
|
||||
|
||||
if (! handled) {
|
||||
_fields.emplace_back(std::pair<std::string, std::vector<triagens::basics::AttributeName>>());
|
||||
_fields.emplace_back(std::pair<Variable const*, std::vector<triagens::basics::AttributeName>>());
|
||||
_onlyAttributeAccess = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
_onlyAttributeAccess = false;
|
||||
}
|
||||
}
|
||||
|
||||
SortCondition::SortCondition (std::vector<std::pair<VariableId, bool>> const& sorts,
|
||||
|
@ -83,6 +87,7 @@ SortCondition::SortCondition (std::vector<std::pair<VariableId, bool>> const& so
|
|||
_onlyAttributeAccess(true) {
|
||||
|
||||
size_t const n = sorts.size();
|
||||
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
if (_unidirectional && i > 0 && sorts[i].second != sorts[i - 1].second) {
|
||||
_unidirectional = false;
|
||||
|
@ -103,19 +108,73 @@ SortCondition::SortCondition (std::vector<std::pair<VariableId, bool>> const& so
|
|||
fieldNames.emplace_back(triagens::basics::AttributeName(node->getStringValue()));
|
||||
node = node->getMember(0);
|
||||
}
|
||||
|
||||
if (node->type == NODE_TYPE_REFERENCE) {
|
||||
handled = true;
|
||||
|
||||
_fields.emplace_back(std::make_pair(static_cast<Variable const*>(node->getData())->name, fieldNames));
|
||||
_fields.emplace_back(std::make_pair(static_cast<Variable const*>(node->getData()), fieldNames));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! handled) {
|
||||
_fields.emplace_back(std::pair<std::string, std::vector<triagens::basics::AttributeName>>());
|
||||
_fields.emplace_back(std::pair<Variable const*, std::vector<triagens::basics::AttributeName>>());
|
||||
_onlyAttributeAccess = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
_onlyAttributeAccess = false;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns the number of attributes in the sort condition covered
|
||||
/// by the specified index fields
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
size_t SortCondition::isCoveredBy (Variable const* reference,
|
||||
std::vector<std::vector<triagens::basics::AttributeName>> const& indexAttributes) const {
|
||||
size_t coveredAttributes = 0;
|
||||
|
||||
for (size_t i = 0; i < indexAttributes.size(); ++i) {
|
||||
if (i >= _fields.size()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (reference != _fields[i].first) {
|
||||
break;
|
||||
}
|
||||
|
||||
auto const& fieldNames = _fields[i].second;
|
||||
if (fieldNames.size() != indexAttributes[i].size()) {
|
||||
// different attribute path
|
||||
break;
|
||||
}
|
||||
|
||||
bool found = true;
|
||||
for (size_t j = 0; j < indexAttributes[i].size(); ++j) {
|
||||
if (indexAttributes[i][j].shouldExpand ||
|
||||
fieldNames[j] != indexAttributes[i][j].name) {
|
||||
// expanded attribute or different attribute
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (! found) {
|
||||
break;
|
||||
}
|
||||
|
||||
// same attribute
|
||||
++coveredAttributes;
|
||||
}
|
||||
|
||||
return coveredAttributes;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -92,6 +92,22 @@ namespace triagens {
|
|||
return _fields.empty();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief number of attributes in condition
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline size_t numAttributes () const {
|
||||
return _fields.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns the number of attributes in the sort condition covered
|
||||
/// by the specified index fields
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
size_t isCoveredBy (Variable const*,
|
||||
std::vector<std::vector<triagens::basics::AttributeName>> const&) const;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -108,7 +124,7 @@ namespace triagens {
|
|||
/// @brief fields used in the sort conditions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::vector<std::pair<std::string, std::vector<triagens::basics::AttributeName>>> _fields;
|
||||
std::vector<std::pair<Variable const*, std::vector<triagens::basics::AttributeName>>> _fields;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief whether or not the sort is unidirectional
|
||||
|
|
|
@ -546,7 +546,10 @@ int EdgeIndex::sizeHint (size_t size) {
|
|||
bool EdgeIndex::supportsFilterCondition (triagens::aql::AstNode const* node,
|
||||
triagens::aql::Variable const* reference,
|
||||
double& estimatedCost) const {
|
||||
SimpleAttributeEqualityMatcher matcher({ { TRI_VOC_ATTRIBUTE_FROM }, { TRI_VOC_ATTRIBUTE_TO } });
|
||||
SimpleAttributeEqualityMatcher matcher({
|
||||
{ triagens::basics::AttributeName(TRI_VOC_ATTRIBUTE_FROM, false) },
|
||||
{ triagens::basics::AttributeName(TRI_VOC_ATTRIBUTE_TO, false) }
|
||||
});
|
||||
return matcher.matchOne(this, node, reference, estimatedCost);
|
||||
}
|
||||
|
||||
|
|
|
@ -702,7 +702,7 @@ int HashIndex::removeMulti (TRI_doc_mptr_t const* doc, bool isRollback) {
|
|||
bool HashIndex::supportsFilterCondition (triagens::aql::AstNode const* node,
|
||||
triagens::aql::Variable const* reference,
|
||||
double& estimatedCost) const {
|
||||
SimpleAttributeEqualityMatcher matcher(fieldNames());
|
||||
SimpleAttributeEqualityMatcher matcher(fields());
|
||||
return matcher.matchAll(this, node, reference, estimatedCost);
|
||||
}
|
||||
|
||||
|
|
|
@ -437,6 +437,7 @@ bool Index::hasBatchInsert () const {
|
|||
bool Index::supportsFilterCondition (triagens::aql::AstNode const* node,
|
||||
triagens::aql::Variable const* reference,
|
||||
double& estimatedCost) const {
|
||||
// by default, no filter conditions are supported
|
||||
estimatedCost = 0.0;
|
||||
return false;
|
||||
}
|
||||
|
@ -447,7 +448,8 @@ bool Index::supportsFilterCondition (triagens::aql::AstNode const* node,
|
|||
|
||||
bool Index::supportsSortCondition (triagens::aql::SortCondition const* sortCondition,
|
||||
triagens::aql::Variable const* reference,
|
||||
double& estimatedCost) const {
|
||||
double& estimatedCost) const {
|
||||
// by default, no sort conditions are supported
|
||||
estimatedCost = 0.0;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -277,7 +277,10 @@ void PrimaryIndex::invokeOnAllElements (std::function<void(TRI_doc_mptr_t*)> wor
|
|||
bool PrimaryIndex::supportsFilterCondition (triagens::aql::AstNode const* node,
|
||||
triagens::aql::Variable const* reference,
|
||||
double& estimatedCost) const {
|
||||
SimpleAttributeEqualityMatcher matcher({ { TRI_VOC_ATTRIBUTE_ID }, { TRI_VOC_ATTRIBUTE_KEY } });
|
||||
SimpleAttributeEqualityMatcher matcher({
|
||||
{ triagens::basics::AttributeName(TRI_VOC_ATTRIBUTE_ID, false) },
|
||||
{ triagens::basics::AttributeName(TRI_VOC_ATTRIBUTE_KEY, false) }
|
||||
});
|
||||
return matcher.matchOne(this, node, reference, estimatedCost);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "Aql/Ast.h"
|
||||
#include "Aql/AstNode.h"
|
||||
#include "Aql/Variable.h"
|
||||
#include "Basics/AttributeNameParser.h"
|
||||
#include "Indexes/Index.h"
|
||||
#include "VocBase/vocbase.h"
|
||||
|
||||
|
@ -52,7 +53,7 @@ namespace triagens {
|
|||
|
||||
public:
|
||||
|
||||
SimpleAttributeEqualityMatcher (std::vector<std::vector<std::string>> const& attributes)
|
||||
SimpleAttributeEqualityMatcher (std::vector<std::vector<triagens::basics::AttributeName>> const& attributes)
|
||||
: _attributes(attributes) {
|
||||
}
|
||||
|
||||
|
@ -217,7 +218,8 @@ namespace triagens {
|
|||
|
||||
bool match = true;
|
||||
for (size_t j = 0; j < _attributes[i].size(); ++j) {
|
||||
if (_attributes[i][j] != fieldNames[j]) {
|
||||
if (_attributes[i][j].shouldExpand ||
|
||||
_attributes[i][j].name != fieldNames[j]) {
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
|
@ -243,7 +245,7 @@ namespace triagens {
|
|||
/// @brief array of attributes used for comparisons
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::vector<std::vector<std::string>> _attributes;
|
||||
std::vector<std::vector<triagens::basics::AttributeName>> _attributes;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -1032,14 +1032,27 @@ bool SkiplistIndex::supportsFilterCondition (triagens::aql::AstNode const* node,
|
|||
return estimatedCost * static_cast<double>(values);
|
||||
}
|
||||
|
||||
estimatedCost = 1.0; // set to highest possible cost by default
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SkiplistIndex::supportsSortCondition (triagens::aql::SortCondition const* sortCondition,
|
||||
triagens::aql::Variable const* reference,
|
||||
double& estimatedCost) const {
|
||||
estimatedCost = 0.0;
|
||||
TRI_ASSERT(sortCondition != nullptr);
|
||||
|
||||
if (! _useExpansion &&
|
||||
sortCondition->isUnidirectional() &&
|
||||
sortCondition->isOnlyAttributeAccess()) {
|
||||
|
||||
size_t const coveredAttributes = sortCondition->isCoveredBy(reference, _fields);
|
||||
|
||||
if (coveredAttributes >= sortCondition->numAttributes()) {
|
||||
estimatedCost = 0.0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
estimatedCost = 1.0;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -238,7 +238,7 @@ namespace triagens {
|
|||
}
|
||||
|
||||
bool isSorted () const override final {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hasSelectivityEstimate () const override final {
|
||||
|
|
Loading…
Reference in New Issue