在GAE NDB Python中使用两个模型并使用一个模型与两个祖先的实体之间的比较(像amazon.com网站一样设计)

时间:2014-03-27 12:04:08

标签: google-app-engine database-design nosql google-cloud-datastore app-engine-ndb

我使用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秒)..需要扩展生产数据存储区以在那里测试..

1 个答案:

答案 0 :(得分:1)

在上下文定义后编辑:

那里有严格的主题。您有很多可能妨碍您的数据存储限制:

  • 写入吞吐量(每个实体组1个写入/秒)
  • 查询不等式过滤器限制
  • 写入时跨实体组事务(在每个事务中复制您的产品) &#34;查询过滤器&#34;特定实体组)
  • 如果您为每个&#34;查询过滤器复制整个产品,则最大实体大小(1MB)&#34;实体

我没有准备好的#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。