4

我正在編寫一個系統使用谷歌應用程序引擎,我需要把一個對象,只有當它不存在數據存儲。我會很好地使用datastore.put()方法,除了我需要知道該對象是否已經存在以計算我擁有的新對象的數量。谷歌應用程序引擎性能 - 檢查對象的存在

據我知道,我有以下幾種選擇(假設我有鑰匙都爲屬性和實體鍵):

private Entity getEntity(String key) 
{ 
    DatastoreService datastore = 
     DatastoreServiceFactory.getDatastoreService(); 

    // Build a query to select this entity from the database: 
    Query q = new Query("MyEntity"); 
    q.setKeysOnly(); 
    // Add a filter for the key attribute: 
    q.addFilter("key", Query.FilterOperator.EQUAL, key); 
    PreparedQuery pq = datastore.prepare(q); 
    // Select a single entity from the database 
    // (there should be no more than one matching row anyway): 
    List<Entity> list = pq.asList(FetchOptions.Builder.withLimit(1)); 

    if (!list.isEmpty()) 
     // Return the found entity: 
     return list.get(0); 
    else 
     return null; 
} 

private Entity getEntity(String key) 
{ 
DatastoreService datastore = 
    DatastoreServiceFactory.getDatastoreService(); 

    // Get a key that matches this entity: 
    Key key = KeyFactory.createKey("MyEntity", key); 

    try { 
     return datastore.get(key); 
    } catch (EntityNotFoundException e) { 
     // Entity does not exist in DB: 
     return null; 
    } 
} 

我傾向於使用第二個,因爲它看起來更直截了當,但我擔心它可能並不意味着以這種方式使用,因爲它引發了一個例外,並且可能會產生開銷。

哪種方法更適合檢查數據庫中是否存在實體?

有沒有更好的方法來做到這一點?

回答

3

做一個get會更快,除非你的實體很大並且有很多屬性 - 在這種情況下,只有鍵的查詢可能會更快。如果性能可能是一個重要的問題,我會建議基準測試 - 但如果不是,後一種方法更直接。

+0

感謝。您能否提供一些有關通用最佳實踐的參考,性能方面?我找不到很多有關不同方式執行相同操作的性能影響的信息(asList vs asterable,get vs query,批量放置vs多個放置等)。 –

+0

@Yanir簡而言之,更少的RPC總是更好。嘗試使用Appstats並對您懷疑的任何事情進行基準測試。 –

1

如果需要爲Entity獨特性,即使該檢查將不保證唯一性,如果有多個線程確切同時訪問數據庫。

在這種情況下,兩個線程都看不到任何東西,並同時創建新的對象。即使事務處理也不能防止發生這種情況,因爲應用程序不會阻止用於確定唯一性的read和用於保存實體的write之間的訪問。

我知道這聽起來不太可能,但是這肯定是發生在我們身上的,例如當我們運行MapReduce作業來批量更新/創建8批以上的大批記錄(100k +)時。

保證對象唯一的唯一方法是指定其密鑰的name屬性。這將使數據存儲create成爲一個新實體(如果不存在的話),否則它將update實體返回到最後保存的對象。

因此,而不是:

Entity entity = new Entity("MyKind"); 

這確保只有一個獨特的每個實體,所述的特性:

String myPropertyValue = getPropValue(); 
Entity entity = new Entity("MyKind", myPropertyValue); 
ds.put(entity); // Ensures only one Entity per this property value