There are a couple of separate points here, but I don't think how MongoDB stores data in RAM is really relevant here - MongoDB just uses the mmap()
call and then lets the kernel take care of the memory management (the Linux kernel will use Least Recently Used (LRU) by default to decide what to page out and what to keep - there are more specifics to that but it's not terribly relevant).
In terms of your issues, it sounds like you might have had a corrupt index, though the evidence is somewhat circumstantial. Now that you have done a repair (the validate() command would have confirmed/denied beforehand), there won't be any evidence in the current data but you may find more evidence in the logs, particularly when you were attempting to recreate the index, or using the index in queries.
As for the spikes in the page faults, btree stats, journal, lock percentage, and average flush time, that has all the hallmarks of a bulk delete that causes a lot of index updates, and causes a large amount of IO. The fact that mapped memory drops off later in the graphs would suggest that once you ran the repair the storage size was significantly reduced, which usually indicates significant fragmentation (bulk deletes, along with updates that grow documents are the leading causes of fragmentation).
Therefore, I would look for a large delete operation logged as slow in the logs - it will only be logged once complete, so look for it to appear after the end of the events in MMS. One of the quirks of not running in a replica set is that a bulk operation like this is relatively non-obvious - it shows up as a single delete operation in the MMS graphs (usually lost in the noise).
These bulk delete operations usually tend to be run on older data that has not been recently used and has hence been paged out of active memory by the kernel (LRU again). To delete it you must page it all the data back in, then flush the changes to disk, and of course deletes require the write lock, hence the spikes in faults, lock percentage etc.
To make room for the deleted data, your current working set is paged out, which will hit performance on your normal usage until the deletes complete and the memory pressure eases.
FYI - when you run a replica set, bulk ops are serialized in the oplog
and hence replicated one at a time - as such you can track such operations by their footprints in the replicated ops stats of the secondaries. This is not possible with a standalone instance (without looking in the logs for the completed ops) and other secondary indications.
As for managing large deletes in the future, it is generally far more efficient to partition your data into separate databases (if possible) and then drop the old data when it is no longer needed by simply dropping the old databases. This requires some extra management on the application side but it negates the need for bulk deletes, is far quicker to complete, limits fragmentation, and dropped databases also remove the files on disk, preventing excessive storage use. Definitely recommended if possible with your use case.
Set the min server memory
option for SQL Server. It will still release pages under memory pressure, unless you also allow SQL Server to lock pages in memory. The combination of setting min server memory
and locking pages in memory should resolve the problem.
I've never used MongoDB, so I don't know if you can manage memory usage. A quick search makes it seem you can't.
Assuming you're running a 64-bit server, and have more than 4 GB of RAM, you could run a 32-bit MongoDB instance, which will limit the memory to 2, 3, or 4GB depending on it's architecture. Does a 32-bit MongoDB even exist?
Best Answer
MongoDB uses memory mapped files for performance I'll point you to a longer answer from me on this here but in essence large amounts of virtual memory usage are not something to worry about. In the case of virtual memory you'll see double usage with journaling, however this is less drastic then it sounds as the space is not actually used until there is an update. It is marked to the OS as being used despite being potentially empty when you start.
These aspects are all elements of how MongoDB uses the memory subsystem to provide performance, similarly to how it preallocates disk space to ensure these resources are marked and ready to serve your connections when they occur.
There's an interest presentation on MongoDB's storage layer that explains how the storage is managed and allocated, aggressively in most cases which tends to bump up these numbers.