Mongodb 笔记04 特殊索引和集合、聚合、应用程序设计
特殊索引和集合
1. 固定集合:固定集合需要事先創建好看,而且它的大小是固定的。當固定集合被占滿時,如果再插入新文檔,固定集合會自動將最老的文檔從集合中刪除。
2. 創建固定集合:db.createCollection("my_collection",{"capped":true,"size":10000}) ?創建一個大小為10000字節的固定集合
? ? 除了大小,createCollection還能指定固定集合中文檔的數量:db.createCollection("my_collection",{"capped":true,"size":10000,"max":10}) ?
? ? 指定文檔數量時,必須同時指定集合大小。固定集合的文檔數量不能超過文檔數量限制,固定集合的大小也不能超過大小限制。
3. 將某個常規集合轉換為固定集合:db.runCommand({"convertToCapped":"test","size":10000}) ? 無法將固定集合轉換為非固定集合。
4. 自然排序:自然排序返回結果集中文檔的順序就是文檔在磁盤上的順序。只有固定集合中的自然排序才有意義,對其他集合來說文檔位置經常變化,自然排序意義不大。
5. 循環游標:一種特殊的游標,當循環游標的結果集被取光后,游標不會被關閉。當有新文檔插入到集合時,循環游標會繼續取到結果。由于普通集合并不維護文檔的插入順序,循環游標只能用在固定集合上。
6. 調用createCollection創建集合時指定autoIndexId選項為false,創建集合時就不會自動在"_id"上創建索引。實踐中不建議這么用,但對于只有插入操作的集合來說,這確實可以帶來速度上的稍許提升。
7. TTL索引:如果需要更加靈活的老化移出系統,可以使用TTL索引,這種索引允許為每一個文檔設置一個超時時間。一個文檔到達預設置的老化程度之后就會被刪除。這種類型的索引對于緩存問題很有用。
? ? db.foo.ensureIndex({"lastUPdated":1},{"expireAfterSecs":60*60*24}) ? ? ? ? ? ?// 過期時間24小時
? ? MongoDB每分鐘對TTL索引進行一次清理,所以不應該依賴以秒為單位的時間保證索引的存活狀態。可以使用collMod命令修改expireAfterSecs的值:
? ? db.runCommand({"collMod":"someapp.cache","expireAfterSecs":3600}) ? ? ? ? ??
? ? 一個給定的集合上可以有多個TTL索引,但TTL不能是復合索引。
8. 全文本索引:暫不建議使用,性能影響太大。
9. 地理空間索引:最常用的是2dsphere索引(用于地球表面類型的地圖)和2d索引(用于平面地圖和時間連續的數據)
10. 使用GridFS存儲文件:GridFS是MongoDB的一種存儲機制,用來存儲大型二進制文件。
? ? ? 優點:
? ? ? a. 簡化你的棧,可以使用GRIDFS來代替獨立的文件存儲工具。
? ? ? b. 對文件存儲做故障轉義或者橫向擴展更容易
? ? ? c. 可以比較從容地解決其他一些文件系統可能遇到的問題。
? ? ? d. 文件存儲的集中度會比較高
? ? ? 缺點:
a. 性能低:從MongoDB中訪問文件,不如直接從文件系統中訪問文件速度快。
? ? ? b. 如果要修改GridFS上的文檔,只能先將已有的文檔刪除。
? ? ? 通常來說,如果你有一些不常改變但是經常需要連續訪問的大文件,那么使用GridFS再合適不過。(性能呢?因為緩存到內存了?)
11. GridFS背后的理念:可以將大文件分割為多個比較大的塊,將每個快作為獨立的文檔進行存儲。有一個文檔用于將這些塊組織在一起并存儲該文檔的元信息。
12. 可以使用任何自定義的字段來保存必須的文件元信息。可能你希望在文件元信息中保存文件的下載次數,MIME類型或者用戶評分。
?
?
聚合
如果你有數據存儲在MongoDB中,你想做的可能就不僅僅是將數據提取出來那么簡單;你可能希望對數據進行分析加以利用。本章介紹MongoDB提供的聚合工具
1. 聚合框架:使用聚合框架可以對集合中的文檔進行變化和組合。基本上,可以用多個構架創建一個管道,用于對一連串的文檔進行處理。這些構件包括篩選、投射、分組、排序、限制和跳過。
2. 管道操作符:每個操作符都會接受一連串的文檔,對這些文檔做一些類型轉換,最后將轉換后的文檔作為結果傳遞給下一個操作(對于最后一個管道操作符,是將結果返回給客戶端)。不同的
? ? ? ? ? ? ? ? ? ? ?管道操作符可以按任意順序組合在一起使用,而且可以被重復任意多次。
? ? ? ? ? ? ? ? ? ? ?1). $match : $match用于對文檔集合進行篩選,之后就可以在篩選得到的文檔子集上做聚合。在實際使用中應該盡可能將"$match"放在管道的前面位置,這樣有兩個好處:
? ? ? ? ? ? ? ? ? ? ? ? ? ?a. 可以快速將不需要的文檔過濾掉,以減少管道的工作量
? ? ? ? ? ? ? ? ? ? ? ? ? ?b. 如果在投射和分組之前執行"$match",查詢可以使用索引
? ? ? ? ? ? ? ? ? ? ? ? ? ?用法:{$match:{"state":"OR"}}
? ? ? ? ? ? ? ? ? ? ? 2). $project : 可以從文檔中提取字段,可以重命名字段,還可以進行一些其他操作。
? ? ? ? ? ? ? ? ? ? ? ? ? ?用法:db.articles.aggregate({"$project":{"author":1,"_id":0}}) ? 只返回author字段。
? ? ? ? ? ? ? ? ? ? ? ? ? ?字段重命名:{"$project":{"userId":"$_id","_id":0}} ? ? $fieldname語法是為了在聚合框架中引用fieldname字段的值。重命名后不能使用原字段上的索引。
? ? ? ? ? ? ? ? ? ? ? ? ? ?數學表達式:
? ? ? ? ? ? ? ? ? ? ? ? ? ?a. $add : [expr1[,expr2....exprN] 這個操作符是接收一個或多個表達式作為參數,將這些表達式相加
? ? ? ? ? ? ? ? ? ? ? ? ? ?b. $subtract : [expr1,expr2] ?接收兩個表達式,用第一個表達式減去第二個表達式作為結果
? ? ? ? ? ? ? ? ? ? ? ? ? ?c. $multiply : [expr1[,expr2.....exprN] : 將參數相乘
? ? ? ? ? ? ? ? ? ? ? ? ? ?d. $divide : [expr1,expr2] 第一個表達式除以第二個表達式的商作為結果
? ? ? ? ? ? ? ? ? ? ? ? ? ?e. $mod [expr1,expr2] 第一個表達式除以第二個表達式的余數作為結果
? ? ? ? ? ? ? ? ? ? ? ? ? ?日期表達式
? ? ? ? ? ? ? ? ? ? ? ? ? ?$year ,$month,$week,$dayOfMonth,$dayOfWeek,$dayOfYear,$hour,$minute,$second
? ? ? ? ? ? ? ? ? ? ? ? ? ?字符串表達式:
? ? ? ? ? ? ? ? ? ? ? ? ? ?a. $substr : [expr,startOffset,numToReturn] : 截取字符串,從startOffset字節開始的numToReturn字節。注意是字節不是字符。
? ? ? ? ? ? ? ? ? ? ? ? ? ?b. $concat : [expr1,expr2,....exprN] : 將給定的表達式(或者字符串)連接在一起作為返回結果
? ? ? ? ? ? ? ? ? ? ? ? ? ?c. $toLower : expr ?返回小寫形式
? ? ? ? ? ? ? ? ? ? ? ? ? ?d. $toUpper: expr 返回大寫形式
? ? ? ? ? ? ? ? ? ? ? ? ? ?邏輯運算符:
? ? ? ? ? ? ? ? ? ? ? ? ? ?$cmp:[expr1,expr2] : 比較expr1和expr2。如果expr1等于expr2,返回0,;如果expr1小于expr2;返回負數;如果大于,返回正數
? ? ? ? ? ? ? ? ? ? ? ? ? ?$strcasecmp:[string1,string2] : 比較字符串大小
? ? ? ? ? ? ? ? ? ? ? ? ? ?$eq/$ne/$gt/$gte/$lt/$lte:[expr1,expr2]
? ? ? ? ? ? ? ? ? ? ? ? ? ? 幾個布爾表達式:
? ? ? ? ? ? ? ? ? ? ? ? ? ? $and:[expr1,expr2...exprN] 如果所有表達式都為true,則返回true,否則返回false
? ? ? ? ? ? ? ? ? ? ? ? ? ? $or :?[expr1,expr2...exprN] ?有一個為true,則返回true
? ? ? ? ? ? ? ? ? ? ? ? ? ? $not : expr 對表達式取反
? ? ? ? ? ? ? ? ? ? ? ? ? ? 兩個控制語句:
? ? ? ? ? ? ? ? ? ? ? ? ? ? $cond :[booleanExpr,trueExpr,falseExpr] : 如果booleanExpr為true,返回trueExpr,否則返回falseExpr
? ? ? ? ? ? ? ? ? ? ? ? ? ? $ifNull : [expr,replacementExpr] : 如果expr為null,返回replacementExpr,否則返回expr
? ? ? ? ? ? ? ? ? ? ?3). $group : $group 操作可以將文檔依據特定字段的不同值進行分組。
? ? ? ? ? ? ? ? ? ? ?4). $unwind : 拆分(unwind) 可以將數組的每一個值拆分成單獨的文檔。
? ? ? ? ? ? ? ? ? ? ?5). $sort : 可以根據任何字段進行排序,與在普通查詢中的語法相同。如果要對大量的文檔進行排序,建議在管道的第一階段進行排序,這樣可以使用索引。 ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? ?6). $limit : 接收一個數字n,返回集合中的前n個字段
? ? ? ? ? ? ? ? ? ? ?7). $skip : 接收一個數字n,丟棄結果集中的前n個文檔。
3. 使用管道:應該盡量在管道的開始階段就將盡可能多的文檔和字段過濾掉。管道如果不是直接從原先的集合中使用數據,那就無法再篩選和排序中使用索引。如果可能,聚合管道會嘗試對操作進行排序,
? ? ? ? ? ? ? ? ? 以便能夠有效的使用索引。如果MongoDB發現某個聚合操作占用了20%以上的內存,這個操作就會直接輸出錯誤。
? ? ? ? ? ? ? ? ? 如果能夠通過$match操作迅速減小結果集的大小,就可以使用管道進行實時聚合。
4. MapReduce : 非常強大,非常靈活。但速度慢,不應該用在實時的數據分析中。
5. 聚合命令:
? ? 1). count : db.foo.count()
? ? 2).?distinct : db.runCommand({"distinct":"people","key":"age"})
? ? 3). group
?
應用程序設計
1. 范式化:將數據分散到多個不同的集合,不用集合之間可以相互引用數據。雖然很多文檔可以引用某一塊數據,但是這塊數據只存儲在一個集合。
? ? 反范式化:將每個文檔所需的數據都嵌入在文檔內部。每個文檔都擁有自己的數據副本,而不是所有文檔共同引用同一個數據副本。
? ??范式化能夠提高數據寫入速度,反范式化能夠提高數據讀取速度。
2. 更適合內嵌:子文檔較小,數據不會定期改變,最終數據一致性即可,文檔數據小幅增加,數據通常需要執行二次查詢才能獲得,快速讀取
? ? 更適合引用:子文檔較大,數據經常變化,中間階段的數據必須一致,文檔數據大幅增加,數據通常不包含在結果中,快速寫入
3. 優化數據操作:如果要優化應用程序,首先必須知道對讀寫性能進行評估以便能找到性能瓶頸。對讀取操作的優化通常包括正確使用索引,以及盡可能將所需信息放在單個文檔中返回,
? ? 對寫入操作的優化通常包括減少索引數量以及盡可能提高更新效率。
4. 經常需要再寫入效率更高的模式與讀取效率更高的模式之間權衡,所以必須要知道哪種操作對你的應用程序更重要。這里的影響因素并不只是讀取和寫入的重要性,也包括讀取和寫入操作的頻繁程度.
5. 數據優化方式:
? ? 1). 優化文檔增長:更新數據時,需要明確更新是否會導致文件體積增大,以及增長程度。如果增長程序是可預知的,可以為文檔預留足夠的增長空間,這樣可以避免文檔移動,提高寫入速度。
? ? ? ? ?檢測一下填充因子,如果它大約是1.2或者更大,可以考慮手動填充。如果要對文檔手動填充,可以在填充文檔時創建一個占用空間比較大的字段,文檔創建成功之后刪除這個字段。
? ? ? ? ?插入時添加或者在upsert時,使用$setOnInsert創建這個字段。更新文檔時,使用$unset移除。如果這個字段不存在,$unset操作什么也不做。
? ? ? ? ?可以考慮將會增長的字段,放在最后面。
? ? 2). 刪除舊數據,主要有三種方式:使用固定集合,使用TTL集合,使用定期刪除集合。
6. 一致性管理:
? ? 服務器為每個數據庫連接維護一個請求隊列。客戶端每次發來的新請求都會添加到隊列末尾。入隊之后,這個連接上的請求會一次得到處理。一個連接擁有一個一致的數據庫視圖,可以總是讀取到這個
? ? 連接最新寫入的數據。注意,每個隊列只對應一個連接:如果打開兩個shell,連接到相同的數據庫,這時就存在兩個不同的連接。如果在齊中一個shell中執行插入操作,緊接著在另一個shell中執行
? ? 查詢操作,新插入的數據肯呢個不會出現在查詢結果中。
7. 不適合使用MongoDB的場景:
? ? 1). MongoDB不支持事務
? ? 2). 無法在多個維度上對不同類型的數據庫進行連接。
? ? 3). 你使用的工具不支持MongoDB
? ? ? ? ??
轉載于:https://www.cnblogs.com/Jtianlin/p/5118097.html
總結
以上是生活随笔為你收集整理的Mongodb 笔记04 特殊索引和集合、聚合、应用程序设计的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android 项目中常用到的第三方组件
- 下一篇: Codeforces 437C The