Mongo實戰 分片集群的查詢與索引

2021-08-08 02:43:47 字數 2463 閱讀 8264

從應用程式的角度來看,查詢分片集群和查詢單個mongod沒什麼區別。這兩種情況下,查詢介面和迭代結果集的過程是一樣的。但在外表之下,兩者還是有區別的,我們需要從細節層面進行了解。

1. 分片查詢型別

假設正在查詢乙個分片集群,為了返回乙個恰當的查詢響應,mongos要與多少個分片進行互動。稍微思考一下,就能發現這與分片鍵是否出現在查詢選擇器裡有關。配置伺服器(就是mongos)維護了乙份分片範圍的對映關係,就是我們在前面博文中描述的塊。如果查詢包含分片鍵,那麼mongos通過資料塊能夠很快定位哪個分片包含查詢的結果集。這個稱為針對性查詢(targeted query)

但是,如果分片鍵不時查詢的一部分,那麼查詢計畫器就不得不訪問所有分片來完成查詢。這稱為全域性查詢或分散/聚合查詢(scatter/gather query)。下圖描述了這兩種查詢。

針對任意指定的分片集群查詢,explain命令能顯示其詳細查詢路徑。首先看乙個針對性查詢,此處要查詢乙個隨機文件。

explain結果清晰地說明了查詢命中了乙個分片-分片a,返回乙個文件。查詢選擇器很聰明地使用了分片鍵字首的子集來路由查詢。

那麼全域性查詢又會是怎樣呢?你可以方便地使用explain命令。下面就是乙個根據filename欄位進行查詢的例子,其中既沒有用到索引,也沒有用到分片鍵:

selector=

db.spreadsheets.find(selector).explain(true)

執行結果如下:

如你所想,該全域性查詢在兩個分片上進行了表掃瞄,如果查詢與你的應用程式相關,你一定想在filename上增加乙個索引。無論哪種情況都會搜尋整個集群以返回完整結果。一些查詢要求並行獲取結果集。這就要求在mongos路由器上合併結果。沒有索引,這樣的額查詢會非常低效,並且會屢遭禁止。因此,在下面的查詢最近建立的文件的例子裡,你就先要建立必要的索引。

db.spreadshetts.ensureindex()
正如預期的那樣,游標掃瞄了每個分片的updated_at索引,一次返回最近更新的文件。

更有可能出現的查詢時返回某個使用者最新修改的文件。同樣,你要建立必要的索引,隨後發起查詢:

db.spreadshetts.ensureindex()
關於上面的查詢計畫,有幾個需要注意的地方。首先,該查詢指向了單個分片。因為你指定了分片鍵username,所以查詢路由器可以找出哪個分片包含了相關的塊。隨後你就會發現排序並不需要訪問所有的分片;當排序查詢中包含分片鍵,所要查詢的分片數量通常都能有所減少。

第二個需要注意的地方是分片使用了索引來執行查詢,這說明了乙個很重要的內容,即分片集群是如何處理查詢的。通過分片鍵將查詢路由給指定分片,一旦到了某個分片上,有分片自行決定使用哪個索引來執行該查詢。在為應用程式設計查詢和索引時,請牢記這一點。

2. 索引

有時,如果不確定某個查詢時怎麼解析的,可以試試explain()。通常這都很簡單,但是在執行分片集群時,有幾點關於索引的內容應該牢記在心,下面會逐個進行說明。

(2)由此可以得出乙個結論,每個分片上的分片集合都應該擁有相同的索引。如果不是這樣的話,查詢效能會很不穩定。

(3)分片集合只允許在_id欄位和分片鍵上新增唯一性索引。其他地方不行,因為這需要在分片間進行通訊,實施起來和複雜,而且相信這麼做速度也很慢,沒有實現的價值

一旦理解了如何進行查詢的路由選擇,以及索引時如何工作的,你應該就能針對分片集群寫出漂亮的查詢和索引了。

mongo分片集群生產環境操作步驟

mongodb 支援通過分片技術從而進行水平擴充套件,用以支撐海量資料集和高吞吐量的操作。如果資料集不夠大,還是建議您使用 mongodb 副本集,因為分片需要處理更多的技術細節,所以在分片環境下其效能可能始終沒有副本集效能強。本文通過介紹如何搭建 mongodb 分片集群以及及一些相關核心概念,可...

Mongo伺服器集群配置學習三 分片

mongodb的分片主要是指將集合拆分成小塊並分別存在不同伺服器上的過程。mongodb支援自動分片,可擺脫手動分片管理上的困難。在以下情況下需要運用分片 1.伺服器的磁碟不夠用。2.單個mongod不能滿足寫資料的效能需求。3.需要將大資料放入記憶體中提高效能。下圖為我們要實現的分片結構 從圖中我...

mongodb 分片集群的坑

一 config的時候不 配置檔案中configsvr一定要 如果啟動失敗,看看是不是安裝config的時候是直接複製的正在執行的mongodb例項 二 route伺服器啟動 直接.mongos命令 config伺服器的副本集名稱 rscfg 一定要記得 否則報 沒有副本的錯 這時候db.runco...