I would like to convert my project from Morphia to Spring Data but some basics query are very slow with Spring Data.
For example:
@Override
public List<PTDefaultBlacklistContact> findByBlacklistId(ObjectId defaultBlacklistId, int limit, int offset, String sortBy) {
Query query = Query.query(Criteria.where("blacklistId").is(defaultBlacklistId));
if (limit != 0)
query.limit(limit);
if (offset != 0)
query.skip(offset);
if (StringUtils.hasLength(sortBy))
query.with(new Sort(sortBy));
log.debug("findByBlacklistId query={}", query);
return mongoOperations.find(query, PTDefaultBlacklistContact.class);
}
takes ~2 minutes
And with Morphia
@Override
public List<PTDefaultBlacklistContact> findByBlacklistId(ObjectId defaultBlacklistId, int limit, int offset, String sortBy) {
Query<PTDefaultBlacklistContact> q = createQuery().disableValidation().filter("blacklistId", defaultBlacklistId).limit(limit)
.offset(offset);
if (StringUtils.hasLength(sortBy)) {
q.order(sortBy);
}
return q.asList();
}
It takes ~5 seconds.
My configuration is basic so it is quiet weird to understand. I juste have this in my application.yml and there is the spring boot mongodb auto configuration.
spring.data.mongodb.uri: mongodb://serv1,serv2,serv3/${mongodb.database}
Any idea ? I am wondering if the cause could be the events of the lifecycle.
Thank you
edit:
Models:
PTDefaultBlacklistContact
@Document(collection = "PTDefaultBlacklistContact")
public class PTDefaultBlacklistContact extends PTModel {
private static final long serialVersionUID = 1L;
@Deprecated
@DBRef
protected PTDefaultBlacklist blacklist;
private String identifier;
@Indexed
private ObjectId blacklistId;
private List<PTHistory> history;
public PTDefaultBlacklistContact() {
}
@Override
public int hashCode() {
int prime = 31;
int result = 1;
result = prime * result + ((blacklistId == null) ? 0 : blacklistId.hashCode());
result = prime * result + ((identifier == null) ? 0 : identifier.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (getClass() != obj.getClass()) {
return false;
}
PTDefaultBlacklistContact other = (PTDefaultBlacklistContact) obj;
if (blacklistId == null) {
if (other.blacklistId != null) {
return false;
}
} else if (!blacklistId.equals(other.blacklistId)) {
return false;
}
if (identifier == null) {
if (other.identifier != null) {
return false;
}
} else if (!identifier.equals(other.identifier)) {
return false;
}
return true;
}
@Override
public String toString() {
return "PTDefaultBlacklistContact{" +
"identifier='" + identifier + '\'' +
", blacklistId=" + blacklistId +
'}';
}
public List<PTHistory> getHistory() {
return history;
}
public void setHistory(List<PTHistory> history) {
this.history = history;
}
public String getIdentifier() {
return identifier;
}
public void setIdentifier(String identifier) {
this.identifier = identifier;
}
@Deprecated
public PTDefaultBlacklist getBlacklist() {
return blacklist;
}
@Deprecated
public void setBlacklist(PTDefaultBlacklist blacklist) {
this.blacklist = blacklist;
}
public ObjectId getBlacklistId() {
if (blacklist != null) {
blacklistId = blacklist.getId();
}
return blacklistId;
}
public void setBlacklistId(ObjectId blacklistId) {
this.blacklistId = blacklistId;
}
}
PTHistory
public class PTHistory {
private Long date;
@DBRef
private PTCampaign campaign;
public Long getDate() {
return date;
}
public void setDate(Long date) {
this.date = date;
}
public PTCampaign getCampaign() {
return campaign;
}
public void setCampaign(PTCampaign campaign) {
this.campaign = campaign;
}
}
With your DBRef configuration above, you'll get all of them resolved eagerly by default with Spring Data. That will result in additional queries issued for every DBRef encountered when reading a document.
We usually recommend using @DBRef(lazy = true)
to avoid those calls and rather only read them once they get accessed.
Thanks to Blakes Seven, here is my investigation with some tests for the same collection. I just added or removed references.
With Morphia with references:
% Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 1472k 0 1472k 0 0 1970k 0 --:--:-- --:--:-- --:--:-- 1968k
real 0m0.752s user 0m0.008s sys 0m0.000s
With Morphia without references:
% Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 1472k 0 1472k 0 0 3022k 0 --:--:-- --:--:-- --:--:-- 3016k
real 0m0.492s user 0m0.012s sys 0m0.000s
With Spring Data with references:
% Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 1472k 0 1472k 0 0 96901 0 --:--:-- 0:00:15 --:--:-- 338k
real 0m15.567s user 0m0.008s sys 0m0.004s
With Spring Data with LAZY references:
% Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 1472k 0 1472k 0 0 703k 0 --:--:-- 0:00:02 --:--:-- 703k
real 0m2.111s user 0m0.016s sys 0m0.000s
With Spring Data without references:
% Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 1472k 0 1472k 0 0 887k 0 --:--:-- 0:00:01 --:--:-- 887k
real 0m1.722s user 0m0.008s sys 0m0.012s
I really don't understand why this is so fast with Morphia without using lazy references. Or so slow with Spring Data with references. Someone have an idea ?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With