Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongodb read query very slow with Spring Data and fast with Morphia

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;
}


}
like image 834
BkSouX Avatar asked Mar 16 '16 14:03

BkSouX


2 Answers

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.

like image 66
Oliver Drotbohm Avatar answered Nov 19 '22 01:11

Oliver Drotbohm


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 ?

like image 35
BkSouX Avatar answered Nov 19 '22 01:11

BkSouX