Производительность Google App Engine - проверка существования объекта - PullRequest
4 голосов
/ 14 июля 2011

Я кодирую систему, используя Google App Engine, и мне нужно поместить объект в хранилище данных, только если он еще не существует.Я был бы в порядке, используя метод 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;
    }
}

Я склонен использовать второй, так как он кажется более простым, ноЯ обеспокоен тем, что он не может быть использован таким образом, поскольку он вызывает исключение, и это может привести к накладным расходам.

Какой из методов лучше проверить, существует ли сущность в базе данных?

Есть ли лучший способ сделать это?

Ответы [ 2 ]

3 голосов
/ 15 июля 2011

Выполнение get будет быстрее, если ваша сущность невелика и имеет много свойств - в этом случае запрос только по ключам будет быстрее.Если производительность, вероятно, будет существенной проблемой, я бы порекомендовал провести сравнительный анализ для тестирования, но если нет, последний подход более прост.

1 голос
/ 28 сентября 2012

Если для Entity требуется уникальность, даже эта проверка не гарантирует уникальность, если к базе данных одновременно подключено несколько потоков точно .

В этом случаеоба потока увидят, что ничего не существует, и создадут новые объекты одновременно.Даже транзакция не может защитить от этого, поскольку приложение не будет блокировать доступ между read для определения уникальности и write для сохранения сущности.

Я знаю, что это вряд ли звучит, но это определенно произошло с нами, например, когда мы запустили задания MapReduce для обновления / создания большого пакета записей (100k +) более 8 сегментов в пакете.

Единственный способ гарантировать объекты - этоуникальным является указание их ключа 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
...