我正在优化我们(第一个)Django项目中的慢页面加载。整个项目确实测试状态管理,因此存在具有计划执行的案例的协议。目前代码是:
protocols = Protocol.active.filter(team=team, release=release)
cases = Case.active.filter(protocol__in=protocols)
caseCount = cases.count()
plannedExecs = Planned_Exec.active.filter(case__in=cases, team=team, release=release)
# Start aggregating test suite information
# pgi Model
testSuite['pgi_model'] = []
for pgi in PLM.objects.filter(release=release).values('pgi_model').distinct():
plmForPgi = PLM.objects.filter(pgi_model=pgi['pgi_model'])
peresults = plannedExecs.filter(plm__in=plmForPgi).count()
if peresults > 0:
try:
testSuite['pgi_model'].append((pgi['pgi_model'], "", "", peresults, int(peresults/float(testlistCount)*100)))
except ZeroDivisionError:
testSuite['pgi_model'].append((pgi['pgi_model'], "", "", peresults, 0))
# Browser
testSuite['browser'] = []
for browser in BROWSER_OPTIONS:
peresults = plannedExecs.filter(browser=browser[0]).count()
try:
testSuite['browser'].append((browser[1], "", "", peresults, int(peresults/float(testlistCount)*100)))
except ZeroDivisionError:
testSuite['browser'].append((browser[1], "", "", peresults, 0))
# ... more different categories are aggregated below, then the report is generated...
这段代码制作了很多SQL语句。 PLM.objects.filter(release=release).values('pgi_model').distinct()
返回50个字符串的列表,两个过滤操作都为每个字符串执行一条SQL语句,这意味着只有100个SQL语句用于循环。 (此外,似乎应将values_list
与flat=True
一起使用。)
由于我想获取有关相关案例和计划执行的信息,我认为我真的只需要检索这两个表,然后对此进行一些分析。使用filter和count()似乎是当时显而易见的解决方案,但我想知道我是不是更好的只是使用.values()构建相关案例的dict和计划执行信息,然后分析它,所以为了避免不必要的SQL语句。任何有用的建议?谢谢!
编辑:在尝试对此进行分析以了解时间的变化时,我正在使用Django Debug工具栏。它解释说有超过200个查询,每个查询都运行得非常快,因此整体而言它们占用的时间非常短。但是,可能是SQL的执行速度相对较快,但是ORM的构建会增加,因为它发生了200多次?我重构了一个前一页,加载了3分钟,并使用了values()而不是ORM,从而使页面加载时间减少到2.7秒和5个SQL语句。
答案 0 :(得分:1)
创建查询集不会访问数据库;只访问它的结果。因此,仅创建查询集不是您的问题。
请注意,将查询集传递到另一个查询集不会创建两个查询。因此,构建dicts不会减少数据库命中数。
如果你可以构建dicts,那么你可能会创建一个比其他方式更简单的查询,这将加快实际的查询执行速度。然而,这是一个单独的问题。
答案 1 :(得分:1)
这反映了我作为反向外键查找的情况。我们应该能够通过在发布中获取与PLM相关联的所有pgi_model来减少top for循环。我假设你有一个PGI模型,PLM模型有一个名为pgi_model的外键字段。如果是这种情况,您可以使用以下内容在PLM版本中找到PGI。你仍然有一个循环,但理论上应该减少循环的迭代:
pgis = PGI.objects.filter(plm__in=PLM.objects.filter(release=release))
for pgi in pgis:
peresults = plannedExecs.filter(plm=pgi.plm).count()
if peresults > 0:
try:
testSuite['pgi_model'].append((pgi['pgi_model'], "", "", peresults, int(peresults/float(testlistCount)*100)))
except ZeroDivisionError:
testSuite['pgi_model'].append((pgi['pgi_model'], "", "", peresults, 0))