我正在考虑让我的所有模型继承自db.Expando类,以便支持松散的非规范化协议,其中db.ReferenceProperty引用的模型的选定属性也将在拥有类上设置。
class ImgModel(db.Expando):
height = db.IntegerProperty()
width = db.IntegerProperty()
url = db.StringProperty()
img_data = db.BlobReferenceProperty()
class company(db.Expando):
logo = db.DenormalizedImgProp(prefix=u'logo')
class DenormalizedImgProp(db.ReferenceProperty):
denorm_attrs = [u'height', u'width', u'url']
def __init__(self,prefix,verbose_name,collection_name,**attrs):
super(DenormalizedImgProp, self).__init__(ImgModel,verbose_name,collection_name,**attrs)
self.denorm_field_prefix = prefix
def __set__(self, model_instance, value):
super(DenormalizedImgProp, self).__set__(model_instance, value)
for attr in self.denorm_attrs:
setattr(model_instance, u'%s_%s' %
(self.denorm_field_prefix, attr),value)
让所有模型继承自Expando类是否有任何性能缺陷?我知道更多的检查是必要的,以解释一些特质,但我真的只是感兴趣,这是否从根本上是可接受的。
答案 0 :(得分:5)
要回答这个标题,使用动态属性的大部分缺点就是失去了属性定义的好处:必须测试对象上some_attribute的存在,不能查询some_attribute未设置的实体,缺少结果来自查询实体上的值与查询中的值具有不同的类型,需要在验证方面花费更多的精力并检查从数据存储中提取的内容...
数据存储区并不关心您是否提供属性类型信息,因此在该级别我不认为存在任何真正的性能影响。
我假设代码最终会按预期工作,并且编写ImgModel和公司等都不会有任何问题。
这让我感到担忧的是你需要注意索引。 Expando可以更轻松地创建大量动态属性,而无需考虑对索引的影响。索引越多,属性值更改时写入对象的时间就越多。需要对具有多个值的多个属性进行排序或不等式过滤的查询越多,获取大量自定义索引就越容易。由于您要自动创建这些动态属性,因此您必须确保少量代码更改不会炸毁索引。
我认为这纯粹是出于理论而难以回答的问题。性能将在很大程度上取决于您实际执行的操作,实现细节以及这些因素如何与平台交互。无论好坏,针对本地应用服务器编写的代码有时会在生产中做出令人惊讶的事情。所以最终如果这是你真正想做的事情,我认为你应该采用一种更简单的方法对其进行部署和基准测试,并自己判断它是否“足够好”。