Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-57533

Avoid creating intermediate objects for covered projections with OR stage

    • Type: Icon: Improvement Improvement
    • Resolution: Duplicate
    • Priority: Icon: Major - P3 Major - P3
    • None
    • Affects Version/s: None
    • Component/s: None
    • Labels:
      None
    • Query Execution

      Consider an example:

      > db.test.insert({})
      > db.test.createIndex({a: 1, b: 1})
      > db.test.createIndex({b: 1, a: 1})
      > db.test.find({$or: [{a: 1}, {b: 1}]}, {a: 1, b: 1, _id: 0}).explain()
      

      The following plan will be selected for this covered query:

      PROJECT -> OR -> [IXSCAN a,b ;  IXSCAN b,a]
      

      The following SBE tree will be generated:

      [4] traverse s18 s17 s15 [s16] {} {}
      from
          [3] unique [s16]
          [3] union [s15, s16] [
              [s8, s5] [1] project [s8 = newObj ("a", s3, "b", s4)]
              [1] nlj [] [s6, s7]
                  left
                      [1] project [s6 = KS(2B020A0104), s7 = KS(2B02F0FE04)]
                      [1] limit 1
                      [1] coscan
                  right
                      [1] ixseek s6 s7 none s5 none [s3 = 0, s4 = 1] @"..." @"a_1_b_1" true
      
              ,
              [s14, s11] [2] project [s14 = newObj ("b", s9, "a", s10)]
              [2] nlj [] [s12, s13]
                  left
                      [2] project [s12 = KS(2B020A0104), s13 = KS(2B02F0FE04)]
                      [2] limit 1
                      [2] coscan
                  right
                      [2] ixseek s12 s13 none s11 none [s9 = 0, s10 = 1] @"9aaa2d3b-aafe-4c1f-a845-e6d06f97b9b2" @"b_1_a_1" true
      
      
         ]
      in
          [4] cfilter {isObject (s15)}
          [4] mkbson s17 s15 [a, b] keep [] true false
          [4] limit 1
          [4] coscan
      

      Each of the index scans is represented by the branch in the union stage. Each branch rehydrates index keys and creates intermediate objects. These objects are then traversed and passed into mkbson stage.

      Instead, we can directly use the slots provided by union branches to build the resulting object once, without traverse, in the same way as SERVER-54745. Currently, we cannot do this because SBE stage builder assumes that for covered plans only one index exists. We have a fixed-size bitset to request index keys from child stages and fixed-size vector to retrieve them.

      We should reconsider how we handle index keys for covered plans to fix this.

            Assignee:
            andrew.paroski@mongodb.com Drew Paroski
            Reporter:
            nikita.lapkov@mongodb.com Nikita Lapkov (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated:
              Resolved: