2016-10-07 7 views
6

मेरे पास "लॉगट्रांसक्शन" नामक एक संग्रह है। मैं परिणाम प्राप्त करना चाहता हूं जैसा कि आप संलग्न छवि में देख सकते हैं।मोंगो डीबी एकत्रीकरण आउटपुट लंबे प्रतिक्रिया समय

output

logTransaction कई क्षेत्रों है, लेकिन इस छवि के लिए इस्तेमाल किया प्रकार हैं:

customer, environment, firstTime, lastTime, integrationIds[] (लेन-देन 1 से अधिक एकीकरण हो सकता है), transactionStatus (समाप्त होने पर, असीमित, FAILED)

मैं इस परिणाम के लिए AggregationOutput का उपयोग कर रहा हूं लेकिन इसमें 30 सेकंड से अधिक समय लग रहा है जो राशि से अधिक लंबा (मुझे लगता है) मेरे पास डेटा है। मुझे आश्चर्य है कि क्या मैं इसे पहले से ही संशोधित करके संशोधित कर सकता हूं या मैं इसे पूरी तरह से बदल सकता हूं। चीजों को और भी तेज बनाने के लिए मुझे किस प्रकार की अनुक्रमणिका का उपयोग करना चाहिए?

मैं MongoDB और Grails का उपयोग करता हूं। मेरे वर्तमान विधि इस प्रकार है:

def myCustomAggregation(integrations, timestamp_lt, timestamp_gt, cust, env) { 
    def currentRequest = RequestContextHolder.requestAttributes 

    def customer = cust ?: currentRequest?.session?.customer 
    def environment = env ?: currentRequest?.session?.environment 

    //$match 
    DBObject matchMap = new BasicDBObject('integrationIds', new BasicDBObject('$in', integrations.collectAll { it?.baselineId })) 
    matchMap.put("firstTimestamp", new BasicDBObject('$lte', timestamp_lt as Long).append('$gte', timestamp_gt as Long)) 
    matchMap.put("customer",customer) 
    matchMap.put("environment",environment) 
    DBObject match = new BasicDBObject('$match',matchMap); 

    //$group1 
    Map<String, Object> dbObjIdMap1 = new HashMap<String, Object>(); 
    dbObjIdMap1.put('integrationId', '$integrationIds'); 
    dbObjIdMap1.put('transactionStatus', '$transactionStatus'); 
    DBObject groupFields1 = new BasicDBObject("_id", new BasicDBObject(dbObjIdMap1)); 
    groupFields1.put('total', new BasicDBObject('$sum', 1)); 
    DBObject group1 = new BasicDBObject('$group', groupFields1); 

    //$group2 
    DBObject groupFields2 = new BasicDBObject("_id", '$_id.integrationId'); 
    groupFields2.put('total_finished', 
     new BasicDBObject('$sum', new BasicDBObject('$cond', [ 
      new BasicDBObject('$eq', ['$_id.transactionStatus', 'FINISHED']), '$total', 0 
     ])) 
    ); 
    groupFields2.put('total_unfinished', 
     new BasicDBObject('$sum', new BasicDBObject('$cond', [ 
      new BasicDBObject('$eq', ['$_id.transactionStatus', 'UNFINISHED']), '$total', 0 
     ])) 
    ); 
    groupFields2.put('total_failed', 
     new BasicDBObject('$sum', new BasicDBObject('$cond', [ 
      new BasicDBObject('$eq', ['$_id.transactionStatus', 'FAILED']), '$total', 0 
     ])) 
    ); 
    DBObject group2 = new BasicDBObject('$group', groupFields2); 
    // This taking more than 30 seconds. Its too much for the amount of data I have in Database. 
    AggregationOutput output = db.logTransaction.aggregate(match,group1,group2) 
    return output.results() 
} 

संपादित करें:

मैं एक यौगिक सूचकांक बनाया के रूप में HoefMeistert सुझाव:

db.logTransaction.explain().aggregate([ 
    { $match: {integrationIds: {$in: ["INT010","INT011","INT012A","INT200"]}, "firstTimestamp": { "$lte" : 1476107324000 , "$gte" : 1470002400000}, "customer": "Awsome_Company", "environment": "PROD"}}, 
    { $group: { _id: {"integrationId": '$integrationIds', "transactionStatus": '$transactionStatus'}, total: {$sum: 1}}}, 
    { $group: { _id: "$_id.integrationId", "total_finished": {$sum: {$cond: [{$eq: ["$_id.transactionStatus", "FINISHED"]}, "$total", 0]}}, "total_unfinished": {$sum: {$cond: [{$eq: ["$_id.transactionStatus", "UNFINISHED"]}, "$total", 0]}}, "total_failed": {$sum: {$cond: [{$eq: ["$_id.transactionStatus", "FAILED"]}, "$total", 0]}}}} 
]); 
:

db.logTransaction.createIndex({integrationIds: 1, firstTimestamp: -1, customer: 1, environment: 1}) 

लेकिन जब मैं इस कुल पर समझाने का उपयोग

मुझे अभी भी यह विजेताप्लान हर बार मिलता है:

"winningPlan" : { 
       "stage" : "CACHED_PLAN", 
       "inputStage" : { 
        "stage" : "FETCH", 
        "filter" : { 
         "$and" : [ 
           { 
            "environment" : { 
              "$eq" : "PROD" 
            } 
           }, 
           { 
            "integrationIds" : { 
             "$in" : [ 
              "INT010", 
              "INT011", 
              "INT012A", 
              "INT200" 
             ] 
            } 
           } 
         ] 
        }, 
        "inputStage" : { 
          "stage" : "IXSCAN", 
          "keyPattern" : { 
           "tenant" : 1, 
           "firstTimestamp" : -1 
          }, 
          "indexName" : "customer_1_firstTimestamp_-1", 
          "isMultiKey" : false, 
          "isUnique" : false, 
          "isSparse" : false, 
          "isPartial" : false, 
          "indexVersion" : 1, 
          "direction" : "forward", 
          "indexBounds" : { 
           "customer" : [ 
            "[\"Awsome_Company\", \"Awsome_Company\"]" 
           ], 
           "firstTimestamp" : [ 
            "[1476107324000.0, 1470002400000.0]" 
           ] 
          } 
        } 
       } 
     }, 

विकास env में संग्रह के लिए वर्तमान अनुक्रमणिका। और गति अच्छी है से पहले की तुलना में, लेकिन जब समयावधि 1 सप्ताह से अधिक है, मैं अभी भी sockettimeoutexception (3 मिनट) मिलती है:

"customer_1_firstTimestamp_-1" : 56393728, 
"firstTimestamp_-1_customer_1" : 144617472, 
"integrationIds_1_firstTimestamp_-1" : 76644352, 
"integrationId_1_firstTimestamp_-1" : 56107008, 
"transactionId_1_firstTimestamp_-1" : 151429120, 
"firstTimestamp_1" : 56102912, 
"transactionId_1" : 109445120, 
"integrationIds_1_firstTimestamp_-1_customer_1_environment_1" : 247790976 
+0

कोई भी मुझे यहाँ से बाहर मदद कर सकते हैं? – Yonetmen

+1

क्या आपने ग्रेओडीबी से पूछताछ करने के लिए Grails के निर्माण के समान कच्ची क्वेरी बनाई है? पता लगाने का पहला कदम यह है कि यह एक Grails मुद्दा या un-अनुकूलित क्वेरी है। क्या आपने क्वेरी को तेज करने के लिए मोंगो डीबी में कुछ कॉलम अनुक्रमणित करने में देखा है? – elixir

उत्तर

3

क्या अनुक्रमित आप वर्तमान में है? जब मैं अपने एकत्रीकरण को देखो सुनिश्चित करें कि आप क्षेत्र आप पर एक अनुक्रमित कर पर मिलान कर रहे हैं:

  • integrationIds
  • firstTimestamp
  • ग्राहक
  • पर्यावरण

पहले के बाद (मैच) चरण सूचकांक अब प्रासंगिक नहीं हैं। जैसा कि elixir द्वारा पूछा गया है, खोल/संपादक में प्रदर्शन कैसा है? क्या यह भी धीमा है। यदि ऐसा है तो "धीमी" चरण को खोजने का प्रयास करें।

अद्यतन: आप भी मदद कर सकता Aggregation Pipeline optimizer ;-) एक भी $and मैच

{ $match: {integrationIds: {$in: ["INT010","INT011","INT012A","INT200"]}, "firstTimestamp": { "$lte" : 1476107324000 , "$gte" : 1470002400000}, "customer": "Awsome_Company", "environment": "PROD"}} 
को

को मैच पुनर्लेखन:

{ $match: { $and : [ 
     {integrationIds: {$in: ["INT010","INT011","INT012A","INT200"]}}, 
     {"firstTimestamp": { "$lte" : 1476107324000 , "$gte" : 1470002400000}}, 
     {"customer": "Awsome_Company"}, 
     {"environment": "PROD"}] 
    } 
+0

हाय होफ़मेस्टर, क्या आपका मतलब है कि प्रत्येक के लिए प्रत्येक फ़ील्ड या सिर्फ एक कंपाउंड इंडेक्स के लिए एक इंडेक्स होना चाहिए? – oxyt

+0

ठीक है कि वास्तव में आप "अन्य" अनुक्रमण आवश्यकताओं पर निर्भर करता है। जब आप केवल इन फ़ील्ड से पूछते हैं तो आप एक कंपाउंड इंडेक्स बना सकते हैं। आपको अपने कंपाउंड इंडेक्स के बारे में सोचना होगा। {integrationIds: 1, firstTimestamp: 1, ग्राहक: 1, पर्यावरण: 1} के घटक सूचकांक के साथ पूर्व। क्वेरी का उपयोग करते समय इंडेक्स का उपयोग किया जाता है: एकीकरण आईडी, एकीकरण आईडी और फर्स्ट टिमस्टैम्प, एकीकरण आईडी और फर्स्ट टिमस्टैम्प और ग्राहक, एकीकरण आईडी और फर्स्ट टिमस्टैम्प और ग्राहक && वातावरण। जब आप "ग्राहक" के लिए पूछताछ करते हैं तो इंडेक्स का उपयोग नहीं किया जाएगा। Https://docs.mongodb.com/v3.2/core/index-compound/ – HoefMeistert

+0

यहां इंडेक्स चौराहे के बारे में कुछ और जानकारी यहां दी गई है: https: // docs। mongodb.com/v3.2/core/index-intersection/#index-intersection-compound-indexes – HoefMeistert

संबंधित मुद्दे