-
-
Notifications
You must be signed in to change notification settings - Fork 3.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
model.save is slower if schema has sub-document or sub-document array #5925
Comments
Thanks for the information, I don't know why off the top of my head but will investigate this ASAP. We're currently working on 5.0.0-rc0 so please be patient. |
I'm not able to reproduce the performance issue you are reporting. Here is a sample script to profile the creation of 10000 documents. I modified your schemas because a) you duplicated const mongoose = require('mongoose');
const co = require('co');
mongoose.Promise = global.Promise;
const GITHUB_ISSUE = `gh-5925`;
exec()
.then(() => {
console.log('successfully ran program');
process.exit(0);
})
.catch(error => {
console.error(`Error: ${error}\n${error.stack}`);
});
function exec() {
return co(function* () {
yield mongoose.connect(`mongodb://localhost:27017/${GITHUB_ISSUE}`);
console.log(`==============`);
console.log(`Benchmarking test with sub doc array`);
yield testWithSubDocArray();
console.log(`==============`);
console.log(`Benchmarking test with nested schema`);
yield testWithNestedSchema();
});
}
function addressDefinition() {
return {
streetaddress1: {
type: String
},
streetaddress2: {
type: String
},
city: {
type: Number
}
};
}
function testWithSubDocArray() {
return co(function* () {
const personSchema = new mongoose.Schema({
name: String,
addresses: [addressDefinition()]
});
const Person = mongoose.model('Person1', personSchema);
const person = new Person({
name: 'test sub doc',
addresses: generateAddresses()
});
yield benchmark(function persistWithSubDoc() {
return person.save();
});
});
}
function testWithNestedSchema() {
return co(function* () {
const personSchema = new mongoose.Schema({
name: String,
addresses: [new mongoose.Schema(addressDefinition())]
});
const Person = mongoose.model('Person2', personSchema);
const person = new Person({
name: 'test sub doc',
addresses: generateAddresses()
});
yield benchmark(function persistWithNested() {
return person.save();
});
});
}
function benchmark(func) {
return co(function* () {
const start = Date.now();
yield func();
const timeTaken = Date.now() - start;
console.log(`Time taken for ${func.name}:
ms: ${timeTaken} ms
seconds: ${timeTaken / 1000 }`
);
});
}
function generateAddresses() {
const addresses = [];
const address = {
streetaddress1: 'street address 1',
streetaddress2: 'street address 2',
city: 1
};
return Array.from({ length: 10000 }, (x => address))
} Here are some sample benchmark profiles from running multiple times: test run 1
test run 2
test run 3
|
I'm sorry for the 4+ years necro! I'm having this issue using a Map, instead of an Array. Should I just convert to array to save, but then convert back to map to use in my application? I don't know what I could do to have this simply save faster. Here is some simple time-logging of the process running:
EDIT: several hours later, many introduced and squashed bugs later, saving stuff through mongoose as arrays work pretty fast.
I assume that Mongoose somehow will try to double-check if every key is unique under the hood if you set the type as a map. That lookup for gigantic maps (mine was around 21k items overall) will severely slow down the saving. The solution, and the best of both worlds here, is to save as Array, convert it to Map, process your data as a Map, then convert it back to an Array before saving back with Mongoose. TLDR: Using maps will make Mongoose slow down to a crawl when saving large objects. Just use arrays instead. |
@TheYuriG thanks for reporting this issue. Can you please come up with a repro script or project that demonstrates this slowness? That would really help us debug and fix this performance bottleneck. You can use getters and setters to automate converting array to map and vice-versa. |
Yeah, if you don't mind waiting a day or two? I just want to wrap up these (unrelated) files I'm modifying so I don't jump in between things. Do you want me to open a separate issue? Would you like me to open a separate repo with the reproduction files so you can easily clone, then
Nice, I'll probably take a look at it when I get to your requested script then. Thanks for letting me know! |
Opening a separate issue would be great, happy to wait a day or two. Separate repo that I can |
The repro script is basically done, I just want to tweak a few things before making the new issue. Sorry for the delay and hope you had a good weekend! Didn't have time to wrap it up today because I got caught up doing intl stuff after the gym. I'll 100% finish it tomorrow morning. |
A separate issue was created (including reproduction script) at #13191. |
Do you want to request a feature or report a bug?
I need some clarification on why save is taking more time if my Schema has sub-document/sub-document array?
Example:
Person.save takes more time if Addresses has 10000 entries.
Whereas below nested schema takes 1/100th of commit time with same payload
What is the current behavior?
If the current behavior is a bug, please provide the steps to reproduce.
What is the expected behavior?
Please mention your node.js, mongoose and MongoDB version.
mongoose version is 4.9.4
The text was updated successfully, but these errors were encountered: