2015-05-19 9 views
6

Ho un server Mongo in esecuzione su un VPS con 16 GB di memoria (sebbene probabilmente con IO lento che utilizza dischi magnetici).

Ho una collezione di circa 35 milioni di dischi, che non rientrano nella memoria principale (db.stats() segnala un size di 35 GB e un storageSize di 14 GB), ma il 1,7 GB riportato per totalIndexSize dovrebbe stare comodamente lì.

C'è un campo particolare bg Sto interrogando su quale può essere presente con il valore true o assente del tutto (per favore non discutere se questa è la migliore rappresentazione dei dati - Continuo a pensare che Mongo si comporta stranamente). Questo campo è indicizzato con un indice non sparse con una dimensione segnalata di 146 MB.

Sto utilizzando il motore di archiviazione WiredTiger con una dimensione cache predefinita (quindi dovrebbe essere di circa 8 GB).

Sto cercando di contare il numero di record mancanti nel campo bg.

Contando true valori è abbastanza veloci (pochi secondi):

> db.entities.find({bg: true}).count() 
8300677 

Tuttavia la query per i valori mancanti è estremamente lento (circa 5 minuti):

> db.entities.find({bg: null}).count() 
27497706 

Ai miei occhi, explain() sembra ok:

> db.entities.find({bg: null}).explain() 
{ 
    "queryPlanner" : { 
     "plannerVersion" : 1, 
     "namespace" : "testdb.entities", 
     "indexFilterSet" : false, 
     "parsedQuery" : { 
      "bg" : { 
       "$eq" : null 
      } 
     }, 
     "winningPlan" : { 
      "stage" : "FETCH", 
      "filter" : { 
       "bg" : { 
        "$eq" : null 
       } 
      }, 
      "inputStage" : { 
       "stage" : "IXSCAN", 
       "keyPattern" : { 
        "bg" : 1 
       }, 
       "indexName" : "bg_1", 
       "isMultiKey" : false, 
       "direction" : "forward", 
       "indexBounds" : { 
        "bg" : [ 
         "[null, null]" 
        ] 
       } 
      } 
     }, 
     "rejectedPlans" : [ ] 
    }, 
    "serverInfo" : { 
     "host" : "mongo01", 
     "port" : 27017, 
     "version" : "3.0.3", 
     "gitVersion" : "b40106b36eecd1b4407eb1ad1af6bc60593c6105" 
    }, 
    "ok" : 1 
} 

Tuttavia la query rimane ostinatamente lento, anche dopo ripetute chiamate. Altre query conteggio per diversi valori sono veloci:

> db.entities.find({bg: "foo"}).count() 
0 
> db.entities.find({}).count() 
35798383 

Trovo questo tipo di strano, dal momento che la mia comprensione è che i campi in indici non sparse mancanti vengono semplicemente memorizzati come null, quindi la query conte con null dovrebbero essere simili per contare un valore reale (o forse fino a tre volte per tre volte più valori positivi, se deve contare più voci di indice o qualcosa del genere). Effettivamente, this answer riporta vasti miglioramenti di velocità rispetto a query simili che coinvolgono i valori null e .count(). L'unico punto di differenziazione che posso pensare è WiredTiger.

qualcuno può spiegare perché è la mia domanda a contare i valori nulli in modo lento o che cosa posso fare per risolvere il problema (oltre a fare la sottrazione evidente delle true conteggi del totale, che avrebbe funzionato bene, ma non avrebbe soddisfare la mia curiosità)?

+0

Ho anche trovato questo. Il tell tell me è il filtro nella fase FETCH. Troverete quando chiedete qualcosa che manca. – msaspence

risposta

5

Questo comportamento è previsto, vedere: https://jira.mongodb.org/browse/SERVER-18653. Sembra una strana chiamata a me, ma ci sei, sono sicuro che ci sono programmatori che sanno più cose su MongoDB di quanto ne pensi io.

Sarà necessario utilizzare un valore diverso per indicare null. Immagino dipenda da cosa usi il campo. Nel mio caso è un riferimento estraneo, quindi comincerò a usare false per significare null. Se lo si utilizza per memorizzare un valore booleano, potrebbe essere necessario utilizzare "null", -1, 0, ecc.

+0

L'utilizzo del framework di aggregazione con un contatore potrebbe attenuare questo problema?Ad esempio, '{" $ group ": {counter: {" $ sum ":" $ _id "}}}' – mils

Problemi correlati