Skip to content
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

Merged
merged 10 commits into from
Mar 23, 2023
Merged

Query index improvements #6376

merged 10 commits into from
Mar 23, 2023

Conversation

ironage
Copy link
Contributor

@ironage ironage commented Mar 11, 2023

  • We had several copies of nearly identical code for using the string index in queries. I started by refactoring this out into a reusable IndexEvaluator class to clean things up. This also makes it easy to use StringIndex::find_all_no_copy() which avoids copying out all the results into a temporary buffer of ObjKeys. Taking advantage of that provides a good speed up when only Query::count() is used and the results aren't actually needed. It also reduces memory use which might be noticeable for queries that return an enormous number of results.
  • Optimize Timestamp and Bool equality queries to use the index if possible.
  • Optimize Mixed case insensitive queries without an index to use precomputed case mapping which gives a small speedup.
  • Optimize Mixed case insensitive queries with an index

Bugs discovered while making changes:

  • During the refactoring, I noticed that Mixed equality was returning case insensitive results when using an index.
  • Adding an index to a Mixed property on a non-empty table was hitting an assertion
  • Querying with string operators (or equality with case insensitive) on a mixed property when the target was not a string caused assertions
Req runs: 1000  EmptyCommit (Full   , EncryptionOff):         min    607us (-80.24%)           max  97.89ms (+1388.82%)         med   5.02ms (+0.74%)            avg   4.55ms (-8.77%)            stddev  4.25ms (+787.52%)
Req runs:  728  EmptyCommit (Full   , EncryptionOn):          min    731us (+11.84%)           max 115.53ms (+21.48%)           med   5.62ms (+1.57%)            avg   5.20ms (+2.81%)            stddev  4.40ms (+18.49%)

Req runs: 1000  EmptyCommit (MemOnly, EncryptionOff):         min     26us (+0.32%)            max     49us (-8.48%)            med     31us (-0.66%)            avg     31us (-1.72%)            stddev     3us (-9.05%)

Req runs:  433  NonInitiatorOpen (Full   , EncryptionOff):     min   1.09ms (-0.77%)            max   1.47ms (+8.76%)            med   1.15ms (+0.67%)            avg   1.18ms (+1.30%)            stddev    65us (+42.44%)
Req runs:  383  NonInitiatorOpen (Full   , EncryptionOn):      min   1.13ms (-1.88%)            max   1.59ms (+5.26%)            med   1.20ms (-5.96%)            avg   1.22ms (-4.99%)            stddev    63us (-6.72%)

Req runs:  188  InitiatorOpen (Full   , EncryptionOff):        min   2.46ms (+0.23%)            max   2.96ms (-61.12%)           med   2.68ms (+1.41%)            avg   2.69ms (+0.43%)            stddev   100us (-73.21%)
Req runs:  158  InitiatorOpen (Full   , EncryptionOn):         min   2.97ms (+0.78%)            max   3.91ms (+2.52%)            med   3.22ms (+0.74%)            avg   3.23ms (+1.30%)            stddev   146us (+8.60%)

Req runs: 1000  AddTable (Full   , EncryptionOff):             min    720us (+28.93%)           max 109.12ms (-3.47%)            med   5.13ms (-0.08%)            avg   4.92ms (+1.89%)            stddev  3.54ms (-27.56%)
Req runs:  630  AddTable (Full   , EncryptionOn):              min    768us (+3.56%)            max 116.25ms (+3.77%)            med   5.50ms (-7.62%)            avg   4.86ms (-15.24%)           stddev  4.88ms (+14.27%)

Req runs: 1000  AddTable (MemOnly, EncryptionOff):             min     29us (+0.00%)            max    268us (-99.99%)           med     35us (-0.71%)            avg     37us (-99.04%)           stddev    11us (-99.99%)

Req runs:    7  IterateTableByIndexNoPrimaryKey (MemOnly, EncryptionOff):     min  65.11ms (-0.16%)            max  65.34ms (-0.82%)            med  65.22ms (-0.29%)            avg  65.21ms (-0.33%)            stddev    84us (-63.39%)

Req runs:    8  IterateTableByIndexIntPrimaryKey (MemOnly, EncryptionOff):     min  59.25ms (+0.11%)            max  59.66ms (+0.11%)            med  59.33ms (+0.15%)            avg  59.37ms (+0.13%)            stddev   137us (-0.52%)

Req runs:    8  IterateTableByIndexStringPrimaryKey (MemOnly, EncryptionOff):     min  60.17ms (-0.26%)            max  60.56ms (-0.35%)            med  60.19ms (-0.25%)            avg  60.24ms (-0.29%)            stddev   130us (-19.28%)

Req runs:  638  IterateTableByIterator (MemOnly, EncryptionOff):                  min    778us (+0.02%)            max    834us (-2.45%)            med    782us (-0.01%)            avg    784us (-0.05%)            stddev     7us (-17.71%)

Req runs:  417  IterateTableByIteratorIndex (MemOnly, EncryptionOff):             min   1.19ms (-0.04%)            max   1.24ms (-1.74%)            med   1.20ms (-0.06%)            avg   1.20ms (-0.07%)            stddev     6us (-15.31%)

Req runs:    5  Sort (MemOnly, EncryptionOff):                                    min 128.45ms (-0.04%)            max 128.90ms (-0.39%)            med 128.55ms (-0.54%)            avg 128.61ms (-0.32%)            stddev   192us (-54.88%)

Req runs:    9  SortInt (MemOnly, EncryptionOff):                                 min  50.55ms (-0.19%)            max  50.75ms (-0.40%)            med  50.67ms (-0.31%)            avg  50.67ms (-0.25%)            stddev    64us (-33.66%)

Req runs:    5  SortIntList (MemOnly, EncryptionOff):                             min 182.59ms (+0.07%)            max 183.52ms (+0.03%)            med 182.83ms (-0.13%)            avg 182.89ms (-0.07%)            stddev   377us (-3.61%)

Req runs:   16  SortIntDictionary (MemOnly, EncryptionOff):                       min  30.45ms (+0.15%)            max  30.71ms (+0.19%)            med  30.54ms (+0.16%)            avg  30.55ms (+0.11%)            stddev    67us (-16.65%)

Req runs:   62  UnorderedTableViewClear (MemOnly, EncryptionOff):                 min   7.91ms (+0.27%)            max   8.28ms (+2.69%)            med   7.94ms (+0.17%)            avg   7.96ms (+0.31%)            stddev    64us (+136.35%)

Req runs:   35  UnorderedTableViewClearIndexed (MemOnly, EncryptionOff):          min  14.18ms (-0.09%)            max  14.71ms (+1.15%)            med  14.23ms (+0.01%)            avg  14.27ms (+0.16%)            stddev   112us (+73.52%)

Req runs:  138  GetString (MemOnly, EncryptionOff):                               min   3.59ms (+0.01%)            max   3.74ms (+0.06%)            med   3.60ms (-0.01%)            avg   3.61ms (+0.04%)            stddev    20us (+30.34%)

Req runs:   47  SetString (MemOnly, EncryptionOff):                               min  10.41ms (+0.43%)            max  10.71ms (-2.91%)            med  10.45ms (-0.07%)            avg  10.46ms (-0.19%)            stddev    48us (-56.48%)

Req runs:   13  GetLinkList (MemOnly, EncryptionOff):                             min  35.25ms (-0.21%)            max  36.48ms (+0.45%)            med  35.59ms (+0.36%)            avg  35.65ms (+0.24%)            stddev   313us (+16.48%)

Req runs:  342  Insert (MemOnly, EncryptionOff):                                  min   1.43ms (-0.45%)            max   6.83ms (-25.89%)           med   1.44ms (-0.29%)            avg   1.46ms (-0.95%)            stddev   313us (-30.85%)

Req runs:   10  CreateIndex (Full   , EncryptionOff):                           * min  46.79ms (+0.76%)            max  47.17ms (+1.02%)          * med  46.89ms (+0.79%)          * avg  46.91ms (+0.79%)            stddev   109us (+28.72%)
Req runs:    9  CreateIndex (Full   , EncryptionOn):                              min  48.70ms (+0.11%)            max  49.01ms (+0.08%)            med  48.78ms (-0.03%)            avg  48.81ms (+0.01%)            stddev   100us (+0.02%)

Req runs:   10  CreateIndex (MemOnly, EncryptionOff):                             min  46.41ms (-0.37%)            max  46.99ms (-0.06%)            med  46.53ms (-0.27%)            avg  46.56ms (-0.28%)            stddev   165us (+29.59%)

Req runs:  138  GetLongString (MemOnly, EncryptionOff):                           min   3.60ms (+0.15%)            max   3.71ms (-1.55%)            med   3.61ms (+0.09%)            avg   3.61ms (+0.03%)            stddev    12us (-36.45%)

Req runs:   23  SetLongString (MemOnly, EncryptionOff):                           min  20.89ms (+0.06%)            max  21.08ms (-1.33%)            med  20.95ms (-0.10%)            avg  20.96ms (-0.33%)            stddev    44us (-67.34%)

Req runs: 1000  FindAllStringFewDupes (MemOnly, EncryptionOff):                   min      0us (+0.00%)            max      7us (+826.32%)          med      0us (+10.00%)           avg      0us (+6.31%)            stddev     0us (+377.85%)

Req runs: 1000  FindAllStringManyDupes (MemOnly, EncryptionOff):                  min     47us (-4.23%)            max     60us (-13.24%)           med     47us (-4.22%)            avg     47us (-4.12%)            stddev     1us (-10.98%)

Req runs: 1000  FindFirstStringFewDupes (MemOnly, EncryptionOff):                 min     81us (+1.46%)            max    101us (+4.23%)            med     81us (+1.35%)            avg     81us (+1.34%)            stddev     1us (+17.03%)

Req runs: 1000  FindFirstStringManyDupes (MemOnly, EncryptionOff):                min     15us (+0.84%)            max     30us (+28.86%)           med     15us (+0.55%)            avg     15us (+0.83%)            stddev     1us (+69.58%)

Req runs:   72  CountStringManyDupesNonIndexed (MemOnly, EncryptionOff):          min   6.88ms (+0.04%)            max   6.99ms (-1.94%)            med   6.89ms (+0.04%)            avg   6.90ms (-0.07%)            stddev    15us (-59.42%)

Req runs: 1000  CountStringManyDupesIndexed (MemOnly, EncryptionOff):             min     15us (-73.79%)           max     29us (-59.75%)           med     15us (-73.67%)           avg     15us (-73.62%)           stddev     1us (-18.26%)

Req runs:  670  Query (MemOnly, EncryptionOff):                                   min    740us (-0.42%)            max    786us (+1.59%)            med    744us (-0.26%)            avg    744us (-0.34%)            stddev     4us (+4.66%)

Req runs:   85  QueryNot (MemOnly, EncryptionOff):                                min   5.81ms (-0.10%)            max   5.97ms (+0.89%)            med   5.83ms (-0.10%)            avg   5.83ms (-0.03%)            stddev    27us (+79.43%)

Req runs: 1000  QueryLongString (MemOnly, EncryptionOff):                         min    119us (+2.37%)            max    142us (+3.67%)          * med    121us (+3.62%)          * avg    121us (+3.47%)            stddev     2us (-2.27%)

Req runs:    5  QueryInsensitiveString (MemOnly, EncryptionOff):                  min    1.04s (-0.52%)            max    1.04s (-0.88%)            med    1.04s (-0.71%)            avg    1.04s (-0.72%)            stddev   721us (-65.21%)

Req runs:  181  QueryInsensitiveStringIndexed (MemOnly, EncryptionOff):           min   1.08ms (-1.22%)            max  47.61ms (+2.73%)            med   2.21ms (-0.39%)            avg   2.93ms (+0.62%)            stddev  5.81ms (+2.91%)

Req runs:  149  QueryChainedOrStrings (MemOnly, EncryptionOff):                   min   3.33ms (-0.24%)            max   3.45ms (-8.50%)            med   3.34ms (-0.45%)            avg   3.34ms (-1.40%)            stddev    12us (-84.12%)

Req runs:  410  QueryChainedOrStringsIndexed (MemOnly, EncryptionOff):            min   1.21ms (-1.08%)            max   1.27ms (-3.57%)            med   1.22ms (-1.15%)            avg   1.22ms (-1.12%)            stddev     8us (-14.86%)

Req runs:   43  QueryNotChainedOrStrings (MemOnly, EncryptionOff):                min  11.21ms (-1.74%)            max  11.60ms (-1.61%)            med  11.28ms (-1.47%)            avg  11.36ms (-1.04%)            stddev   138us (+43.36%)

Req runs:   44  QueryNotChainedOrStringsIndexed (MemOnly, EncryptionOff):         min  11.30ms (+0.11%)            max  11.48ms (-2.42%)            med  11.34ms (-0.68%)            avg  11.35ms (-0.67%)            stddev    39us (-57.44%)

Req runs:  577  QueryChainedOrInts (MemOnly, EncryptionOff):                    * min    861us (+13.64%)           max    902us (+12.13%)         * med    865us (+13.73%)         * avg    866us (+13.68%)           stddev     5us (+6.11%)

Req runs:   26  QueryChainedOrIntsIndexed (MemOnly, EncryptionOff):               min  19.06ms (-9.78%)            max  19.24ms (-9.47%)            med  19.13ms (-9.83%)            avg  19.14ms (-9.76%)            stddev    56us (+69.45%)

Req runs:    5  QueryIntEquality (MemOnly, EncryptionOff):                        min  98.36ms (-0.04%)            max  98.82ms (+0.18%)            med  98.44ms (-0.03%)            avg  98.50ms (+0.00%)            stddev   184us (+99.13%)

Req runs:  838  QueryIntEqualityIndexed (MemOnly, EncryptionOff):                 min    588us (-4.14%)            max    674us (+2.01%)            med    594us (-3.55%)            avg    595us (-3.62%)            stddev     7us (-2.82%)

Req runs: 1000  QueryIntsVsDoubleColumns (MemOnly, EncryptionOff):                min      0us (+0.00%)            max      1us (-0.00%)            med      0us (+0.00%)            avg      0us (-2.46%)            stddev     0us (-0.87%)

Req runs: 1000  QueryStringOverLinks (MemOnly, EncryptionOff):                    min    200us (+0.44%)            max    245us (+10.03%)           med    201us (+0.48%)            avg    202us (+0.59%)            stddev     3us (+38.73%)

Req runs:   23  SubqueryStrings (MemOnly, EncryptionOff):                         min  21.60ms (+0.05%)            max  21.87ms (+0.11%)            med  21.62ms (-0.01%)            avg  21.64ms (+0.01%)            stddev    57us (+14.05%)

Req runs:   60  QueryEqual<mixed><NonNullable><Indexed> (MemOnly, EncryptionOff):     min   8.18ms (-4.88%)            max   8.30ms (-6.08%)            med   8.21ms (-4.96%)            avg   8.21ms (-5.00%)            stddev    20us (-37.97%)

Req runs:    5  QueryEqual<mixed><NonNullable><NonIndexed> (MemOnly, EncryptionOff):     min 162.78ms (-0.38%)            max 163.15ms (-0.38%)            med 163.09ms (-0.24%)            avg 163.03ms (-0.30%)            stddev   149us (+1.20%)

Req runs: 1000  QueryEqual<uuid><NonNullable><Indexed> (MemOnly, EncryptionOff):       * min     47us (+4.89%)            max     60us (+5.37%)          * med     48us (+5.45%)          * avg     49us (+5.60%)            stddev     1us (+39.05%)

Req runs:   40  QueryEqual<uuid><NonNullable><NonIndexed> (MemOnly, EncryptionOff):      min  12.26ms (-2.31%)            max  12.38ms (-2.50%)            med  12.27ms (-2.39%)            avg  12.28ms (-2.38%)            stddev    19us (-18.74%)

Req runs:   28  QueryEqual<objectId><NonNullable><Indexed> (MemOnly, EncryptionOff):     min  17.67ms (-9.65%)            max  18.08ms (-13.82%)           med  17.70ms (-9.71%)            avg  17.72ms (-10.59%)           stddev    75us (-82.97%)

Req runs:   13  QueryEqual<objectId><NonNullable><NonIndexed> (MemOnly, EncryptionOff):     min  36.98ms (-6.20%)            max  37.52ms (-6.46%)            med  37.11ms (-5.96%)            avg  37.18ms (-5.98%)            stddev   175us (-16.77%)

Req runs: 1000  QueryEqual<timestamp><NonNullable><Indexed> (MemOnly, EncryptionOff):       min     52us (-99.17%)           max     67us (-98.97%)           med     53us (-99.15%)           avg     53us (-99.15%)           stddev     2us (-95.85%)

Req runs:   80  QueryEqual<timestamp><NonNullable><NonIndexed> (MemOnly, EncryptionOff):     min   6.21ms (-0.15%)            max   6.38ms (-0.51%)            med   6.23ms (-0.26%)            avg   6.23ms (-0.22%)            stddev    24us (-9.71%)

Req runs:    5  QueryEqual<bool><NonNullable><Indexed> (MemOnly, EncryptionOff):             min 145.70ms (-24.77%)           max 146.82ms (-24.54%)           med 145.88ms (-24.99%)           avg 146.03ms (-24.82%)           stddev   454us (+9.46%)

Req runs:    5  QueryEqual<bool><NonNullable><NonIndexed> (MemOnly, EncryptionOff):          min 193.11ms (-1.06%)            max 194.93ms (-3.23%)            med 193.31ms (-2.01%)            avg 193.76ms (-1.88%)            stddev   791us (-68.38%)

Req runs:   60  QueryInsensitiveEqual<mixed><NonNullable><Indexed> (MemOnly, EncryptionOff):        min   8.19ms (-95.09%)           max   8.51ms (-94.92%)           med   8.21ms (-95.09%)           avg   8.23ms (-95.08%)           stddev    61us (-79.67%)

Req runs:    5  QueryInsensitiveEqual<mixed><NonNullable><NonIndexed> (MemOnly, EncryptionOff):     min 161.25ms (-3.10%)            max 162.05ms (-2.92%)            med 161.38ms (-3.19%)            avg 161.50ms (-3.11%)            stddev   317us (+75.51%)

Req runs:    7  QueryInsensitiveEqual<string><NonNullable><NonIndexed> (MemOnly, EncryptionOff):     min  65.85ms (+0.03%)            max  66.38ms (+0.03%)            med  66.20ms (+0.40%)            avg  66.15ms (+0.23%)            stddev   204us (+18.53%)

Req runs: 1000  QueryInsensitiveEqual<string><NonNullable><Indexed> (MemOnly, EncryptionOff):        min     65us (-0.32%)            max     71us (-14.21%)           med     66us (-0.62%)            avg     66us (-0.74%)            stddev     1us (-42.18%)

Req runs:   21  QueryTimestampGreaterOverLinks (MemOnly, EncryptionOff):                             min  23.11ms (+0.44%)            max  23.96ms (+2.26%)            med  23.44ms (+1.61%)            avg  23.41ms (+1.32%)            stddev   213us (+101.01%)

Req runs:  260  QueryTimestampGreater (MemOnly, EncryptionOff):                                      min   1.91ms (-0.08%)            max   2.02ms (-3.73%)            med   1.92ms (-0.26%)            avg   1.92ms (-0.41%)            stddev    12us (-42.95%)

Req runs:  259  QueryTimestampGreaterEqual (MemOnly, EncryptionOff):                                 min   1.91ms (-0.01%)            max   2.01ms (+0.68%)            med   1.92ms (+0.04%)            avg   1.92ms (+0.03%)            stddev    10us (+21.73%)

Req runs:  259  QueryTimestampLess (MemOnly, EncryptionOff):                                         min   1.91ms (-0.52%)            max      2ms (-1.04%)            med   1.92ms (-0.20%)            avg   1.92ms (-0.27%)            stddev    12us (-2.66%)

Req runs:  260  QueryTimestampLessEqual (MemOnly, EncryptionOff):                                    min   1.91ms (-0.07%)            max   1.98ms (-1.77%)            med   1.92ms (-0.21%)            avg   1.92ms (-0.28%)            stddev     9us (-32.26%)

Req runs: 1000  QueryTimestampEqual (MemOnly, EncryptionOff):                                        min    127us (-1.42%)            max    149us (+7.40%)            med    128us (-1.35%)            avg    128us (-1.21%)            stddev     2us (+39.58%)

Req runs:   77  QueryTimestampNotEqual (MemOnly, EncryptionOff):                                     min   6.43ms (-0.06%)            max   6.64ms (+0.88%)            med   6.47ms (+0.13%)            avg   6.48ms (+0.23%)            stddev    42us (+49.70%)

Req runs:  130  QueryTimestampNotNull (MemOnly, EncryptionOff):                                    * min   3.82ms (+0.78%)            max   3.93ms (-2.21%)          * med   3.83ms (+0.71%)            avg   3.83ms (+0.50%)            stddev    11us (-69.99%)

Req runs:  478  QueryTimestampEqualNull (MemOnly, EncryptionOff):                                    min   1.04ms (+0.46%)            max   1.10ms (-3.20%)            med   1.04ms (+0.39%)            avg   1.05ms (+0.43%)            stddev     7us (-8.43%)

Req runs:   17  QueryListOfPrimitiveIntsSize (MemOnly, EncryptionOff):                               min  28.82ms (+0.23%)            max  29.01ms (-0.31%)            med  28.86ms (+0.11%)            avg  28.86ms (+0.04%)            stddev    41us (-57.94%)

Req runs:   36  IntUIDsRandomOrderSeqAccess (MemOnly, EncryptionOff):                                min  13.69ms (-0.44%)            max  14.02ms (+0.93%)            med  13.74ms (-0.45%)            avg  13.75ms (-0.38%)            stddev    66us (+121.31%)

Req runs:   36  IntUIDsRandomOrderRandomAccess (MemOnly, EncryptionOff):                             min  13.74ms (+0.06%)            max  13.90ms (-1.41%)            med  13.79ms (+0.21%)            avg  13.79ms (+0.14%)            stddev    41us (-32.15%)

Req runs:   90  IntUIDsRandomOrderRandomDelete (MemOnly, EncryptionOff):                           * min   5.46ms (+19.74%)           max   5.80ms (+17.67%)         * med   5.51ms (+19.62%)         * avg   5.52ms (+19.30%)           stddev    48us (-22.42%)

Req runs:  124  IntUIDsRandomOrderRandomCreate (MemOnly, EncryptionOff):                             min   3.98ms (-1.27%)            max   4.24ms (-17.12%)           med   4.01ms (-2.43%)            avg   4.02ms (-3.23%)            stddev    33us (-75.16%)

Req runs:  306  TransactionDuplicate (MemOnly, EncryptionOff):                                       min   1.63ms (-0.55%)            max   1.71ms (-5.80%)            med   1.63ms (-0.52%)            avg   1.63ms (-1.52%)            stddev     6us (-83.01%)

☑️ ToDos

  • 📝 Changelog update
  • 🚦 Tests (or not relevant)
  • C-API, if public C++ API changed.

ironage added 5 commits March 10, 2023 17:40
This enables StringIndex::find_all_no_copy in more places
which should speed up equals queries with many results for
indexed Int, ObjectId, UUID and Mixed types. This also fixed
a bug on indexed Mixed equality queries that would return case
insensitive results.
optimize EqualIns for mixed properties
changelog
@ironage ironage self-assigned this Mar 11, 2023
@cla-bot cla-bot bot added the cla: yes label Mar 11, 2023
Copy link
Member

@nicola-cab nicola-cab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just minor stuff... great work!

// 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();
Copy link
Member

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?

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();
Copy link
Member

Choose a reason for hiding this comment

The 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 for(const auto& key : keys)

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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 keys was previously a std::vector<ObjKey> and now it is a IndexEvaluator* which doesn't have built in iterator support (I suppose I could add iterator support if you really wanted to keep the loop the same). The change in type allows us to dynamically fetch the keys directly from BPTree one at a time as needed. The previous way was to always evaluate all the results and return them in the vector. But that is entirely unused when we only have one query condition and are doing a count of results. So the optimization here is to fetch the matching object keys as needed because sometimes we don't need them at all.

Copy link
Member

Choose a reason for hiding this comment

The 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.

@@ -2384,7 +2384,7 @@ TEST(Query_TwoColumnsNumeric)
size_t num_expected_matches = num_rows;
if ((lhs_type == type_Mixed) != (rhs_type == type_Mixed)) {
// Only one prop is mixed
num_expected_matches = 6;
num_expected_matches = 5;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This magic numbers change should have some explanation probably

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a comment to this test. The number of matches changes in this test because I also changed TestValueGenerator::convert_for_test<Mixed> to return an ObjectId instead of an int in one case.

@@ -22,6 +22,8 @@
#include <realm.hpp>
#include <realm/column_type_traits.hpp>

#include <list>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No so sure this include is needed here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is actually required, there is a use of std::list later on. It was working accidentally in the other tests because another include brings in std::list, but the benchmarks don't do this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, but it does not show up in the diff, it tricked me.

@@ -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)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe, since you are repeating this over several ifs, you could have added this check inside Mixed::types_are_comparable

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that both of the values could be numerics, so Mixed::types_are_comparable would actually return true, but trying to convert to a string will fail. We don't want to change Mixed::types_are_comparable because that is used in other places for other non-string values.

CHANGELOG.md Outdated Show resolved Hide resolved
CHANGELOG.md Outdated Show resolved Hide resolved
CHANGELOG.md Outdated Show resolved Hide resolved
CHANGELOG.md Outdated
* <How do the end-user experience this issue? what was the impact?> ([#????](https://github.com/realm/realm-core/issues/????), since v?.?.?)
* None.
* Fixed a crash when querying a mixed property with a string operator (contains/like/beginswith/endswith) or with case insensitivity. ([6376](https://github.com/realm/realm-core/issues/6376) since introduction of Mixed)
* Querying for equality of a string on a mixed property was returning case insensitive matches. ([6376](https://github.com/realm/realm-core/issues/6376) since introduction of Mixed)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you elaborate which matches wasn't working? Was it not taking casing into consideration? So it would return true for "A"="a" where it was supposed to return false?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that is correct. I have added an example to clarify.

@nicola-cab nicola-cab self-requested a review March 14, 2023 10:19
Copy link
Member

@nicola-cab nicola-cab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Contributor

@jedelbo jedelbo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@ironage
Copy link
Contributor Author

ironage commented Mar 23, 2023

one sync test failure on evergreen is unrelated to these changes

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 21, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants