Ich habe eine Sammlung namens "logTransaction". Ich möchte die Ergebnisse erhalten, wie Sie im angehängten Bild sehen können.MongoDB AggregationOutput längere Reaktionszeit
logTransaction viele Felder hat aber die für dieses Bild verwendeten sind:
customer
, environment
, firstTime
, lastTime
, integrationIds[]
(eine Transaktion mehr als 1 Integration haben kann), transactionStatus
(FERTIG, UNFINISHED, FAILED)
Ich verwende AggregationOutput
für dieses Ergebnis, aber es dauert mehr als 30 Sekunden, die viel länger ist (denke ich) als die Menge von Daten, die ich habe. Ich frage mich nur, ob ich das verbessern kann, indem ich das ändere, was ich bereits habe oder sollte ich es total ändern. Welche Art der Indexierung sollte ich verwenden, um die Dinge noch schneller zu machen?
Ich verwende MongoDB
und Grails
. Meine aktuelle Methode sieht wie folgt aus:
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()
}
Edit:
ich eine Verbindung Index erstellt als HoefMeistert vorgeschlagen:
db.logTransaction.createIndex({integrationIds: 1, firstTimestamp: -1, customer: 1, environment: 1})
Aber wenn ich auf dieses Aggregat erklären:
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]}}}}
]);
Ich bekomme diesen wintingPlan immer noch jedes Mal:
"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]"
]
}
}
}
},
Aktuelle Indizes für die Sammlung in Entwicklung env. und die Geschwindigkeit ist gut im Vergleich zu vor, aber wenn Zeitspanne größer als 1 Woche, habe ich noch bekommen sockettimeoutexception (3 Minuten):
"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
Niemand kann helfen hier draußen? – Yonetmen
Haben Sie eine Abfrage erstellt, die der von Grails ähnelt, um MongoDb abzufragen? Der erste Schritt, um herauszufinden, ist, ob es sich um ein Grails-Problem oder eine unoptimierte Abfrage handelt. Haben Sie in MongoDb einige Spalten indexiert, um die Abfrage zu beschleunigen? – elixir