We neeed to process thousands of timeseries entities regularly and we have performance issues reading that much data from the Datastore, the processins is computationaly light and does not cause issues. We created a synthetic test simulating real server traffic where we test with 25k entitites.
We use the Java runtime and Objectify (5.1.1 and 5.1.8) to access the Datastore.
The entity
@Entity(name="logs")
@Cache
public class Log {
@Id
public Long id;
@Index
public Ref<User> user;
public String deviceId;
public String nonce;
public String version;
public String data;
@Index
public Date timestamp;
@OnSave
private void prePersist() {
if (timestamp == null) {
timestamp = new Date();
}
}
}
The query
query = ofy().load().type(Log.class).
filter("timestamp >", startDate).
order("timestamp").
limit(25000);
We tried different loading of the entities. First query.list() then ofy().load().keys(query.keys()) so the look-up will go through GAE's memcache, but the results are the same. Retrieving 25k entities takes alaways around 8 seconds (measured via System.nanoTime()). In the case of query.list(), that call itself is fast but iterating over the entities is slow. Looks like that the entity is retrieved from the Datastore in that very moment and not in query.list(). All this is a simple servlet on an F4 frontend instance with dedicated memcache, no task.
Reading 25k entities is just a test to get some numbers about our server implementation's performance. In real worl we expect to read up to 500k entities at once, is this doable under 30-60 seconds with GAE's Datastore and dedicated memcache? In 2 years it could be millions of entities.
Another issue is limited RAM, but that is solvable via GAE's Managed VMs or GCE.
The questions is what is the fastest way to retrieve timeseries entities from the Datastore + dedicated memcache with Objectify. Looks like the memcache does not help Objectify in our case. The memcache has tens of thousands of Objectify items inside but the loading time is the same as with empty memcache. Objectify's/Datastore's best practices is to make batch get operations, how to achieve that? Is Objectify doing this under the hood with our entity and query or do we have to change something? Can the low-level Datastore API help us improve reading performance? Thank you.
EDIT We are already working on merging the logs so every log entity will hold multiple current logs. That will give us around 10x reed improvement, which is still not enough for hundreds of thousands of records.
userandtimestampwhich is not good because there are hundreds of thousands of logs. - shelll