简体   繁体   中英

MongoDB + SpringData Query very slow

I have this simple class:

@Document (collection = "advertise")
public class AdvertiseCache {
    @Id
    private int id;

    private int brandId;
    private String brandName;
    private String modelName;

    @Indexed
    private int odometer;

    @Indexed
    private int price;
    private boolean learner;
    private int manufacturedYear;
    private double engineSize;
    private String transmissionTypeName;
    private String stateName;
    private String ownerTypeName; //private/dealer
    private String conditionTypeName; //new/used
}

I have another class with same attributes but annotated with @Entity.

They are stored in MongoDB and respectively in PostgreSQL.

I am using Spring Data JPA for PostgreSQL and Spring Data MongoDB ... for mongo.

Both databases contain same data, 30 rows.

  • 10000 queries of type findAll will cost: Mongo ~8000-9000ms and PostgreSQL ~10000-11000ms

  • 10000 queries of type findAll where price >= 1 and price <=9000 and odometer >=1 and odometer <= 40000 will cost: Mongo: ~7000ms and PostgreSQL ~7200ms

WHY? Am I doing something wrong? I was expecting mongo much faster. (I my application rarely I am using just find all. Most of the times I use filters for sorting)

Both servers are running in a FreeBSD 9 virtual machine. I tested this on another VM with CentOS 6.3. Similar results +-100ms.

Tnx

/// more code for explanations (my filter builder will contain only odometerMin, odometerMax for between criteria and priceMin and priceMax for between criteria:

public List<AdvertiseCache> findByFilter(FilterBuilder filter) {
    List<AdvertiseCache> result = null;
    Query query = new Query();
    Criteria criteria = new Criteria();
    criteria = criteria.and("price").gte(filter.getPriceMin()).lte(filter.getPriceMax());
    criteria = criteria.and("odometer").gte(filter.getOdometerMin()).lte(filter.getOdometerMax()); 
    query.addCriteria(criteria);
    query.limit(filter.getLimit());
    query.skip(filter.getOffset());
    result = mongoTemplate.find(query, AdvertiseCache.class, collectionName);
    return result;
}

I am not sure I get the frustration here. Or to be more precise: what do you think is too slow / should be faster? If I read your data points correctly you're still under 1ms per executed query.

You might wanna improve your test scenario a bit:

  1. Your data model is rather simplistic. A collection of primitives doesn't make Mongo shine really. It excels relational databases if you can store aggregates directly instead of joining them together as you would have to with a relational store.

  2. Your access patterns are trivial. findAll(…) is just streaming the data back to the client and is probably quite optimized against a Postgres as well. If you have the indexes set correctly, Postgres and Mongo shouldn't differ too much. Also the simple range queries do not let Mongo excel really. This essentially all boils down to 1. If you get a more complex data model and the JOINs start to pile up in the relational world you'll see the difference.

  3. You read way to little data. 30 rows/documents is simply nothing. To see differences you need to increase the amount of documents / rows to be returned. If you do so, make sure you compare apples to apples: with Spring Data MongoDB you get document-to-object mapping, which you don't get with plain JDBC.

There's two conclusions I'd draw:

  1. Anything but the results you see would be a shocking result for Postgres or the relational approach in general. MongoDB is a great database, but if it exceeded relational in such a simple case (very simple model, very simple queries, very little data), wouldn't that make relational look like toys? They're not. They just have characteristics that make them a sub-optimal choice in some cases but might even perform better in others. Performance is one aspect of the decision. Ease of getting data in and out of the store is another, and so is scalability.

  2. If you're really up to a store comparison, make sure you compare on the right levels of abstraction. For MongoDB this would probably be the raw driver API vs JDBC on the Postgres side. If you bring O(R|D)M into the game you're comparing the store + the mapper framework which might distort the results.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM