GAE数据库查询对象创建性能测试:Query vs GqlQuery

标签:Google App Engine, Python, 性能

Google App Engine的数据库查询对象有Query和GqlQuery这2种类型,其创建方式完全不同。粗略看上去,GqlQuery的分析量更大,需要消耗更多的CPU时间;不过有bind方法,使其可以重复使用。

以下是我在自己电脑上5次创建的测试结果:
Query:        0.000270984161489
GqlQuery:    0.00831642010371
GqlQueryBind:    0.000697854056853
GqlQueryBind2:    0.00072104136143
这是10000次创建的测试结果:
Query:        0.598677764911
GqlQuery:    7.09144402431
GqlQueryBind:    0.0869479221521
GqlQueryBind2:    0.087524252384
可见如果只是临时用用,对于同一个查询类型不使用超过20次的话,使用Query类型是很不错的。
而如果经常使用同一个查询类型,只是改改查询参数,则使用GqlQuery的bind方法也是不错的。不过要注意GqlQuery还存在着GQL注入的危险,因此必须小心验证参数。

以下是测试脚本:
from time import clock
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db

class TestModel(db.Model):
    field1 = db.StringProperty()
    field2 = db.IntegerProperty()
    field3 = db.IntegerProperty()
    field4 = db.StringProperty()

    @classmethod
    def testQuery(cls, times):
        t = clock()
        for i in xrange(times):
            TestModel.all().filter('field1 > ', 'a').filter('field1 < ', 'z').filter('field2 = ', 0).filter('field3 = ', 0).order('-field1').order('field4')
        return clock() - t

    @classmethod
    def testGqlQuery(cls, times):
        t = clock()
        for i in xrange(times):
            TestModel.gql('WHERE field1 > :1 AND field1 < :2 AND field2 = :3 AND field3 = :4 ORDER BY field1 DESC, field4 ASC', 'a', 'z', 0, 0)
        return clock() - t

    @classmethod
    def testGqlQueryBind(cls, times):
        t = clock()
        query = TestModel.gql('WHERE field1 > :1 AND field1 < :2 AND field2 = :3 AND field3 = :4 ORDER BY field1 DESC, field4 ASC', 'a', 'z', 0, 0)
        for i in xrange(times - 1):
            query.bind('a', 'z', 0, 0)
        return clock() - t

    @classmethod
    def testGqlQueryBind2(cls, times):
        t = clock()
        query = TestModel.gql('WHERE field1 > :1 AND field1 < :2 AND field2 = :3 AND field3 = :4 ORDER BY field1 DESC, field4 ASC')
        for i in xrange(times):
            query.bind('a', 'z', 0, 0)
        return clock() - t

class MainPage(webapp.RequestHandler):
    def get(self):
        times = 10000
        self.response.headers['Content-Type'] = 'text/plain; charset=utf-8'
        self.response.out.write('Query:\t\t%s\n' % TestModel.testQuery(times))
        self.response.out.write('GqlQuery:\t%s\n' % TestModel.testGqlQuery(times))
        self.response.out.write('GqlQueryBind:\t%s\n' % TestModel.testGqlQueryBind(times))
        self.response.out.write('GqlQueryBind2:\t%s' % TestModel.testGqlQueryBind2(times))

application = webapp.WSGIApplication([('/', MainPage)], debug=False)

def main():
    run_wsgi_app(application)

if __name__ == "__main__":
    main()

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

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

    想说点什么呢?