MongoDB Aggregation 優化

寫 MQL aggregation 有一些要注意的地方,雖然蠻多部分 MongoDB 都幫你優化了,但還是要注意一下小地方,讓你的 MQL 效能更好

Case1

絕對優先使用 $match 減少資料量

$match -> $project

  • $match 過濾不必要的資料,減少記憶體與CPU消耗
  • $project 過濾不必要的欄位,同上,若你預期的結果不需要使用某些欄位時,就先移除再進行其他操作

Case2

$match -> $sort

基本上是上面的變形,先減少資料量再排序

Case4

這邊是比較少用到的狀況,但也很好理解

1
2
3
4
{ $limit: 35},
{ $limit: 15}
自動合併為 =>
{ $limit: 15}
1
2
3
4
{ $skip: 3},
{ $skip: 5}
自動合併為 =>
{ $skip: 8}
1
2
3
4
{ $match: { age : 22 }},
{ $match: { dept: "IC" }}
自動合併為 =>
{ $match: { $and: [ { age : 22 }, { dept: "IC" } ] }}

Case5

$lookup + $unwind 合併
通常 $lookup + $unwind 這樣的組合,MongoDB會自動併入

1
2
3
4
5
6
7
8
9
{
$lookup: {
from: "xxxCollection",
as: "newArray",
localField: "fieldX",
foreignField: "fieldY"
}
},
{ $unwind: "newArray"}
1
2
3
4
5
6
7
8
9
{
$lookup: {
from: "xxxCollection",
as: "newArray",
localField: "fieldX",
foreignField: "fieldY",
unwinding: { preserveNullAndEmptyArrays: false }
}
}

這樣做有非常強大的好處,主因是能避免先生成 Array 檔案後,再進行 $unwind 拆分成很多檔案。
另一個隱藏好處是可以避免第一個階段 Array 過大,超過 BSON 16MB 限制

Case6

最常見的排序,要特別注意的是這建立在檔案數量沒有修改的情況下(像是 $unwind)
可以預知最大數量就是 15,因此排序後立即限制數量,最後再進行 $skip

1
2
3
{ $sort: { age : -1 } },
{ $skip: 10 },
{ $limit: 5 }

=>

1
2
3
4
5
6
7
8
9
10
11
{
"$sort" : {
"sortKey" : {
"age" : -1
},
"limit" : NumberLong(15)
}
},
{
"$skip" : NumberLong(10)
}
  • 作者: MingYi Chou
  • 版權聲明: 轉載不用問,但請註明出處!本網誌均採用 BY-NC-SA 許可協議。