GAE数据存储读取性能

时间:2015-10-21 07:33:07

标签: java performance google-app-engine objectify

我们需要定期处理数以千计的时间序列实体,并且我们在从数据存储区读取大量数据时遇到性能问题,处理过程轻微且不会引起问题。我们创建了一个模拟真实服务器流量的综合测试,我们使用25k权限进行测试。

我们使用Java运行时和Objectify(5.1.1和5.1.8)来访问数据存储区。

实体

@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();
        }
    }
}

查询

query = ofy().load().type(Log.class).
        filter("timestamp >", startDate).
        order("timestamp").
        limit(25000);

我们尝试了不同的实体加载。首先query.list()然后ofy().load().keys(query.keys())所以查找将通过GAE的内存缓存,但结果是相同的。检索25k实体需要大约8秒(通过System.nanoTime()测量)。在query.list()的情况下,该调用本身很快,但对实体的迭代很慢。看起来那个实体是在那个时刻从数据存储区中检索出来的,而不是query.list()中的。所有这些都是F4前端实例上的一个简单的servlet,具有专用的memcache,没有任务。

阅读25k实体只是一个测试,以获得有关我们的服务器实现的性能的一些数字。在实际情况下,我们希望同时读取多达50万个实体,这是否可以在30-60秒内使用GAE的数据存储和专用内存缓存?在两年内,它可能是数百万个实体。

另一个问题是RAM有限,但可通过GAE的托管虚拟机或GCE解决。

问题是使用Objectify从Datastore +专用内存缓存中检索时间序列实体的最快方法。看起来memcache对我们的案例没有帮助Objectify。内存中有数万个Objectify项目,但加载时间与空内存缓存相同。 Objectify / Datastore的最佳实践是批量获取操作,如何实现? Objectify是用我们的实体和查询来做这件事还是我们必须改变一些东西?低级数据存储API可以帮助我们提高阅读性能吗?谢谢。

修改 我们已经在合并日志,因此每个日志实体将保存多个当前日志。这将为我们提供大约10倍的簧片改进,这仍然不足以成千上万的记录。

1 个答案:

答案 0 :(得分:1)

此解决方案不太可能按照您希望的方式扩展。

查询@Cache实体默认为“混合”仅键查询(速度极快),然后是批量获取(相对较慢)。如果缓存很热,这可以很好地执行,但可能不是你所说的规模。最后,即使使用专用的内存缓存,缓存也会被重置 - 然后您的操作可能会超时并失败几次,直到缓存再次预热。

您可以禁用此混合功能:ofy().load().hybrid(false)或仅删除@Cache注释。使用冷缓存时,常规查询的性能会明显提高。您也可以尝试将chunk()尺寸更改为更大的尺寸。默认值小到20。

通过标准API对数据存储区进行托管VM访问(目前)明显慢于经典GAE中的访问。这可能会导致这种规模的问题。

数据存储通常不适合涉及大量实体的批量读取和写入的操作。为此目的,它也往往非常昂贵。您可以考虑将数据存储区用作可靠的“主”副本,并为使用聚簇索引的其他从属数据库中的数据编制索引。或者,根据您的耐久性要求,只需将辅助数据存储区用作主副本。

相关问题