Какова цель объединения всех объектов хранилища данных в одну группу?
Я начал работать над существующим проектом, в котором используется 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 не является классом модели. Это потому, что мы используем Сообщение исключительно как способ группировки редакций, а не для хранения данных.
Вероятно, это было сделано для достижения строго согласованных запросов внутри группы. Как вы указали, у этого дизайна есть... недостатки.
Если это исключительно справочные данные (т. Е. Чтение много раз записывается), которые могут смягчить некоторые из негативов, но также в основном делают недействительными позитивы (т.е. возможная согласованность не является проблемой, если данные не обновляются часто).