2015-07-26 17 views
6

Sto usando mongo v3.0.1 su una macchina Ubuntu. E ho una collezione di 300 milioni di file. Ho creato due indici in base alla mia preferenza di ricerca.

Quando sto cercando di eseguire l'aggregazione con spiega, sta prendendo l'indice inefficiente, ed è per questo che ci vogliono 20-25 secondi più tempo. C'è un modo per inserire $hint, in modo che la mia query di aggregazione utilizzi l'indice appropriato.

$match è il mio primo pipeline. Ho due indici:

  1. "Host_-1_SiteType_-1"

  2. "VisitTime_-1_AccountId_-1_Host_-1_SiteType_-1_Extension_-1_LifeTime_-1"

e la mia $match gasdotti è come:

{ "$match" : { 
    "AccountId": accID, 
    "VisitTime": { "$lte" : today, "$gte" : last365Days }, 
    "$or": [ 
     { "$and": [ 
      { "Extension":{ "$in": ["chrome_0","firefox_0"] }}, 
      { "LifeTime": 0 } 
     ]}, 
     { "LifeTime": { "$gt": 1000 }} 
    ], 
    "Host": { "$ne": "localhost" }, 
    "SiteType" : { "$exists": true }, 
} 

e utilizza il primo indice, anziché il secondo indice. e il tempo impiegato dal primo indice in 50 secondi in cui, come usando solo il secondo indice, ci vogliono solo 18 secondi.

Ecco il mio uno del campione documento:

{ 
    "_id" : "2bc1143c-07e4-4c37-a020-a7485b2802a3", 
    "CreatedDate" : ISODate("2015-07-22T04:05:06.802+0000"), 
    "UpdatedDate" : ISODate("2015-07-22T05:28:26.469+0000"), 
    "AccountId" : accID, 
    "Url" : "http://www.test.com/test.html", 
    "Host" : "test.com", 
    "VisitTime" : ISODate("2014-08-12T18:08:25.813+0000"), 
    "LifeTime" : 789546.01, 
    "Status" : "closed", 
    "LocalTime" : ISODate("2014-08-12T18:08:25.813+0000"), 
    "DeviceId" : "123456789", 
    "Extension" : "firefox_0", 
    "SubSiteType" : "TestSubSite", 
    "SiteType" : "TestSite", 
    "Flag" : "1" 
} 

Ed ecco la mia aggregazione spiegazione:

{ 
    "stages" : [ 
     { 
      "$cursor" : { 
       "query" : { 
        "AccountId" : "accID", 
        "VisitTime" : { 
         "$lte" : "2015-07-25T18:30:00Z", 
         "$gte" : "2014-07-25T18:30:00Z" 
        }, 
        "Host" : { 
         "$ne" : "localhost" 
        }, 
        "SiteType" : { 
         "$exists" : true 
        }, 
        "$or" : [ 
         { 
          "$and" : [ 
           { 
            "Extension" : { 
             "$in" : [ 
              "chrome_0", 
              "firefox_0" 
             ] 
            } 
           }, 
           { 
            "LifeTime" : 0 
           } 
          ] 
         }, 
         { 
          "LifeTime" : { 
           "$gt" : 1000 
          } 
         } 
        ] 
       }, 
       "fields" : { 
        "Host" : 1, 
        "_id" : 0 
       }, 
       "queryPlanner" : { 
        "plannerVersion" : 1, 
        "namespace" : "Test", 
        "indexFilterSet" : false, 
        "parsedQuery" : { 
         "$and" : [ 
          { 
           "$or" : [ 
            { 
             "$and" : [ 
              { 
               "LifeTime" : { 
                "$eq" : 0 
               } 
              }, 
              { 
               "Extension" : { 
                "$in" : [ 
                 "chrome_0", 
                 "firefox_0" 
                ] 
               } 
              } 
             ] 
            }, 
            { 
             "LifeTime" : { 
              "$gt" : 1000 
             } 
            } 
           ] 
          }, 
          { 
           "$not" : { 
            "Host" : { 
             "$eq" : "localhost" 
            } 
           } 
          }, 
          { 
           "VisitTime" : { 
            "$lte" : "2015-07-25T18:30:00Z" 
           } 
          }, 
          { 
           "AccountId" : { 
            "$eq" : "accID" 
           } 
          }, 
          { 
           "VisitTime" :"2014-07-25T18:30:00Z" 

          }, 
          { 
           "SiteType" : { 
            "$exists" : true 
           } 
          } 
         ] 
        }, 
        "winningPlan" : { 
         "stage" : "FETCH", 
         "filter" : { 
          "$and" : [ 
           { 
            "SiteType" : { 
             "$exists" : true 
            } 
           }, 
           { 
            "$or" : [ 
             { 
              "$and" : [ 
               { 
                "LifeTime" : { 
                 "$eq" : 0 
                } 
               }, 
               { 
                "Extension" : { 
                 "$in" : [ 
                  "chrome_0", 
                  "firefox_0" 
                 ] 
                } 
               } 
              ] 
             }, 
             { 
              "LifeTime" : { 
               "$gt" : 1000 
              } 
             } 
            ] 
           }, 
           { 
            "VisitTime" : { 
             "$lte" : "2015-07-25T18:30:00Z" 
            } 
           }, 
           { 
            "AccountId" : { 
             "$eq" : "accID" 
            } 
           }, 
           { 
            "VisitTime" : { 
             "$gte" : "2014-07-25T18:30:00Z" 
            } 
           } 
          ] 
         }, 
         "inputStage" : { 
          "stage" : "IXSCAN", 
          "keyPattern" : { 
           "Host" : -1, 
           "SiteType" : -1 
          }, 
          "indexName" : "Host_-1_SiteType_-1", 
          "isMultiKey" : false, 
          "direction" : "forward", 
          "indexBounds" : { 
           "Host" : [ 
            "[MaxKey, \"localhost\")", 
            "(\"localhost\", MinKey]" 
           ], 
           "SiteType" : [ 
            "[MaxKey, MinKey]" 
           ] 
          } 
         } 
        }, 
        "rejectedPlans" : [ 
         { 
          "stage" : "FETCH", 
          "filter" : { 
           "$and" : [ 
            { 
             "SiteType" : { 
              "$exists" : true 
             } 
            }, 
            { 
             "$or" : [ 
              { 
               "$and" : [ 
                { 
                 "LifeTime" : { 
                  "$eq" : 0 
                 } 
                }, 
                { 
                 "Extension" : { 
                  "$in" : [ 
                   "chrome_0", 
                   "firefox_0" 
                  ] 
                 } 
                } 
               ] 
              }, 
              { 
               "LifeTime" : { 
                "$gt" : 1000 
               } 
              } 
             ] 
            } 
           ] 
          }, 
          "inputStage" : { 
           "stage" : "IXSCAN", 
           "keyPattern" : { 
            "VisitTime" : -1, 
            "AccountId" : -1, 
            "Host" : -1, 
            "SiteType" : -1, 
            "Extension" : -1, 
            "LifeTime" : -1 
           }, 
           "indexName" : "VisitTime_-1_AccountId_-1_Host_-1_SiteType_-1_Extension_-1_LifeTime_-1", 
           "isMultiKey" : false, 
           "direction" : "forward", 
           "indexBounds" : { 
            "VisitTime" : [ 
             "[new Date(1437849000000), new Date(1406313000000)]" 
            ], 
            "AccountId" : [ 
             "[\"accID\", \"accID\"]" 
            ], 
            "Host" : [ 
             "[MaxKey, \"localhost\")", 
             "(\"localhost\", MinKey]" 
            ], 
            "SiteType" : [ 
             "[MaxKey, MinKey]" 
            ], 
            "Extension" : [ 
             "[MaxKey, MinKey]" 
            ], 
            "LifeTime" : [ 
             "[MaxKey, MinKey]" 
            ] 
           } 
          } 
         } 
        ] 
       } 
      } 
     }, 
     { 
      "$group" : { 
       "_id" : "$Host", 
       "Count" : { 
        "$sum" : { 
         "$const" : 1 
        } 
       } 
      } 
     }, 
     { 
      "$sort" : { 
       "sortKey" : { 
        "Count" : -1 
       }, 
       "limit" : 5 
      } 
     }, 
     { 
      "$project" : { 
       "_id" : false, 
       "Host" : "$_id", 
       "TotalVisit" : "$Count" 
      } 
     } 
    ], 
    "ok" : 1 
} 
+0

No, non c'è un modo per specificare il suggerimento. '$ Match' è il tuo primo pipeline stage? c'è un indice appropriato che può essere scelto in base alle condizioni in quella dichiarazione? Non mostri la query che stai eseguendo qui o "l'indice sbagliato" che viene scelto o il "giusto" che pensi debba essere scelto. –

+0

Come osservazione molto breve, avrei avuto la frequenza di "AccountId" sarebbe notevolmente inferiore a "VisitTime", ma è il primo elemento in quell'indice composto. In effetti, stai selezionando quello che è probabilmente un campione molto ampio di "VisitTime". L'altro indice è quello scelto, corretto? Puoi includere anche l'output di spiegare? –

+0

Ciao @BlakesSeven, ho appena aggiornato la mia domanda con l'output di spiegazione e il documento di esempio. Per favore, date un'occhiata, dove sto sbagliando? –

risposta

4

definizione dell'indice può essere molto soggettiva, e non qualcosa che hai appena pigramente dire "index questa roba "e quindi spero per il meglio. In realtà richiede qualche riflessione sul processo di ricerca a cui si applica.

La tua richiesta qui sembra essere composta da questi elementi principali, che sono principalmente i valori "Account" e "Lifetime". Sicuramente ci sono altre cose come il "VisitTime", ma prendendo la vecchia libreria e l'analogia con l'indice delle carte allora pensate al processo.

Quindi, quando si cammina attraverso la porta della biblioteca si sono presentati con i sistemi di indice due carte:

  1. Contiene i libri della libary dalla data in cui sono stati scritti, che consente di ottenere una selezione delle carte indicando i libri in base alla data

  2. Contiene i nomi degli autori dei libri e delle posizioni nella libreria.

Ora considerando che sai di voler cercare libri di un autore scritto negli ultimi 10 anni, quale sistema di indicizzazione scegli? Quindi guardi attraverso le date di 10 anni e cerchi l'autore contenuto all'interno? O preferisci innanzitutto consultare l'autore e quindi restringere a quali libri sono stati scritti negli ultimi 10 anni?

Le probabilità sono che negli ultimi 10 anni ci siano molti più contenuti che solo quelli di un singolo autore. Quindi 2 è la scelta migliore perché una volta che hai tutti i libri per quell'autore, quindi passare attraverso le carte per trovare quelli entro 10 anni dovrebbe essere un compito molto più piccolo.

Ecco perché l'ordine delle chiavi in ​​un indice è importante per i modelli di query che si stanno utilizzando. Chiaramente "Account" dovrebbe essere la cosa che restringe di più la selezione e poi altri dettagli per aiutare a restringere ulteriormente quella verso il basso.

Tutto ciò che mette qualcosa come "VisitTime" prima di questo, significa che devi setacciare tutte le cose che probabilmente non vuoi in quel periodo prima di arrivare effettivamente alle cose di cui hai bisogno.

L'ordine è importante e devi sempre tenerlo in considerazione con il design dell'indice.

+0

Hi @ blakes-seven Ho provato diversi ordini di campi indice, e sembra che "Host_-1_SiteType_-1' sia l'indice più potente. Non importa ciò che creo come indice, ma prende sempre quell'indice. –

+0

@AnkitSarkar Come ho già detto, l'output delle spiegazioni è diverso dal vostro parere. L'indice scelto ** è ** "Host_-1_SiteType_-1", e quindi quello che ti dà le scarse prestazioni. Il riepilogo principale della risposta qui è "Account" è ciò di cui hai bisogno per restringere i risultati a una velocità di query accettabile. –

+0

Come suggerito, ho eliminato tutti gli indici e li ho ricreati. Ora i miei indici sono: 'AccountId: -1, SiteType: -1, Host: -1, VisitTime: -1',' Host_-1_SiteType_-1', 'AccountId: -1, SiteType: -1, Estensione: -1 , Host: -1, Durata: -1, VisitTime: -1'. e nessun 3 sta lavorando :) Grazie @ blake-seven! –

0

Come @ blake-seven menzionato in precedenza, per creare un indice efficace su un'enorme raccolta, tenere sempre a mente quali campi vengono principalmente utilizzati per restringere la condizione di corrispondenza. Quindi ci penso due volte prima di ricrearli. Come suggerito, ho messo "AccountId" come prima preferenza e dopo "SiteType" (perché "Ricerca categoria" è più efficace) dopo "Estensione" (puoi pensare che questo campo sia "Sottocategoria") e "Host" sta usando per restringere ulteriormente il numero di documenti restituiti. questo è tutto!

Quindi, AccountId : -1,SiteType : -1,Extension : -1, Host : -1, LifeTime : -1, VisitTime : -1 è il mio indice finale.

Problemi correlati