ThinkPHP連線mongo的奇異現象
由於最近公司P(po)V(fu)上(wu)升(qi),我們想出了不復雜的查詢邏輯,由Mongo資料庫代替mysql資料庫的解決方案
於是經過一番改造,終於把一坨邏輯改成了mongo,接著進行了多次測試,以下是測試中的一部分資訊,出於安全考慮,欄位和表名已經隱藏,請黨和人民放心。
mysql程式執行資訊:
mongo程式執行資訊:
結論:多次測試表示,mongo的整體速度都優於mysql(非複雜查詢)
那麼這樣一來,mongo的方案就確定下來了。
於是,我們進行了更大規模的改造,將一個功能模組都改成了mongo,結果,問題發生了。
不知道為什麼,mongo的查詢速度大幅度下降,由於我們原來的邏輯屬於集中式的A(luo)P(ji)I(hun)方(luan)式,改造工作遇到了一些瓶頸,所以不得不在公有層就進行大規模Model例項化,所以問題開始,鎖定在了這裡
可以看到,我在這裡做了一個斷(jie)點(shu)調(cheng)試(xu),然後對比程式的執行時間,同時mysql的也是一樣的邏輯
當然,由於初始化的速度非常快,這裡使用的時間單位是毫秒/100
mongo速度:
這是多少?——1秒!震驚了,足足1秒鐘,僅僅是例項化6個model並構建mongo連線
好吧,也許是think的mongo模型沒有做判斷,導致我連線了6次mongo資料庫?
果斷只留下一個例項化,結果——還是1秒多….
我的連線方式如下:
BaseModel,所有自定義Model的父類,繼承think的MongoModel:
自定義Model,傳遞表名,呼叫父類構造:
沒看出任何問題的我也是醉了,於是不得不思考think的機制問題,於是一路追上去…
路過think的MongoModel,沒發現呼叫,於是找到Model類的構造的db方法
沒有發現什麼異常,在這裡斷點依然很慢
繼續追查,發現了直到發現了_after_db()
這個回撥方法是空的,而model沒有父類,很顯然,他呼叫的是子類的回撥方法,那麼根據我們的邏輯,子類必然是MongoModel,好吧,我們繼續走…
找到了切換資料庫的方法…原來think是這麼個運作流程…
db成員變數就是當前資料庫的連線,做過自己框架的同學想必和我一樣,對這個成員變數很是熟悉吧…
好,我們來dump一下,看看它到底是誰…
DbMongo…在驅動目錄下找到DbMongo下的對應切換資料庫方法
很顯然,第一次進入的時候,我們會直接獲取資料庫連線(這裡的邏輯很很明顯的告訴我們,重複連線神馬的,think沒這麼2)
重頭戲來了….我們找到了最根的資料庫連線,明顯看到了MongoClient擴充套件的例項化,於是我直接在這裡打斷了程式…結果發現依然很慢….
再試,索性連引數都不傳,直接連…好吧,也很慢….
也就是說,與之前的邏輯無關,本身MongoClient就很慢!
OMG!難道是我本機配置不對?趕緊寫個demo壓壓驚…
好,來看看速度…
….這是啥,火箭麼?!
順便來一個PDO直連mysql的demo,測試速度如下:
明顯,本地配置沒問題,程式碼沒問題,甚至think框架都沒問題…
這到底是什麼鬼?!