我有一个产品数据库,其中包含基于语言代码的每个零件的产品、零件和标签。
我现在遇到的问题是,我还没有找到足够的资源来获取不同的数据集,并将它们合并到一个dict中,以满足我的需求。
数据库中的产品基于一定类型(即颜色、尺寸)的多个部件。每一部分都有每种语言的标签。为此我创建了4个不同的模型。产品、产品部件、产品部件类型和产品部件标签。
我已经把范围缩小到10行代码,这些代码可以拼合起来生成问题。目前我有3种产品,3种类型,每种类型3个部件,2种语言。这个请求需要5500毫秒的求偶时间。
for product in productData:
productDict = {}
typeDict = {}
productDict['productName'] = product.name
cache_key = 'productparts_%s' % (slugify(product.key()))
partData = memcache.get(cache_key)
if not partData:
for type in typeData:
typeDict[type.typeId] = { 'default' : '', 'optional' : [] }
## Start of problem lines ##
for defaultPart in product.defaultPartsData:
for label in labelsForLangCode:
if label.key() in defaultPart.partLabelList:
typeDict[defaultPart.type.typeId]['default'] = label.partLangLabel
for optionalPart in product.optionalPartsData:
for label in labelsForLangCode:
if label.key() in optionalPart.partLabelList:
typeDict[optionalPart.type.typeId]['optional'].append(label.partLangLabel)
## end problem lines ##
memcache.add(cache_key, typeDict, 500)
partData = memcache.get(cache_key)
productDict['parts'] = partData
productList.append(productDict)
我想问题在于for循环的数量太多,必须反复迭代相同的数据。LabelForLangcode从ProductPartLabels获取与当前语言代码匹配的所有标签。
产品的所有部分都存储在db.listproperty(db.key)中。零件的所有标签也是如此。
我需要的原因
一些什么
复杂的dict是我想要显示一个产品的所有数据及其默认部分,并显示可选部分的选择器。
defaultpartsdata和optionapartsdata是产品模型中如下所示的属性:
@property
def defaultPartsData(self):
return ProductParts.gql('WHERE __key__ IN :key', key = self.defaultParts)
@property
def optionalPartsData(self):
return ProductParts.gql('WHERE __key__ IN :key', key = self.optionalParts)
当完成的dict在memcache中时,它可以顺利工作,但是如果应用程序进入休眠状态,memcache是否会重置?此外,我还想为第一次用户显示页面(memcache为空),但没有巨大的延迟。
正如我上面所说,这只是一小部分零件/产品。如果是30件100件的产品,结果会是什么?
是否有一种解决方案可以创建计划任务,以便每小时将其缓存在memcache中?这样有效吗?
我知道这很难接受,但我被困住了。我已经连续12个小时这样做了。无法找到解决方案。
弗雷德里克
编辑:
AppStats屏幕截图
here
.
从我所能看到的信息来看,这些查询在AppStats中是很好的。只需要大约200-400毫秒。这有什么区别呢?
编辑2:
我实现了Dound的解决方案并添加了ABIT。现在看起来是这样的:
langCode = 'en'
typeData = Products.ProductPartTypes.all()
productData = Products.Product.all()
labelsForLangCode = Products.ProductPartLabels.gql('WHERE partLangCode = :langCode', langCode = langCode)
productList = []
label_cache_key = 'productpartslabels_%s' % (slugify(langCode))
labelData = memcache.get(label_cache_key)
if labelData is None:
langDict = {}
for langLabel in labelsForLangCode:
langDict[str(langLabel.key())] = langLabel.partLangLabel
memcache.add(label_cache_key, langDict, 500)
labelData = memcache.get(label_cache_key)
GQL_PARTS_BY_PRODUCT = Products.ProductParts.gql('WHERE products = :1')
for product in productData:
productDict = {}
typeDict = {}
productDict['productName'] = product.name
cache_key = 'productparts_%s' % (slugify(product.key()))
partData = memcache.get(cache_key)
if partData is None:
for type in typeData:
typeDict[type.typeId] = { 'default' : '', 'optional' : [] }
GQL_PARTS_BY_PRODUCT.bind(product)
parts = GQL_PARTS_BY_PRODUCT.fetch(1000)
for part in parts:
for lb in part.partLabelList:
if str(lb) in labelData:
label = labelData[str(lb)]
break
if part.key() in product.defaultParts:
typeDict[part.type.typeId]['default'] = label
elif part.key() in product.optionalParts:
typeDict[part.type.typeId]['optional'].append(label)
memcache.add(cache_key, typeDict, 500)
partData = memcache.get(cache_key)
productDict['parts'] = partData
productList.append(productDict)
结果好多了。我现在有大约3000毫秒的内存缓存和大约700毫秒的内存缓存。
我仍然担心3000毫秒,在本地应用程序开发服务器上,每次重新加载时memcache都会被填满。难道不应该把所有的东西都放进去然后从里面读吗?
最后但同样重要的是,是否有人知道为什么在应用程序开发的生产服务器上,请求需要10倍的时间?
编辑3:
我注意到数据库模型的非索引,这会有区别吗?
编辑4:
在咨询了AppStats(并了解它之后,花了一些时间。大问题在于part.type.typeid,其中part.type是db.referenceproperty。应该以前见过。也许能更好地解释一下:)我会重新考虑那部分。回到你身边。
弗雷德里克