0

I'm having issues optimising update performance for a Meteor collection.

I take a document from one collection (CollectionA), modify it, cherry-pick some of the content, and then update a near duplicate of it in another collection (CollectionB). I also upsert in case new documents have been added to CollectionA

Everything happens in a few milliseconds, but the update can take anywhere from 10–30+ seconds depending on the size of the document being updated. The documents are typically around 30kb...

I have tried without Meteor.defer, with writeConcern : 0, and on both local and cloud replica set clusters. Have also tried using insert instead of update. Nothing makes a noticeable difference.

cronTask(){

    CollectionA.find({isPublished : true, "approval.status" : { $gte : 1 } }).forEach((doc)=>{

        let newDoc = {
            parentId : doc._id,
            slug : doc.slug, // these never change, only the content array changes...
            title : doc.title,
            description: doc.description,
            tags : doc.tags,
            category : doc.category,
            createdAt : new Date(),
            content: [...,...,...] // the content of the new document is cherrypicked from the parents before saving
        }

        while(doc.content.length) {
            // cherry-picking and pushing to newDoc.content
            // super quick, a couple of MS
        }

        Meteor.defer(()=>{
            CollectionB.update({parentId : doc._id}, {$set : newDoc}, {upsert : true}, (err,res)=>{
                if (!err) {
                    console.log(`Saved child for ${doc.title}`);
                } else {
                    console.log(`Error saving child for ${doc.title}: ${err}`);
                }
            });
        });

    });
}
Jack Wild
  • 2,072
  • 6
  • 27
  • 39
  • let me guess: you do that while having a page open that reacts to changes in the collection you are adding to? That's a common problem and there are some answers on SO for that. I'll try to dig them up for you. – Christian Fritz Nov 19 '15 at 18:46
  • Does the following answer help you? http://stackoverflow.com/a/19599027/1087119 – Christian Fritz Nov 19 '15 at 18:47
  • 1
    Thanks Christian, it wasn't actually that... but that looks very useful for me to read anyway. After lots of head scratching I found that the problem was schema validation which was taking forever, and then the actual update did about 30 in 2ms, so I'm okay with that. ;) Not sure why the schema validation took such a long time, but it's on the server in this case, so I just disabled it because it's not essential to do for this. – Jack Wild Nov 20 '15 at 09:43
  • great! if you can formulate it as an answer, then I think it would be worth adding it here for others. Sounds like a pitfall not easy to detect. – Christian Fritz Nov 20 '15 at 16:40

1 Answers1

1

Turned out that the issue was not in fact the update, it was schema validation (using https://github.com/aldeed/meteor-simple-schema).

I disabled schema checking for the objects in the array (the method is on the server so it's safe to not validate in this case). Now it takes <1ms to update all 30 documents.

Not sure why the schema validation was so slow.

Jack Wild
  • 2,072
  • 6
  • 27
  • 39
  • Just found this answer and it pointed me in the perfect direction. Personally, I'm using astronomy but using the raw collection instead of the astronomy class made my update in a test env go from 8sec to 5ms! Thank you :) – Duffmaster33 Sep 13 '16 at 17:42