我目前正在从Firebase获取一个数据快照,如下所示:
public Task<DataSnapshot> getLatestMessage(@NonNull String roomId) {
final TaskCompletionSource<DataSnapshot> source = new TaskCompletionSource<>();
DatabaseReference dbRef = mDatabase.getReference(NODE_MESSAGES).child(roomId);
dbRef.keepSynced(true);
ValueEventListener listener = new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
source.setResult(dataSnapshot);
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
source.setException(databaseError.toException());
}
};
Query query = dbRef.orderByKey().limitToLast(1);
query.addListenerForSingleValueEvent(listener);
return source.getTask();
}
注意,我已经在
keepSynced()
对象上调用了dbRef
。下面是示例数据结构:
/root
/messages
/$roomId
/$messageId
/content
/timestamp
/etc...
我可以按预期获得最新的单个快照数据,但我想知道,如果我在
keepSynced()
对象中移动Query
调用而不是DatabaseReference
,会有什么不同吗?即 // dbRef.keepSynced(true); >> REMOVE THIS <<
ValueEventListener listener = new ValueEventListener() {...};
Query query = dbRef.orderByKey().limitToLast(1);
query.keepSynced(true); // >> ADD THIS <<
query.addListenerForSingleValueEvent(listener);
我们目前平均每天50%的负载在firebase上,随着用户的不断涌入,我想知道它是否能以某种方式改进应用程序中的任何东西,特别是负载。我甚至试过这么愚蠢的事情:
dbRef.keepSynced(true);
ValueEventListener listener = new ValueEventListener() {...};
Query query = dbRef.orderByKey().limitToLast(1);
query.addListenerForSingleValueEvent(listener);
dbRef.keepSynced(false);
--在开始时启用
keepSynced()
以确保引用指向最新版本,然后在查询和添加侦听器后禁用它。不幸的是,这并没有提供新的数据,不像保持启用时那样。我已经通过了Optimization DB Performance documentation并且相信我按照需要遵循了建议的实践。
最佳答案
对查询执行keepSynced()
调用不会对数据库服务器上的负载产生任何影响。服务器需要加载完全相同的数据并对其进行监视,它只需将最后一项返回给客户端。
我建议您在应用程序中谨慎使用limitToLast()
。对keepSynced
的每次调用都会将一个空侦听器保存到您附加到它的引用/查询。这意味着,即使用户不看聊天室,每个客户机都有一个活跃的监听器。虽然这可能正是对应用程序用例的正确调用,但它将限制应用程序的可伸缩性。
如果您担心达到峰值负载,您可能需要考虑如何shard your data over multiple databases。聊天应用程序通常比较容易分片,因为每个聊天室都已经是独立的。