2016-06-01 11 views
1

Mongodb 3.2, installiert auf Centos 6, mit viel RAM und Festplatte. Ich habe eine Sammlung mit 10K Dokumente der folgenden Struktur:Mongodb Aggregation - Sortierung macht die Abfrage sehr langsam

{ 
    "id":5752034, 
    "score":7.6, 
    "name":"ASUS X551 15.6-inch Laptop", 
    "categoryId":"803", 
    "positiveAspects":[{ 
         "id":30030525, 
         "name":"price", 
         "score":9.8, 
         "frequency":139, 
         "rank":100098 
        }, 
        { 
         "id":30028399, 
         "name":"use", 
         "score":9.9, 
         "frequency":99, 
         "rank":100099 
        } 
        . 
        . 
       ] 
} 

Für jedes Dokument, das verschachtelte Array positiveAspects hat einige hundert Elemente.

Die collectoin hat die follwing Indizes:

{ "v" : 1, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "proddb.product_trees" } 
{ "v" : 1, "key" : { "positiveAspects.id" : 1.0, "positiveAspects.score" : 1.0 }, "name" : "positiveAspects.id_1_positiveAspects.score_1", "ns" : "proddb.product_trees" } 
{ "v" : 1, "key" : { "categoryId" : 1.0, "score" : 1.0 }, "name" : "categoryId_1_score_1", "ns" : "proddb.product_trees" } 
{ "v" : 1, "key" : { "rank" : -1.0 }, "name" : "rank_-1", "ns" : "proddb.product_trees" } 
{ "v" : 1, "key" : { "positiveAspects.rank" : -1.0 }, "name" : "positiveAspects.rank_-1", "ns" : "proddb.product_trees" } 

Ich möchte folgende Aggregation laufen, dauert es etwa 40 Sekunden:

{ 
    aggregate:"product_trees", 
    pipeline:[ 
    { 
    $match:{ 
     categoryId:"803", 
     score:{ 
      $gte:8.0 
     } 
    } 
    }, 
    { 
    $unwind:"$positiveAspects" 
    }, 
    { 
    $match:{ 
     positiveAspects.id:30030525, 
     positiveAspects.score:{ 
      $gte:9.0 
     } 
    } 
    }, 
    { 
    $sort:{ 
     positiveAspects.rank:-1 
    } 
    }, 
    { 
    $project:{ 
     _id:0, 
     score:1, 
     id:1, 
     name:1, 
     positiveAspects:1 
    } 
    }, 
    { 
    $limit:10 
    } 
] 
} 

Mit der folgenden Erklärung:

2016-06-01T16:10:49.140-0500 D QUERY [conn47] Beginning planning... 
============================= 
Options = NO_BLOCKING_SORT INDEX_INTERSECTION 
Canonical query: 
ns=proddb.product_treesTree: $and 
    categoryId == "803" 
    score $gte 8.0 
Sort: {} 
Proj: {} 
============================= 
2016-06-01T16:10:49.140-0500 D QUERY [conn47] Index 0 is kp: { _id: 1 } unique name: '_id_' io: { v: 1, key: { _id: 1 }, name: "_id_", ns: "proddb.product_trees" } 
2016-06-01T16:10:49.140-0500 D QUERY [conn47] Index 1 is kp: { positiveAspects.id: 1.0, positiveAspects.score: 1.0 } multikey name: 'positiveAspects.id_1_positiveAspects.score_1' io: { v: 1, key: { positiveAspects.id: 1.0, positiveAspects.score: 1.0 }, name: "positiveAspects.id_1_positiveAspects.score_1", ns: "proddb.product_trees" } 
2016-06-01T16:10:49.140-0500 D QUERY [conn47] Index 2 is kp: { categoryId: 1.0, score: 1.0 } name: 'categoryId_1_score_1' io: { v: 1, key: { categoryId: 1.0, score: 1.0 }, name: "categoryId_1_score_1", ns: "proddb.product_trees" } 
2016-06-01T16:10:49.140-0500 D QUERY [conn47] Index 3 is kp: { rank: -1.0 } name: 'rank_-1' io: { v: 1, key: { rank: -1.0 }, name: "rank_-1", ns: "proddb.product_trees" } 
2016-06-01T16:10:49.140-0500 D QUERY [conn47] Index 4 is kp: { positiveAspects.rank: -1.0 } multikey name: 'positiveAspects.rank_-1' io: { v: 1, key: { positiveAspects.rank: -1.0 }, name: "positiveAspects.rank_-1", ns: "proddb.product_trees" } 
2016-06-01T16:10:49.140-0500 D QUERY [conn47] Predicate over field 'score' 
2016-06-01T16:10:49.140-0500 D QUERY [conn47] Predicate over field 'categoryId' 
2016-06-01T16:10:49.140-0500 D QUERY [conn47] Relevant index 0 is kp: { categoryId: 1.0, score: 1.0 } name: 'categoryId_1_score_1' io: { v: 1, key: { categoryId: 1.0, score: 1.0 }, name: "categoryId_1_score_1", ns: "proddb.product_trees" } 
2016-06-01T16:10:49.140-0500 D QUERY [conn47] Rated tree: 
$and 
    categoryId == "803" || First: 0 notFirst: full path: categoryId 
    score $gte 8.0 || First: notFirst: 0 full path: score 
2016-06-01T16:10:49.140-0500 D QUERY [conn47] Tagging memoID 1 
2016-06-01T16:10:49.140-0500 D QUERY [conn47] Enumerator: memo just before moving: 
2016-06-01T16:10:49.140-0500 D QUERY [conn47] About to build solntree from tagged tree: 
$and 
    categoryId == "803" || Selected Index #0 pos 0 
    score $gte 8.0 || Selected Index #0 pos 1 
2016-06-01T16:10:49.140-0500 D QUERY [conn47] Planner: adding solution: 
FETCH 
---fetched = 1 
---sortedByDiskLoc = 0 
---getSort = [{ categoryId: 1 }, { categoryId: 1, score: 1 }, { score: 1 }, ] 
---Child: 
------IXSCAN 
---------keyPattern = { categoryId: 1.0, score: 1.0 } 
---------direction = 1 
---------bounds = field #0['categoryId']: ["803", "803"], field #1['score']: [8.0, inf.0] 
---------fetched = 0 
---------sortedByDiskLoc = 0 
---------getSort = [{ categoryId: 1 }, { categoryId: 1, score: 1 }, { score: 1 }, ] 
2016-06-01T16:10:49.140-0500 D QUERY [conn47] Planner: outputted 1 indexed solutions. 
2016-06-01T16:10:49.140-0500 D QUERY [conn47] Only one plan is available; it will be run but will not be cached. query: { categoryId: "803", score: { $gte: 8.0 } } sort: {} projection: {}, planSummary: IXSCAN { categoryId: 1.0, score: 1.0 } 
2016-06-01T16:11:27.170-0500 I COMMAND [conn47] command proddb.product_trees command: aggregate { aggregate: "product_trees", pipeline: [ { $match: { categoryId: "803", score: { $gte: 8.0 } } }, { $unwind: "$positiveAspects" }, { $match: { positiveAspects.id: 30030525, positiveAspects.score: { $gte: 9.0 } } }, { $sort: { positiveAspects.rank: -1 } }, { $project: { _id: 0, score: 1, id: 1, name: 1, positiveAspects: 1 } }, { $limit: 10 } ], cursor: {} } keyUpdates:0 writeConflicts:0 numYields:226 reslen:7459 locks:{ Global: { acquireCount: { r: 906 } }, Database: { acquireCount: { r: 453 } }, Collection: { acquireCount: { r: 453 } } } protocol:op_query 38030ms 

Unter der $sort wird die Abfrage in 2 Sekunden ausgeführt.

Können Sie erklären, warum die $sort Ursache solcher Leistung schlagen, prüfen, gibt es Index, den es verwenden kann? Gibt es einen Index, den ich übersehen habe? Was kann getan werden, um das Problem zu beheben?

Danke!

MongoDB aggregarion - macht sortiert die Abfrage sehr langsam

+0

versuchen Sie, das $ -Projekt so umzuordnen, dass das '$ sort' direkt vom' $ limit' folgt, da es eine Optimierung gibt, die Sie verwenden können. https://docs.mongodb.com/manual/core/aggregation-pipeline-optimization/#sort-limit-coalescence – CodeMan

+0

Ich habe das versucht, aber es hat die Antwortzeit nicht beeinflusst. – Seffy

Antwort

2

Es ist, weil $sort nicht Index verwenden, wenn nicht in einem frühen Stadium des Aggregation-Framework verwendet. Um die Indizierung zu nutzen, müssen $ sort oder $ match als erste Stufe verwendet werden.

Bitte sehen Pipeline Operators and Indexes

+0

Ich sehe, aber viele reale Fälle können die Ergebnisse am Anfang der Pipeline nicht sortieren. Also sind solche Pipelines dazu verdammt langsam zu sein? Gibt es Techniken, um es schneller zu machen? – Seffy

+0

Leider kann man nicht viel tun. Wenn Sie jedoch MongoDB 3.2+ verwenden, versuchen Sie, $ filter anstelle von $ unwind zu verwenden. Dies reduziert Ihre Datenmenge und beschleunigt die Abfrage. – Saleem

+0

die anderen Probleme ist, dass $ sort nur einen Kern/Prozessor @Seffy verwenden – profesor79

0

Das entspannen wegen geschehen $ stage.Your Abfrageleistung ist langsam, da Abfrage nicht nach dem $ entspannen stage.Check Berücksichtigung Index, mit explain.you zu know.This bekommen geschieht, weil Nach dem $ -Abwickeln ändern sich die ganzen Dokumente und es wird anders, das im RAM für die Indizierung gespeichert wird.