>  Q&A  >  본문

关于mongodb查询子文档优化的问题(LOL对战详情查询)

图为mongodb中一条document结构,记录的是LOL的一场比赛对局详情
participants中有10个玩家,前5个teamID为100,后5个teamId为200.比赛的结果哪个队伍取胜是记录在teams那个子文档中的。
我现在的想要查询championId为64(盲僧), 157(亚索)这两个英雄在同一个队伍时的胜利场次,(规定游戏版本号>6.7),查询语句我是这样写的:

db.getCollection('matches').count({
    $and: [
        { "matchVersion": {$gte:"6.7"} }
      , {
        $or: 
        [
            {
                $and: 
                [
                    { "participants": {$elemMatch: {"teamId": 100, "championId": 64 } } }
                ,   { "participants": {$elemMatch: {"teamId": 100, "championId": 157 } } }
                ,   { "teams":{ $elemMatch: {"teamId": 100, "winner":true} } }
                ]
            },
            {
                $and:
                [
                    { "participants": {$elemMatch: {"teamId": 200, "championId": 64 } } }
                ,   { "participants": {$elemMatch: {"teamId": 200, "championId": 157 } } }
                ,   { "teams":{ $elemMatch: {"teamId": 200, "winner":true} } }
                ]
            }
        ]
        }
    ]
}
)

数据规模为14万,可是执行这样一个查询要花费3秒。已经对对应的查询建立了索引。对查询explain的结果如下

不过好像有些索引也没有用到,比如teams.teamId, teams.winner的复合索引,matchVersion的索引

请问这个查询该如何优化呢?我觉得这个数据规模花费这么久时间应该是我的使用姿势不对吧?

过去多啦不再A梦过去多啦不再A梦2699일 전677

모든 응답(1)나는 대답할 것이다

  • 淡淡烟草味

    淡淡烟草味2017-05-02 09:20:33

    귀하의 실행계획 지수를 사용하고 있으나 효율성이 높지 않음을 알 수 있으나, 핵심정보가 많이 접혀져 자세한 내용을 볼 수 없습니다. 다음번에는 원본 JSON을 직접 보내는 것이 이해하기 쉽기 때문에 가장 좋습니다. 마찬가지로 데이터 샘플이 있는 경우 JSON으로 보내는 것이 가장 좋습니다. 그러면 다른 사람들이 문제를 해결할 때 테스트 데이터의 복사본을 가질 수 있어 훨씬 편리합니다.
    $and이것은 대부분의 경우 나타날 필요가 없습니다. 객체의 두 평행 요소는 and 사이의 관계입니다. 이렇게 하면 쿼리 구조가 단순화되고 다른 사람이 보기가 더 쉬워집니다. 따라서 귀하의 쿼리는 다음과 같이 단순화되었습니다.

    으아악

    마지막이자 가장 중요한 인덱스 문제는 자신에게 더 유용한 인덱스는 participants.teamId+participants.championId+teams.teamId+teams.winner+matchVersion의 공동 인덱스가 되어야 한다는 추측입니다. 조건의 필터링 가능성에 따라 필터링해야 합니다. 더 나은 조건을 먼저 설정하세요. 쓰기 효율성을 높이기 위해 일부 조건을 제거할 수도 있습니다. 그러나 이는 데이터 분포에 따라 다릅니다.
    인덱스가 사용되지 않는 이유는 무엇입니까? mongodb 2.6 이상에서는 교차 인덱싱을 지원하고 동일한 쿼리를 충족하기 위해 여러 인덱스를 사용할 수 있지만 현재 실행 계획 평가 시스템에서는 교차 인덱스를 트리거하기가 어렵습니다. 따라서 쿼리를 만족시키기 위해 인덱스를 사용해 보십시오.

    회신하다
    0
  • 취소회신하다