[SERVER-77899] remove repeat contain index from the relevant candidate indexes, this can avoid some useless calculations Created: 08/Jun/23 Updated: 24/Jun/23 Resolved: 22/Jun/23 |
|
| Status: | Closed |
| Project: | Core Server |
| Component/s: | None |
| Affects Version/s: | None |
| Fix Version/s: | None |
| Type: | Improvement | Priority: | Major - P3 |
| Reporter: | y yz | Assignee: | Backlog - Query Optimization |
| Resolution: | Won't Do | Votes: | 0 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Assigned Teams: |
Query Optimization
|
| Participants: |
| Description |
|
remove repeat contain index from the relevant candidate indexes, this can avoid some useless calculations. {a:1, b:1} is better than {a:1},because both cases are satisfied for db.collection.find({a:xx}) |
| Comments |
| Comment by y yz [ 24/Jun/23 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
(y)got it, thanks. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Ben Shteinfeld [ 23/Jun/23 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
> why it's not safe to choose {a:1, b:1}over {a:1}It is not a query correctness/safety issue as much as it is a performance one. Consider a situation where the field 'b' is multikey (the 'b' field contains arrays). This means that any given document, the {a:1, b:1}index has duplicate entries for 'a' for each element in the 'b' array. If you have a query which only references 'a', then using the {a:1}index is preferable to the {a:1, b:1}index because we avoid examining duplicate key entries. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by y yz [ 23/Jun/23 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
hi, Steve Tarzia. Thank you for your reply, but I have some different ideas. in sharding cluster: many times, although the user not create duplicate indexes explicitly, but sh.shardCollection() may make a duplicate implicitly. For example, the following scenario is very common in production environments:
the tradeDB.userTradeInfo storage user's history trade information, the shard key is "userid" that can ensure the data of the same user resides in the same shard; the main query sql is "db.userTradeInfo.find({userid:xxxx, time:{$gte:2022-xx-xx, $lte:2022-xx-xx}})", so the dba create index {userid:1, time:1}. for the query sql "db.userTradeInfo.find({userid:xxxx, time:{$gte:2022-xx-xx, $lte:2022-xx-xx}})", if not delete index {userid:1}, the two index {userid:1} and {userid:1, time:1} are the candidate index. befor the plan is cached,two indexes need to be scored; after the plan is cached, the all query shold use CachedPlanStage::pickBestPlan to determine whether replan is necessary.
if we delete the contain duplicate index(here is {userid:1}), Only one index plan({userid:1, time:1}) is available, this saves a lot of computing resources and improves performance at the same time 2. if query sql's candidate indexes contain {a:1} and {a:1, b:1}, the {a:1, b:1}'s rank score must >= {a:1}'s rank score. Associative indexing principle(the leftmost rule),I think the {a:1, b:1}'s rank score must >= {a:1}'s rank score certainly. if the rank score of the two index is same,review the index query code, the first candidate index is selected as the best index by default. if we create index {a:1, b:1}, and then create index {a:1}, if the rank score of the two index is same, the {a:1, b:1} will be the best winning index, the test result is Consistent, as following:
I don't know why it's not safe to choose {a:1, b:1} over {a:1}, Can you give me an example,thanks。
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Steve Tarzia [ 22/Jun/23 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Hi 1147952115@qq.com , thank you for your contribution. We are not going to accept this change at this time. We don't expect customers to define both {a:1} and {a:1, b:1} indexes so we don't want to add code to our system to address this case. Also, it's not clear that {a:1} and {a:1, b:1} execution performance will be the same, so it's not safe to choose {a:1, b:1} over {a:1}. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by y yz [ 16/Jun/23 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
In addition,This feature helps to avoid index skew。 for example: Let's say we have two indexes({a:1}, {a:1, b:1}), the sql is db.collection.find({a:xxx,b:{$tge:xxx, $lte:xxx}})。if The first few times, we shoud get total count that {a=xxx},In this case, the score is the same for both indexes,it may choice {a:1} as the winning index. As time goes on,the {a:1} index plan‘s(getPlanCache.list) works may be larger, if the sql db.collection.find({a:xxx,b:{$tge:xxx, $lte:xxx}}), b filed arrow down, CachedPlanStage::pickBestPlan function can not trigger replan。 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by y yz [ 09/Jun/23 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Hi eric.sedor@mongodb.com thanks | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Eric Sedor [ 08/Jun/23 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Hi 1147952115@qq.com; As in | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by y yz [ 08/Jun/23 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
the code address: https://github.com/mongodb/mongo/pull/1552
this is an improved feature, but Ican not choose "Improvement" button.
Performance will be affected when there are many repeat contain indexes. In addition,{a:1, b:1} is better than {a:1},because both cases are satisfied for db.collection.find({a:xx}) and db.collection.find({a:xx,b:xx}),it can also reduce the number of replan. |