摘要:執行計劃之前發了一篇關于執行計劃的說明。利用執行計劃,我們可以判斷每一次的執行情況和給出的執行建議。在中跑執行計劃的命令,舉個例子執行計劃的模式為三種。程序中跑執行計劃我使用的是庫用的是。響應結果會有執行時間掃描記錄數等真實的執行情況。
執行計劃
之前發了一篇關于mongodb執行計劃的說明。利用執行計劃,我們可以判斷每一次sql的執行情況和mongodb給出的執行建議。在mongo shell中跑執行計劃的命令,舉個例子:
db.collecitonName.find({}).explain("queryPlanner")
執行計劃的模式為三種:queryPlanner executionStats allPlansExecution。第一種不會真正跑命令本身,只有響應命令分析后的報告。上面例子的響應結果就是對 db.collecitonName.find({}) 這個查詢語句的分析。
程序中跑執行計劃我使用的是java, mongodb庫用的是mongodb-java-driver。mongodb-java-driver的API提供了兩種方式去跑執行計劃:
方式一:MongoClient mongoClient = new MongoClient(new ServerAddress(host, port)); mongoClient.getDB("xxx").getCollection("yyy").find(quert).explain();
這是一個便捷的方式。這種方式會真正執行命令,也就是說它使用的是executionStats模式。響應結果會有執行時間、掃描記錄數等真實的執行情況。如果你的程序想要在命令執行前做一個預判,這個API不是你想要的。
方式二:API沒有提供queryPlanner的方式。我花了一些時間去搜索資料,發現網上沒有跑queryPlanner的需求,至少我是沒有找到類似的發問和使用例子。糾結了一會兒,最終發現庫里有這樣一個api, mongoClient.getDB("xxx").command(BasicDBObject command),支持程序傳入一個命令。最后在官方文檔里找到了這樣一個說明:
explain New in version 3.0. The explain command provides information on the execution of the following commands: aggregate, count, distinct, group, find, findAndModify, delete, and update. Although MongoDB provides the explain command, the preferred method for running explain is to use the db.collection.explain() and cursor.explain() helpers. The explain command has the following syntax:
語法如下:
{ explain:, verbosity: } explain: 。 支持 aggregate, count, distinct, group, find, findAndModify, delete, and update等等的命令。 verbosity: 。支持模式"queryPlanner" 、"executionStats" 、"allPlansExecution" (Default)
跟蹤find進去,find支持的字段如下,應有盡有。
{ "find":, "filter": , "sort": , "projection": , "hint": , "skip": , "limit": , "batchSize": , "singleBatch": , "comment": , "maxScan": , // Deprecated in MongoDB 4.0 "maxTimeMS": , "readConcern": , "max": , "min": , "returnKey": , "showRecordId": , "tailable": , "oplogReplay": , "noCursorTimeout": , "awaitData": , "allowPartialResults": , "collation": }
通過閱讀文檔,跑queryPlanner模式的執行計劃應該是這樣的:
//查詢某個集合,queryCondition是查詢條件。 MongoClient mongoClient = MongoUtil.getConnection(mongodb.getHost(), mongodb.getPort(), "", "", mongodb.getDb()); BasicDBObject command = new BasicDBObject(); BasicDBObject find = new BasicDBObject(); find.put("find", "集合名"); find.put("filter", queryCondition);//查詢條件,是一個BasicDBObject command.put("explain", find); command.put("verbosity", "queryPlanner"); CommandResult explainResult = mongoClient.getDB(mongodb.getDb()).command(command);python程序中跑執行計劃遇到的坑
使用 pymongo庫
import json import pymongo if __name__ == "__main__": client = pymongo.MongoClient(host="127.0.0.1", port=27017) #指定一個db db = client.get_database(name="datanamexxx") command = {} explain = {} #要操作的集合 explain["find"] = "collectionnamexxx" #查詢的條件 explain["filter"] = {"col1":"202060056"} verbosity = "executionStats" command["explain"] = explain command["verbosity"] = verbosity print json.dumps(db.command(command=command))
以上程序是有問題的,不能達到想要的目的(一次查詢的執行情況)。后來經過查閱mongo文檔和嘗試,明確是使用方式不正確導致的。
錯誤原因:mongo的command要求參數是有序的,因為首參數是命令名。正如上面的find命令:
{ "find":, #命令名 "filter": , "sort": , "projection": , "hint": , "skip": , "limit": , "batchSize": , "singleBatch": , ...
mongo驅動在處理命令時首先要知道執行哪個命令,然而 python的dict或者的java的map再或者所有的map數據結構都是無序的。我們需要一個記錄參數的順序,使用者需要把首參數設置在最前面。我們來看看驅動的源碼,原理其實是對dict封裝一層,添加一個list來記錄參數順序:
#繼承dict class SON(dict): def __init__(self, data=None, **kwargs): #__keys就是記錄參數順序的列表 self.__keys = [] dict.__init__(self) self.update(data) self.update(kwargs) #省略... #打印時,按__keys的順序拼字符串,合理 def __repr__(self): result = [] for key in self.__keys: result.append("(%r, %r)" % (key, self[key])) return "SON([%s])" % ", ".join(result) #設置元素時,先把key按順序保存下來 def __setitem__(self, key, value): if key not in self.__keys: self.__keys.append(key) dict.__setitem__(self, key, value) def __delitem__(self, key): self.__keys.remove(key) dict.__delitem__(self, key) #省略...pymongo正確的使用方式
import json import pymongo if __name__ == "__main__": client = pymongo.MongoClient(host="127.0.0.1", port=27017) #指定一個db db = client.get_database(name="datanamexxx") #注意順序 explainSon = SON([("find", "collectionnamexxx"), ("filter", {"uid": "202060056"})]) cmd = SON([("explain", explainSon), ("verbosity", "queryPlanner")]) print json.dumps(db.command(cmd))
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/19496.html
我的專欄地址:我的segmentfault,歡迎瀏覽 一、執行計劃介紹 MongoDB 3.0之后,explain的返回與使用方法與之前版本有了不少變化,介于3.0之后的優秀特色,本文僅針對MongoDB 3.0+的explain進行討論。現版本explain有三種模式,分別如下: queryPlanner executionStats allPlansExecution 其中 qu...
平日學習接觸過的網站積累,以每月的形式發布。2017年以前看這個網址:http://www.kancloud.cn/jsfron... 03月份前端資源分享 1. Javascript 175453545 Redux compose and middleware 源碼分析 深入 Promise(二)——進擊的 Promise Effective JavaScript leeheys blog -...
平日學習接觸過的網站積累,以每月的形式發布。2017年以前看這個網址:http://www.kancloud.cn/jsfron... 03月份前端資源分享 1. Javascript 175453545 Redux compose and middleware 源碼分析 深入 Promise(二)——進擊的 Promise Effective JavaScript leeheys blog -...
平日學習接觸過的網站積累,以每月的形式發布。2017年以前看這個網址:http://www.kancloud.cn/jsfron... 03月份前端資源分享 1. Javascript 175453545 Redux compose and middleware 源碼分析 深入 Promise(二)——進擊的 Promise Effective JavaScript leeheys blog -...
閱讀 2413·2021-08-18 10:21
閱讀 2519·2019-08-30 13:45
閱讀 2155·2019-08-30 13:16
閱讀 2100·2019-08-30 12:52
閱讀 1363·2019-08-30 11:20
閱讀 2622·2019-08-29 13:47
閱讀 1622·2019-08-29 11:22
閱讀 2760·2019-08-26 12:11