1. 程式人生 > >ThinkPHP連線mongo的奇異現象

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框架都沒問題…

這到底是什麼鬼?!