我使用GAE NDB Python
方法1:
# both models below have similar properties (same number and type)
class X1(ndb.Model):
p1 = ndb.StringProperty()
::
class X2(ndb.Model):
p1 = ndb.StringProperty()
::
def get(self):
q = self.request.get("q")
w = self.request.get("w")
record_list = []
if (q=="a"):
qry = X1.query(X1.p1==w)
record_list = qry.fetch()
elif (q=="b"):
qry = X2.query(X2.p1==w)
record_list = qry.fetch()
方法2:
class X1(ndb.Model):
p1 = ndb.StringProperty()
::
def get(self):
q = self.request.get("q")
w = self.request.get("w")
if (q=="a"):
k = ndb.Key("type_1", "k1")
elif (q=="b"):
k = ndb.Key("type_2", "k1")
qry = X1.query(ancestor=k, X1.p1==w)
record_list = qry.fetch()
我的问题:
当我扩展实体时,哪种方法在查询性能方面更好
如果我在方法2中将祖先(水平处于相同的层次结构级别)扩展为10,000或1,00,000,那么对查询性能是否会产生重大影响
此应用程序是祖先
的正确用例吗?背景:
这个项目是为了更好地理解GAE,目标是创建像amazon.com这样的电子商务网站,我需要根据很多(10)过滤条件(如价格范围,品牌,屏幕尺寸和等等)。每个过滤条件的范围很小(例如,可能有五个价格区间);可以同时选择多个范围的过滤条件。可以选择多个过滤条件,就像在amazon.com左窗格中一样。
如果我以AND,OR连接表达式的形式将所有过滤条件放在查询中,即使我使用查询光标和逐页获取,也会花费大量时间用于缩放数据集。
为了克服这个问题,我想我会将数据存储在父类作为字符串的实体中。父级将是产品匹配的不同过滤器选项的cancatenation。会有很多冗余,因为我会将相同的数据存储在几个实体中,以满足它所满足的滤波器值的所有组合。这种方法的缺点是每个产品数据在不同的实体中存储多次(更多的存储);但是我希望得到更好的查询性能(< 2秒),因为现在我的查询字符串除了祖先之外只包含一个或两个AND或OR连接元素。祖先将是用户选择搜索产品的过滤条件的串联
如果我不清楚,请告诉我。这只是我尝试的一种实验性方法。另一种方法是通过cron作业定期缓存结果..
任何其他建议,以实现这样一个网站的良好查询性能将是高度赞赏..
更新(新战略):
我决定使用每个类别的每个范围都有一些布尔属性(标志)的模型(每个实体的总属性为~14)..对于一个类别,它有两个可能的值,我有三个模型(一个具有两个值中的任何一个的所有实体,另外两个具有每个值的entites)..因此存在重复(相同的数据可以在两个实体中存储两次)。 我的完整产品数据模型也是一个独立的模型。上面的模型包含了这个完整模型的关键..
我无法取消查询类并编写我自己的过滤(我实际上最初做得很好)..原因是我需要逐页获取结果(~15个结果)..我需要对它们进行排序..如果我获取所有结果并应用我自己的过滤,对于大数据集,由于返回的结果大小,所有结果的获取需要花费大量时间。
初始开发服务器结果看起来不错..查询执行时间对于~6000个匹配的实体来说是<3秒..(虽然我希望它是~1秒)..需要扩展生产数据存储区以在那里测试..
答案 0 :(得分:1)
在上下文定义后编辑:
那里有严格的主题。您有很多可能妨碍您的数据存储限制:
我没有准备好的#34;回答,只是基于常识的一些简单的建议。
在我看来,当你添加新的过滤标准,产品类型等时,你的第一个解决方案会变得过于复杂。
数据存储区的问题,以及大多数&#34; NoSQL&#34;解决方案是,他们倾向于开箱即用的分析/查询功能很少(他们不是已经发展多年的RDBMS的成熟度级别),迫使你手动计算结果&#34;。
对于您的情况,我没有看到任何开箱即用的东西,以及&#34;数据存储区查询引擎&#34;对于此类查询显然是不够的。 保持您的数据非常简单,只需将您的产品存储为具有属性的实体。 如果您有明显不同的产品类别,则可以将它们存储为不同的实体类型 - &gt;我非常怀疑人们会经营一个&#34;品牌&#34;查询&#34;鞋子&#34;和&#34;食物&#34;。
您必须在限制内运行数据存储区查询以快速获取总结果集,并手动优化(映射减少作业,异步任务..)...然后只要您缓存结果可以。
- &GT;从性能,成本和可维护性的角度来看,您的积极缓存解决方案看起来要好得多。
您无法缓存整个产品库,有些稀饭查询需要更长时间......就像我说的,我在这里看不到任何完美的答案,只是性能的不同权衡
只是我的2美分:)我会对你最终采用的解决方案感到好奇。
您通常将祖先用于实体拥有的数据。
例如:
一本书是你的根实体,它拥有&#34;拥有&#34;页面实体。 没有书的页面毫无意义。 本书是佩奇的祖先。
用户是您的根实体,它拥有&#34;拥有&#34; BlogPost实体。 没有Writer的BlogPost是毫无意义的。 用户是BlogPost的祖先。
如果您的两个实体X1和X2共享相同的属性,我会说它们是相同的X实体,只有一个附加的&#34;类型&#34;属性以确定您是否在谈论X Type1或X type2。