[SERVER-7568] Aggregation framework favors non-blocking sorts Created: 06/Nov/12 Updated: 08/Feb/23 Resolved: 22/Oct/19 |
|
| Status: | Closed |
| Project: | Core Server |
| Component/s: | Aggregation Framework |
| Affects Version/s: | None |
| Fix Version/s: | 4.3.1 |
| Type: | Improvement | Priority: | Major - P3 |
| Reporter: | David Schneider | Assignee: | David Storch |
| Resolution: | Done | Votes: | 25 |
| Labels: | nh-240, performance, usability | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Issue Links: |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Backwards Compatibility: | Fully Compatible | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Sprint: | Query 2017-05-08, Query 2017-05-29, Query 2019-10-07, Query 2019-10-21, Query 2019-11-04 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Participants: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Case: | (copied to CRM) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Linked BF Score: | 15 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Description |
| Comments |
| Comment by Graeme Downes [ 12/Nov/19 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Can you confirm by implementing the $project workaround we will lose the benefits of indexed sorts? Â As per the docs:Â
https://docs.mongodb.com/manual/reference/operator/aggregation/sort/#sort-operator-and-performance Thanks | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by David Storch [ 22/Oct/19 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
This issue is fixed as of commit 8d048a3bb2. Users should no longer need to work around the problem with hints or index filters, or by rewriting queries. The fix will first become available in development release 4.3.1. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Githook User [ 22/Oct/19 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Author: {'name': 'David Storch', 'username': 'dstorch', 'email': 'david.storch@mongodb.com'}Message: This change results in the multi-planning mechanism | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Tomasz Fidos [ 03/Jun/19 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Thanks | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Asya Kamsky [ 01/Jun/19 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
The workaround is to use a hint to specify the index that will satisfy the $match. This has not been fixed - when it is, the status and resolution fields will be updated accordingly. Asya | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Tomasz Fidos [ 27/May/19 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Vote up and: 1) Is this workaround: putting $project in-between $match and $sort, now an official solution? Why is it working? 2) Is this fixed? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Asya Kamsky [ 18/Oct/17 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Note that as of 3.6 aggregation can take a "hint" option to specify desired index to use. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Charlie Swanson [ 20/Nov/15 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I've updated the description to reflect the underlying problem a little more succinctly. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Daniel Pasette (Inactive) [ 22/Jun/15 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
This is a non-trivial issue to solve. The agg pipeline optimizer asks the query planner for a plan which does not include a blocking sort, when that is in fact what the user desires in this case. The workaround of inserting a $project before the $sort mentioned by andrey.hohutkin@gmail.com does work for now. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by yosi oren [ 27/Jan/15 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
vote up | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Andrey Hohutkin [ 27/Jan/15 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
It happens not only in aggregation. It causes slowness on every query operation like find, findAndModify. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Thomas Rueckstiess [ 07/Apr/14 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
The test ist not quite fair, because the query is always on num, but the sort is either on _id or on num. So we have:
And the output of the test script is something like:
If we switch the query to be on _id instead (and make sure that some documents match, by setting the _id value to i in the insert as well):
We get the exact opposite result, with the sort on num being slow in the aggregation:
This is because of the choice of indexes. For the original test script, the aggregation framework chooses the _id index for the slow case, and has to scan through the entire collection instead of quickly finding the 10 matches and sorting them in memory with the num index (that's what the find() does). That is the actual question here: Why does the aggregation framework choose the much less efficient index for the combined query/sort? To show this, I ran both find and agg on 2.6 and made use of the explain parameter in the aggregation framework. Here is the modified test script:
And here is the explain output from find and aggregate:
redbeard0531, is this expected behavior or should the aggregation framework also choose the fast index on num here? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by David Schneider [ 07/Nov/12 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I added the itcount() call to the cursor. But still get the same result. Anyway the find query was just to compare. For me to ~400ms execution time for aggregation with sort by _id comparing to nearly nothing in the other cases raises concern.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Aaron Staple [ 06/Nov/12 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
When you put something like this in a script it does not actually touch the server, it just builds a cursor: db.demo.find(query).sort(sortId); You would need to do something like this to ensure the query runs: db.demo.find(query).sort(sortId).itcount(); |