-
Notifications
You must be signed in to change notification settings - Fork 173
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Query index improvements #6376
Query index improvements #6376
Changes from all commits
9f76977
db39fde
fbc84cf
13abce8
d4632e9
a728860
65dc23c
78affcf
5847885
b3be7da
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -992,12 +992,14 @@ void Query::aggregate(QueryStateBase& st, ColKey column_key) const | |
auto node = pn->m_children[best]; | ||
if (node->has_search_index()) { | ||
auto keys = node->index_based_keys(); | ||
REALM_ASSERT(keys); | ||
// The node having the search index can be removed from the query as we know that | ||
// all the objects will match this condition | ||
pn->m_children[best] = pn->m_children.back(); | ||
pn->m_children.pop_back(); | ||
for (auto key : keys) { | ||
auto obj = m_table->get_object(key); | ||
const size_t num_keys = keys->size(); | ||
for (size_t i = 0; i < num_keys; ++i) { | ||
auto obj = m_table->get_object(keys->get(i)); | ||
if (pn->m_children.empty() || eval_object(obj)) { | ||
st.m_key_offset = obj.get_key().value; | ||
st.match(realm::npos, obj.get<T>(column_key)); | ||
|
@@ -1312,15 +1314,18 @@ void Query::do_find_all(TableView& ret, size_t limit) const | |
auto best = find_best_node(pn); | ||
auto node = pn->m_children[best]; | ||
if (node->has_search_index()) { | ||
auto keys = node->index_based_keys(); | ||
REALM_ASSERT(keys); | ||
KeyColumn& refs = ret.m_key_values; | ||
|
||
// The node having the search index can be removed from the query as we know that | ||
// all the objects will match this condition | ||
pn->m_children[best] = pn->m_children.back(); | ||
pn->m_children.pop_back(); | ||
|
||
auto keys = node->index_based_keys(); | ||
for (auto key : keys) { | ||
const size_t num_keys = keys->size(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK it seems it is a pattern, why do we need to do this rather than a simpler There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The iteration pattern here isn't really part of the optimization. The change is because There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the iterator is a "nice to have" feature, but that's ok to leave it as it is, it is up to you. |
||
for (size_t i = 0; i < num_keys; ++i) { | ||
ObjKey key = keys->get(i); | ||
if (limit == 0) | ||
break; | ||
if (pn->m_children.empty()) { | ||
|
@@ -1433,13 +1438,15 @@ size_t Query::do_count(size_t limit) const | |
auto node = pn->m_children[best]; | ||
if (node->has_search_index()) { | ||
auto keys = node->index_based_keys(); | ||
REALM_ASSERT(keys); | ||
if (pn->m_children.size() > 1) { | ||
// The node having the search index can be removed from the query as we know that | ||
// all the objects will match this condition | ||
pn->m_children[best] = pn->m_children.back(); | ||
pn->m_children.pop_back(); | ||
for (auto key : keys) { | ||
auto obj = m_table->get_object(key); | ||
const size_t num_keys = keys->size(); | ||
for (size_t i = 0; i < num_keys; ++i) { | ||
auto obj = m_table->get_object(keys->get(i)); | ||
if (eval_object(obj)) { | ||
++cnt; | ||
if (cnt == limit) | ||
|
@@ -1449,7 +1456,7 @@ size_t Query::do_count(size_t limit) const | |
} | ||
else { | ||
// The node having the search index is the only node | ||
auto sz = keys.size(); | ||
auto sz = keys->size(); | ||
cnt = std::min(limit, sz); | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -72,7 +72,7 @@ struct Contains : public HackClass { | |
{ | ||
if (m1.is_null()) | ||
return !m2.is_null(); | ||
if (Mixed::types_are_comparable(m1, m2)) { | ||
if (m1.is_type(type_String, type_Binary) && Mixed::types_are_comparable(m1, m2)) { | ||
BinaryData b1 = m1.get_binary(); | ||
BinaryData b2 = m2.get_binary(); | ||
return operator()(b1, b2, false, false); | ||
|
@@ -133,7 +133,7 @@ struct Like : public HackClass { | |
{ | ||
if (m1.is_null() && m2.is_null()) | ||
return true; | ||
if (Mixed::types_are_comparable(m1, m2)) { | ||
if (m1.is_type(type_String, type_Binary) && Mixed::types_are_comparable(m1, m2)) { | ||
BinaryData b1 = m1.get_binary(); | ||
BinaryData b2 = m2.get_binary(); | ||
return operator()(b1, b2, false, false); | ||
|
@@ -186,7 +186,7 @@ struct BeginsWith : public HackClass { | |
|
||
bool operator()(const QueryValue& m1, const QueryValue& m2) const | ||
{ | ||
if (Mixed::types_are_comparable(m1, m2)) { | ||
if (m1.is_type(type_String, type_Binary) && Mixed::types_are_comparable(m1, m2)) { | ||
BinaryData b1 = m1.get_binary(); | ||
BinaryData b2 = m2.get_binary(); | ||
return b2.begins_with(b1); | ||
|
@@ -232,7 +232,7 @@ struct EndsWith : public HackClass { | |
|
||
bool operator()(const QueryValue& m1, const QueryValue& m2) const | ||
{ | ||
if (Mixed::types_are_comparable(m1, m2)) { | ||
if (m1.is_type(type_String, type_Binary) && Mixed::types_are_comparable(m1, m2)) { | ||
BinaryData b1 = m1.get_binary(); | ||
BinaryData b2 = m2.get_binary(); | ||
return operator()(b1, b2, false, false); | ||
|
@@ -395,7 +395,7 @@ struct ContainsIns : public HackClass { | |
{ | ||
if (m1.is_null()) | ||
return !m2.is_null(); | ||
if (Mixed::types_are_comparable(m1, m2)) { | ||
if (m1.is_type(type_String, type_Binary) && Mixed::types_are_comparable(m1, m2)) { | ||
BinaryData b1 = m1.get_binary(); | ||
BinaryData b2 = m2.get_binary(); | ||
return operator()(b1, b2, false, false); | ||
|
@@ -479,7 +479,7 @@ struct LikeIns : public HackClass { | |
{ | ||
if (m1.is_null() && m2.is_null()) | ||
return true; | ||
if (Mixed::types_are_comparable(m1, m2)) { | ||
if (m1.is_type(type_String, type_Binary) && Mixed::types_are_comparable(m1, m2)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe, since you are repeating this over several There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The problem is that both of the values could be numerics, so |
||
BinaryData b1 = m1.get_binary(); | ||
BinaryData b2 = m2.get_binary(); | ||
return operator()(b1, b2, false, false); | ||
|
@@ -544,7 +544,7 @@ struct BeginsWithIns : public HackClass { | |
|
||
bool operator()(const QueryValue& m1, const QueryValue& m2) const | ||
{ | ||
if (Mixed::types_are_comparable(m1, m2)) { | ||
if (m1.is_type(type_String, type_Binary) && Mixed::types_are_comparable(m1, m2)) { | ||
BinaryData b1 = m1.get_binary(); | ||
BinaryData b2 = m2.get_binary(); | ||
return operator()(b1, b2, false, false); | ||
|
@@ -610,7 +610,7 @@ struct EndsWithIns : public HackClass { | |
|
||
bool operator()(const QueryValue& m1, const QueryValue& m2) const | ||
{ | ||
if (Mixed::types_are_comparable(m1, m2)) { | ||
if (m1.is_type(type_String, type_Binary) && Mixed::types_are_comparable(m1, m2)) { | ||
BinaryData b1 = m1.get_binary(); | ||
BinaryData b2 = m2.get_binary(); | ||
return operator()(b1, b2, false, false); | ||
|
@@ -675,8 +675,18 @@ struct EqualIns : public HackClass { | |
|
||
bool operator()(const QueryValue& m1, const QueryValue& m2) const | ||
{ | ||
return (m1.is_null() && m2.is_null()) || | ||
(Mixed::types_are_comparable(m1, m2) && operator()(m1.get_binary(), m2.get_binary(), false, false)); | ||
if (m1.is_null() && m2.is_null()) { | ||
return true; | ||
} | ||
else if (Mixed::types_are_comparable(m1, m2)) { | ||
if (m1.is_type(type_String, type_Binary)) { | ||
return operator()(m1.get_binary(), m2.get_binary(), false, false); | ||
} | ||
else { | ||
return m1 == m2; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
template <class A, class B> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this loop really making a difference?