MongoDB在這裡比PostgreSQL慢了7倍
- 2019 年 10 月 7 日
- 筆記
編程應用、實戰教程,不容錯過
最近有需求,要將一個局域網Web數據平台遷移到線上,順帶着,本地服務使用的PostgreSQL也要替換成國內某雲的MongoDB。
由於之前的Web框架選擇的Django,為了能夠最小限度地改動代碼,並對接上MongoDB上已存在的數據庫和數據,在一番對比之後(Djongo和MongoEngine),選擇了MongoEngine這個對象文檔映射(ODM)模塊來替代Django原有的ORM。
對照着MongoEngine的文檔一頓操作,第一個頁面遷移完成,趕緊打開看看。
不看則已,一看瞎哭,頁面加載完足足等了1、2、3、4、5、6、7、8、……27秒

(線上MongoDB服務)
而之前的系統這個頁面打開只需要幾秒鐘:

(本地PostgreSQL服務)
這還了得,上線了不是給自己丟臉嗎,趕緊排查測試。
在這個頁面裏面,主要數據操作是從數據庫中查詢出原始數據,然後加載到Pandas的DataFrame中,接着在Pandas中進行各種數據處理,最後返回JSON數據給前端進行渲染。
數據庫總的數據量為接近500萬,最後的查詢結果在3萬左右。
對各個環節分別進行測試發現,主要的時間消耗在了從數據庫讀取數據,然後加載到Pandas這個過程中。
於是將這個過程專門提取出來,單獨測試其消耗的時間。結果發現,使用MongoEngine進行數據查詢,然後加載到Pandas中需要幾十秒的時間:

21秒的耗時,可能是由於MongoEngine對PyMongo進行封裝之後的性能不行吧,於是直接使用PyMongo進行測試:

果然,經過一層封裝之後,MongoEngine的效率不如PyMongo,但是直接使用PyMongo也消耗了14秒的時間。
而在本地使用PostgreSQL作為數據庫後端的Django ORM測試僅僅花費了3秒的時間:

使用list()對數據查詢結果進行處理是將其加載到Pandas中的一個常規前置操作,相當於遍歷查詢集的結果並將每一條數據添加到一個列表中。類似於以下操作:
res = [] for i in xx: res.append(i)
只是一個list()操作,就讓MongoDB的速度比PostgreSQL慢如此之多,難道我哪裡操作不對?
歡迎小夥伴們出謀劃策,分享解決方案~
萬水千山總是情,點個「收藏」行不行