我在專案中遇到一個MongoDB的問題,好多天了還是沒能得到解決,希望得到大牛的指點。
具體問題是:長時間不存取資料庫的情況下,第一次查詢資料庫所需的時間很長,但是之後的查詢就會很快。
具體情況:
①整个数据库大小大概在1.9TB左右;
②我查询的collection的数据大致为700万条;
③我查询一次得到的数据为23万条左右;
④服务器内存为120GB;
⑤已按照查询条件建立了索引,索引数据大小为600MB左右;
⑥第一次查询所用时间20s左右,之后的查询在1s以内。
目前考慮的原因:
由于MongoDB不负责内存的管理,所以,当长时间未访问数据库时,内存中的数据即为冷数据,操作系统的内存管理程序就会将这部分冷数据释放,导致下次查询时,需要重新加载数据到内存,所以比较费时。目前,不能够确定是加载索引比较费时,还是加载数据比较费时。MongoDB虽然提供了touch命令(该命令能够指定将某个collection的索引数据或者用户数据加载到内存中),但是我使用的是WiredTiger存储引擎,该命令不支持该存储引擎。
需要得到的幫助:
①是不是以上原因导致的该问题?
②如果是该原因导致的,如何确定是加载索引费时还是加载数据费时?
③有什么比较好的解决方案么?
注:由于该collection最大会达到25GB左右,而且整个数据库还有其他很多collection,所以将该collection的所有数据存储到内存是不可取的。如果能够确认是加载索引费时的话,倒是可以考虑定期将索引加载到内存,但是对于WiredTiger存储引擎,没有支持该功能的方法,这又是一个问题。
phpcn_u15822017-05-02 09:28:08
您說的這個問題是和working set相關聯。
1、什麼是working set?
MongoDB的記憶體管理中一個重要的概念。在記憶體管理中盡量將業務經常存取的資料集和相關的索引放置在記憶體中。
2、怎麼將working set放置在記憶體中呢?
在您的表述中,其實是一個需要將working set提前預熱放置在記憶體中(Preload or Preheating)。具體怎麼做?您提到了touch(MMAP引擎),那麼在後續的版本(WT引擎)中如何實現呢?
如果是關係型資料庫,常會用到的辦法是select *,很多時候做效能測試,為達到好的效果,都會事先執行一批次Select語句預熱記憶體。
在MongoDB中,可以考慮:
1)如果業務查詢中可以直接使用到covered index來查詢的,或者說需要預熱index的時候:
db.collection.find({}, {"_id" : 0, "field_a" : 1, "field_b" : 1}).hint({"field_a" : 1, "field_b" : 1}).explain( )
2)當需要預熱working set時,前提是您知道你的collection中哪些資料是經常需要被存取的,通常是某個時間段,然後將這個時間段的collection,使用上面相同的方法來預熱。
不同之處是:預熱index是將這個index都預熱了,所以查詢條件是{},鵝而,預熱working set,只是預熱collection中某一部分數據,所以這個查詢條件可能是和時間範圍相關的條件。
供參考。
Love MongoDB! Have fun!
MongoDB中文社群深圳用戶大會
這個週六,大家約起
詳情請入