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

SBE plan cache entries can be incorrectly reused after a refineCollectionShardKey operation

    • Fully Compatible
    • ALL
    • v6.0
    • QE 2022-04-04, QE 2022-04-18, QE 2022-05-02
    • 146

      An SBE plan cache entry which was created prior to the shard key being refined can be re-used after the shard key refinement completes. The result is that a query can use an incorrect plan. The plan will be doing orphan filtering incorrectly, leading to incorrect results.

      The reason that SBE plans cannot be reused across shard key refinement boundaries relates to how orphan filtering is implemented in SBE. Here is an example SBE plan doing orphan filtering for a shard key of {a: 1}:

      [2] filter {shardFilter (s5, s13)}
      [2] project [s13 = if (! exists (s11), Nothing, s12)]
      [2] mkbson s12 [a = s11] true false
      [2] project [s11 = let [l1.0 = fillEmpty (getField (s6, \"a\"), null)] if (isArray (l1.0), Nothing, l1.0)]
      [1] filter {fillEmpty (s10, false)}
      [1] traverse s10 s9 s8 [s6, s7] {s10 || s9} {s10}
      from
          [1] project [s8 = getField (s6, \"tid\")]
          [1] scan s6 s7 none none none none [] @\"92b69019-c6fd-4bb6-a3b7-511e0b8517b2\" true false
      in
          [1] project [s9 = fillEmpty (s8 == 3, false)]
          [1] limit 1
          [1] coscan
      

      This plan boils down to a collection scan followed by shard filtering. Importantly, the plan explicitly encodes the steps necessary to extract the shard key and insert it into slot s13:

      [2] project [s13 = if (! exists (s11), Nothing, s12)]
      [2] mkbson s12 [a = s11] true false
      [2] project [s11 = let [l1.0 = fillEmpty (getField (s6, \"a\"), null)] if (isArray (l1.0), Nothing, l1.0)]
      

      Let's say that the shard key is refined to something like {a: 1, b: 1}. This plan is no longer valid, because it only extracts values for the "a" field of the shard key, and the "b" part will be completely ignored. The result is that incorrect shard keys are passed to the "shardFilter()" builtin function, and orphan filtering is done incorrectly.

            Assignee:
            denis.grebennicov@mongodb.com Denis Grebennicov
            Reporter:
            david.storch@mongodb.com David Storch
            Votes:
            0 Vote for this issue
            Watchers:
            7 Start watching this issue

              Created:
              Updated:
              Resolved: