减少数据库操作时间Django / Mysql

时间:2016-09-14 22:09:20

标签: python mysql django database

所以,问题是我有一个中等大小的电子邮件列表~250,000个条目。

我有另一个表包含无效电子邮件列表~5000,我需要从第一个表中删除(标记为非活动状态)。为此,我运行了一个简单的django函数,每个循环需要3-4秒。代码是:

def clean_list():
    id = 9
    while id<40000:
        i = Invalid.objects.get(id=id)
        y = i.email.strip()
        f = IndiList.objects.get(email__contains=y)
        f.active = False
        f.save()
        id +=1

什么是更好的方法呢?无论是SQL查询还是更好的django代码或其他方式。

帮助!

3 个答案:

答案 0 :(得分:1)

您可能需要了解一些优化措施。不要为每个对象循环获取get,而是尝试获取值列表:

queryset = Invalid.objects.filter(id__range=(9,40000)) queryset_list = queryset.values_list('email' flat=True)

https://docs.djangoproject.com/en/1.10/ref/models/querysets/#values-list

然后循环遍历值列表并在电子邮件上执行.get()。最后你也可以这样做:

f.active = False f.save(update_fields=['active'])

只会更新布尔字段。 https://docs.djangoproject.com/en/1.10/ref/models/instances/#updating-attributes-based-on-existing-fields

如果可能,还尝试通过id或字符串之外的其他字段找到.get()对象的方法。

答案 1 :(得分:1)

未测试:

IndiList.objects.filter(email__in=Invalid.objects.only('email').all()).update(active=False)

我不确定Django是否足够聪明,可以从中构建子查询,如果没有,那么应该这样做:

IndiList.objects.filter(email__in=Invalid.objects.all().values_list('email', flat=True)).update(active=False)

第二种方法的问题是它将生成2个查询而不是一个,并将50,000个ID注入第二个sql查询字符串,所以我更愿意在这一点上使用原始sql:

from django.db import connection

cursor = connection.cursor()
cursor.execute = 'UPDATE indilist SET active=false WHERE email IN (SELECT email FROM invalid)'

答案 2 :(得分:0)

经过几次迭代后,我使用的功能超过 1000倍。

def clean_list3():
    pp = Invalid.objects.filter(id__gte=9)
    listd = [oo.email.strip() for oo in pp]
    for e in IndiList.objects.all():
        if e.email.strip() in listd:
            e.active=False
            e.save()
            print(e.id)

技巧很简单,而不是每次都要点击数据库,我将250,000个对象保存在内存中的查询集中。以及内存中无效列表的电子邮件列表。

然后我不得不在我们找到匹配的电子邮件时才点击数据库,以便将其保存为非活动状态。