I have a server-side method which computes various statistics by comparing two failry large collections (100k documents each), one a collection of sales data and the other contains a calendar. The method runs a loop about 3000 times (a user selected set of days). Each loop it might need to do 5-6 fetch and 4-5 count queries and while each query doesn’t take that much time, in aggregate they slow down the whole process. Currently a fetch is taking about 6ms and a count 4ms, making each loop take around 55ms in total or almost 3 minutes for the whole method. While these seem quick it’s not quick enough, especially with multiple users asking for data. I’m looking for advice on how speed this whole process up.
I’m running Meteor 1.6.1 hosted on a Digital Ocean droplet using a a 3-member MongoDB deployment also hosted on Digital Ocean (droplets with 2GB ram each).
I have tried the following:
- Created an index for each query
- Returning only needed fields in each query
- Reduced number of queries to minimum needed for the various operations
- Ran a $explain on each query to make sure it’s hitting the relevant index
If I run each query in the Mongo shell, they all report less than 1ms response time with a fetch, but in my Meteor app it’s about 5-7ms for the fetch. I’ve tried pre-loading some of the data into an in-memory array which definitely runs quite a bit faster (only taking around 15 seconds to complete the whole method), but is impractical if I have to load everything in both collections. I’ve also tried MongoDB hosting on Compose and MLab just to see if it’s my DO deployment, but both has worse response times).
Is this something where Redis could speed things up, or is Redis mostly used for client-server interactions? Is there an in-memory DB solution for server-side use? Would Grapher help in this case? Help appreciated.
//Data schema example (simplified)
Locations = {
location: {
id: "ID",
date: "2017-01-01"
},
items: 1234,
cost: 1234,
expenses: 1234
}
Calendar = {
date: "2017-01-01",
open: true
}
//Query examples
let costOnDay = Locations.findOne({"location.id": "ABCD1234", "location.date": "2017-01-01"}, {fields: {store: 1, cost: 1}});
let expenses = Locations.find({"location.id": "ABCD1234", "location.date": {$lte: "2017-01-01"}}, {sort: {"location.date": -1}, limit: 120, fields: {store: 1, expenses: 1}}).fetch().reverse();
let daysOpen = Calendar.find({date: {$gte: "2017-01-01", $lte: "2017-02-01"}, open: true}, {sort: {date: 1}}).count();