1、前言:
mongodb部署在阿里雲服務器,
mongodb中collection存儲了百萬條記錄。
需求:優化查詢指定時間段內的所有數據的查詢時間,結果有百萬級別。
最初:313587條記錄耗時:114.156 s
2、一般解決方式
百度 google后,大部分解決方式是創建復合索引,連接如下:
解決:創建復合索引。http://virusswb.blog.51cto.com/115214/816136
但是復合索引並沒有解決我的問題,耗時並沒有減少。
於是開始以下分析:
其實通過find()查詢得到cursor的速度非常快。
耗時發生在cursor的next()迭代過程中:
大部分next()很快,部分next()耗時0.00099s甚至2.9840s。
cursor.next()部分速度慢的原因:
當數據為空后,進入cursor._refresh() 就會變慢。
cursor._refresh()部分速度慢的原因:
-
分析完后,發現cursor._refresh 應該會按照某種算法加載剩余部分數據或全部數據。
其實從mongodb加載數據的過程是免不了的。
所以最初的find()查詢得到cursor,
迭代cursor.next()或list(cursor)得到全部記錄的調用方式是沒有任何問題的。
3、針對我問題的解決方式
一般來說,大家開發環境數據庫所在服務器與自己電腦所在服務器在同一個網段;生產環境也是如此。
而我的數據庫服務器部署在阿里雲,在自己機器上訪問互聯網中一台機器上的數據庫,並加載百萬級數據時,
網絡延遲會很慢,導致耗時比較長。
於是測試了下將代碼放到mongodb所在服務器上執行,同樣313587條記錄耗時0.84s
完美解決了問題。
4、遺留的小尾巴
將代碼放在和數據庫同一網段的服務器上執行,會優化百萬級別的查詢時間。
但是:如果查詢記錄數太大,而服務器內存不夠,服務器會out of memory,正在執行的程序會被系統kill掉。
所以:要么加大服務器內存,要么再來一台和服務器同一網段的服務器,做到單機單用。
5、總結
程序員不僅要學會使用API,更需要了解其他網絡、操作系統相關的知識。
不可以把視線拘泥於代碼層面。
加油!
【完】