2015-06-03 11 views
8

sto cercando di riprodurre il primo esempio di istruzione di indice di intersezione (http://docs.mongodb.org/manual/core/index-intersection/), ma di fronte a un problema: mongo non utilizza entrambi gli indiciPerché MongoDB non usa Index Intersection?

miei passi:

  1. Scarica mongo (3.0.3) e installarlo
  2. Run mongod: mongod.exe --dbpath d: \ dati (cartella è vuota)
  3. Run mongo: mongo.exe
  4. aggiungere indici:

    db.orders.ensureIndex({ qty: 1 }) 
    db.orders.ensureIndex({ item: 1 }) 
    db.orders.getIndexes() 
    [{ 
         "v" : 1, 
         "key" : { 
           "_id" : 1 
         }, 
         "name" : "_id_", 
         "ns" : "test.orders" 
    }, 
    { 
         "v" : 1, 
         "key" : { 
           "qty" : 1 
         }, 
         "name" : "qty_1", 
         "ns" : "test.orders" 
    }, 
    { 
         "v" : 1, 
         "key" : { 
           "item" : 1 
         }, 
         "name" : "item_1", 
         "ns" : "test.orders" 
    }] 
    
  5. Controllare interrogazione spiega:

    db.orders.find({ item: "abc123", qty: { $gt: 15 } }).explain() 
    { 
        "queryPlanner" : { 
          "plannerVersion" : 1, 
          "namespace" : "test.orders", 
          "indexFilterSet" : false, 
          "parsedQuery" : { 
            "$and" : [ 
              { 
                "item" : { 
                  "$eq" : "abc123" 
                } 
              }, 
              { 
                "qty" : { 
                  "$gt" : 15 
                } 
              } 
            ] 
          }, 
          "winningPlan" : { 
            "stage" : "KEEP_MUTATIONS", 
            "inputStage" : { 
              "stage" : "FETCH", 
              "filter" : { 
                "qty" : { 
                  "$gt" : 15 
                } 
              }, 
              "inputStage" : { 
                "stage" : "IXSCAN", 
                "keyPattern" : { 
                  "item" : 1 
                }, 
                "indexName" : "item_1", 
                "isMultiKey" : false, 
                "direction" : "forward", 
                "indexBounds" : { 
                  "item" : [ 
                    "[\"abc123\", \"abc123\"]" 
                  ] 
                } 
              } 
            } 
          }, 
          "rejectedPlans" : [ 
            { 
              "stage" : "KEEP_MUTATIONS", 
              "inputStage" : { 
                "stage" : "FETCH", 
                "filter" : { 
                  "item" : { 
                    "$eq" : "abc123" 
                  } 
                }, 
                "inputStage" : { 
                  "stage" : "IXSCAN", 
                  "keyPattern" : { 
                    "qty" : 1 
                  }, 
                  "indexName" : "qty_1", 
                  "isMultiKey" : false, 
                  "direction" : "forward", 
                  "indexBounds" : { 
                    "qty" : [ 
                      "(15.0, 1.#INF]" 
                    ] 
                  } 
                } 
              } 
            } 
          ] 
        }, 
        "serverInfo" : { 
          "host" : "localhost", 
          "port" : 27017, 
          "version" : "3.0.3", 
          "gitVersion" : "b40106b36eecd1b4407eb1ad1af6bc60593c6105" 
        }, 
        "ok" : 1 
    } 
    

Come si può vedere winningPlan contiene solo item_1 indice. C'è respinto Ples che contiene qty_1 indice. Ma non ci sono piani che contengano l'intersezione dell'indice. So che ci sono molte condizioni per selezionare un indice specifico. Ma nel mio caso, mongo non lo pianifica nemmeno!

Qualcuno potrebbe aiutarmi?

+0

FWIW, funziona allo stesso modo con MongoDB 3.0.2 –

+0

Quanti documenti ci sono nel database? Cosa dice 'explain (true)' say? Quanto dura la query? Qual è la distribuzione dei campi di dati, se presente? – mnemosyn

risposta

3

Ci sono alcuni dettagli sulla selezione dell'indice nel SERVER-3071 JIRA issue ma non posso dire se tutto è ancora rilevante per 3.0. In ogni caso:

MongoDB 3.0.2 sembra non prendere in considerazione l'interazione indice per gamma query. Ma sarà per intervalli di punti:

> db.orders.find({ item: {$eq : "abc123"}, qty: { $eq: 15 } }).explain() 
... 

     { 
      "stage" : "FETCH", 
      "inputStage" : { 
       "stage" : "KEEP_MUTATIONS", 
       "inputStage" : { 
        "stage" : "AND_SORTED", 
        "inputStages" : [ 
         { 
          "stage" : "IXSCAN", 
          "keyPattern" : { 
           "qty" : 1 
          }, 
          "indexName" : "qty_1", 
          "isMultiKey" : false, 
          "direction" : "forward", 
          "indexBounds" : { 
           "qty" : [ 
            "[15.0, 15.0]" 
           ] 
          } 
         }, 
         { 
          "stage" : "IXSCAN", 
          "keyPattern" : { 
           "item" : 1 
          }, 
          "indexName" : "item_1", 
          "isMultiKey" : false, 
          "direction" : "forward", 
          "indexBounds" : { 
           "item" : [ 
            "[\"abc123\", \"abc123\"]" 
           ] 
          } 
         } 
        ] 
       } 
+1

quindi, in sostanza, l'intersezione dell'indice sembra non succedere mai nelle query della vita reale? Non funziona con $ in query con più di 1 elemento, secondo i miei test :( –

+0

Osservando lo stesso comportamento con v3.4.10 – mils

+0

Ulteriori osservazioni: 'hint()' non funziona con un prefisso di un indice composito (solo indice composito completo); l'intersezione dell'indice sembra non funzionare con i prefissi dell'indice composito (solo indici singoli) – mils

1

Stiamo ospitando un sito multi-tenant. Quindi non v'è una raccolta mongo tenendo alcune informazioni su tutti i clienti, per esempio,

{customerId: 22, category: "category", region: "region", balance: 23434... } 

Dopo abbiamo imparato a conoscere Indice Intersection, abbiamo cercato di creare più indici dei campi singoli per supportare le query con diversi criteri di query con campi variabili, come ad esempio come

{ customerId: 22, category: "1" } 
{ customerId: 22, region: "somewhere" } 
{ customerId: 22, balance: {$gt:0} } 
{ customerId: 22, region: {$in: ["R1", "R2"]},balance: {$gt:0} } 
.... 

Ma semplicemente scoperto alcuna intersezione successo imparando da "db.collection.explain". Dato che i campi sono limitati, alla fine abbiamo optato per una soluzione per costruire un indice composto comprensivo di tutti i campi.

{customerId: 1, category: 1, region: 1, balance:1...} 

E poi si è scoperto che sotto di tutte le query utilizzano il "grande" indice composto, per quanto "customerId" è nella query.

{ customerId: 22, category: "1" } 
{ customerId: 22, region: "somewhere" } 
{ customerId: 22, balance: {$gt:0} } 
{ customerId: 22, region: {$in: ["R1", "R2"]},balance: {$gt:0} } 
.... 
+0

L'aggiunta di un indice composto di grandi dimensioni non è di grande aiuto. Dei quattro esempi di query forniti, gli ultimi tre utilizzano solo il prefisso 'customerId' dell'indice composto, mentre il primo utilizza il prefisso' customerId' più 'category' dell'indice composto. Se stavi cercando di indicizzare per queste quattro query, un indice composto solo sui primi due campi sarebbe migliore. Basta dire così nessuno ha l'idea che un massiccio indice composto possa accelerare il filtraggio di query arbitrarie su qualsiasi campo incluso in esso :) – DanielSmedegaardBuus