貌似没必要分离不常修改的大实体

标签:Google App Engine, Python

最近在做一个网站,用到了投票机制。

最初的打算是将计分信息和描述信息分成2个模型,前者作为后者的父实体,大致如下:
class A(db.Model):
  point = db.FloatProperty(default=0.0)
  vote = db.IntegerProperty(default=0)
  hot = db.FloatProperty(default=0.0)
  story = db.FloatProperty(default=0.0)
  cg = db.FloatProperty(default=0.0)
  role = db.FloatProperty(default=0.0)
  sys = db.FloatProperty(default=0.0)
  music = db.FloatProperty(default=0.0)
  comment = db.IntegerProperty(default=0)
  active = db.BooleanProperty(default=False)

class B(db.Model):
  name = db.StringProperty(required=True)
  names = db.StringListProperty()
  intro = db.TextProperty(required=True)
  pic = db.StringProperty(indexed=False)
  active = db.BooleanProperty(default=False)
  time = db.DateTimeProperty(auto_now_add=True)
这样我查询时就可以对B的names字段进行查询,获取一个key,再拿到这个key的parent,再获取A。而在更新A时,由于无需处理StringListProperty和TextProperty,所以保存速度应该是比较快的。

于是我做了个测试:
t = time()
b = B.all(keys_only=True).filter('names =', 'air').filter('active =', True).get()
t1 = time()
a = A.get(b.parent())
t2 = time()
a.point += 1.0
a.story += 1.0
a.cg += 1.0
a.role += 1.0
a.sys += 1.0
a.music += 1.0
a.vote += 1
a.hot = (a.point * .5 + a.story * .2 + a.cg * .1 + a.role * .05 + a.sys * .05 + a.music * .1) / a.vote + math.log(a.vote)
t3 = time()
a.put()
t4 = time()

print t1-t
print t2-t1
print t3-t2
print t4-t3
print t4-t
测了多次,去掉明显偏大的结果,大致如下:
0.014~0.019
0.008~0.012
0.0001
0.031~0.044
0.061~0.072
而如果是使用一个模型:
class C(db.Model):
  point = db.FloatProperty(default=0.0)
  vote = db.IntegerProperty(default=0)
  hot = db.FloatProperty(default=0.0)
  story = db.FloatProperty(default=0.0)
  cg = db.FloatProperty(default=0.0)
  role = db.FloatProperty(default=0.0)
  sys = db.FloatProperty(default=0.0)
  music = db.FloatProperty(default=0.0)
  comment = db.IntegerProperty(default=0)
  active = db.BooleanProperty(default=False)
  name = db.StringProperty(required=True)
  names = db.StringListProperty()
  intro = db.TextProperty(required=True)
  pic = db.StringProperty(indexed=False)
  time = db.DateTimeProperty(auto_now_add=True)
这样获取时就直接对C进行查询,不需要多余的get。
接着测试了一下性能:
t = time()
c = C.all().filter('names =', 'air').filter('active =', True).get()
t1 = time()
c.point += 1.0
c.story += 1.0
c.cg += 1.0
c.role += 1.0
c.sys += 1.0
c.music += 1.0
c.vote += 1
c.hot = (c.point * .5 + c.story * .2 + c.cg * .1 + c.role * .05 + c.sys * .05 + c.music * .1) / c.vote + math.log(c.vote)
t2 = time()
c.put()
t3 = time()

print t1-t
print t2-t1
print t3-t2
print t3-t
结果:
0.015~0.018
0.0001
0.037~0.051
0.053~0.069
可以看到查询基本相等,在get处节省了0.01秒,put则多用了0.007秒。而由于查看的次数是远大于投票的次数的,所以不拆分会获得更好的性能。

3条评论 你不来一发么↓ 顺序排列 倒序排列

    向下滚动可载入更多评论,或者点这里禁止自动加载

    想说点什么呢?