Какова цель объединения всех объектов хранилища данных в одну группу?

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

class BaseModel(ndb.Model):
    @classmethod
    def create(cls, **kwargs):
        return cls(parent=cls.make_key(), **kwargs)
    @classmethod
    def make_key(cls):
        return ndb.Key('Group', cls.key_name())

class Vehicle(BaseModel):
    @classmethod
    def key_name(cls):
        return 'vehicle_group'

В итоге ключи выглядят так:

Key(Group, 'vehicle_group', Vehicle, 5068993417183232)

Нет такого типа, как "Группа" или сущность "vehicle_group", но это нормально в следующих документах: "обратите внимание, что в отличие от файловой системы, родительская сущность фактически не должна существовать".

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

Но если поместить все эти объекты в одну группу, то, по-моему, возникнут проблемы по мере масштабирования проекта, и ограничение записи в секунду будет применяться ко всему виду. Похоже, что нет никаких транзакционных причин для группы.

Никто в проекте не знает, почему это было сделано изначально. Мои вопросы:

  • Кто-нибудь знает, откуда взялась эта схема "xxx_group"?
  • И это так же койка, как кажется?

2 ответа

Решение

Группирование множества сущностей в одной группе сущностей дает по крайней мере два преимущества, о которых я могу подумать:

  • возможность выполнять (предковые) запросы внутри транзакций - запросы без предков (или кросс-групп) не допускаются внутри транзакций
  • возможность доступа ко многим объектам внутри одной транзакции - транзакции между группами ограничены максимум 25 группами объектов

Ограничение 1 запись / секунда / группа может вообще не быть проблемой масштабируемости для некоторых приложений (например, подумайте, что при однократной записи читается много приложений, например, приложений, для которых 1 записи в секунду более чем достаточно).

Что касается механики, то (уникальным) родительским ключом "сущности" для группы является ndb.Key('Group', "xxx_group") ключ (который имеет идентификатор ключа "xxx_group"). Соответствующая "сущность" или ее модель не должны существовать (если только саму сущность не нужно создавать, но это не так). Родительский ключ используется просто для создания "пространства имен" группы в хранилище данных, если хотите.

Вы можете увидеть как-то похожее использование в примерах из документацииEntity Keys, посмотрите Message использовать (кроме Message это просто "родительский" объект в пути предка, но не корневой объект):

Редакция класса (ndb.Model): message_text = ndb.StringProperty ()

ndb.Key('Account', 'sandy@foo.com', 'Message', 123, 'Revision', '1')
ndb.Key('Account', 'sandy@foo.com', 'Message', 123, 'Revision', '2')
ndb.Key('Account', 'larry@foo.com', 'Message', 456, 'Revision', '1')
ndb.Key('Account', 'larry@foo.com', 'Message', 789, 'Revision', '2')

...

Обратите внимание, что Message не является классом модели. Это потому, что мы используем Сообщение исключительно как способ группировки редакций, а не для хранения данных.

Вероятно, это было сделано для достижения строго согласованных запросов внутри группы. Как вы указали, у этого дизайна есть... недостатки.

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

Другие вопросы по тегам