使用 Django 将列表的每个元素与数据库中的每个元素进行比较的优化
Optimization for comparing every element of a list to every element in database using Django
我正在 Django 1.10 中开发一个项目,我的一个应用程序要求我导入一个包含 500-100,000 个 IP 地址的列表,然后比较这 500-100,000 个IP 地址到存储在我的 SQLite3 数据库中的 ~25,000+ 个 IP 地址。不幸的是,这需要相当长的时间,这是我非常需要减少的。
我的数据库包含一个 Host
table 和一个名为 ipv4_address
.
的字段
这是相关的model.py:
class Host(models.Model):
ipv4_address = models.GenericIPAddressField(protocol='ipv4', default='0.0.0.0', unique=True)
这里是相关的 views.py:
bad_ips = []
read_bad_ips = [ '500', 'to', '100000', 'ips', 'here', '...' ]
for ip in read_bad_ips:
if Host.objects.filter(ipv4_address=ip).exists():
bad_ips.append(Host.objects.get(ipv4_address=ip))
其中 read_bad_ips
是 IP 地址列表,bad_ips
是我想要的存在于数据库 和 read_bad_ips
列表。
从 views.py 优化这段代码的最佳方法是什么?
谢谢!
编辑:@nik_m的解决方案解决了这场危机!
read_bad_ips = [ '500', 'to', '100000', 'ips', 'here', '...' ]
addresses = Host.objects.values_list('ipv4_address', flat=True)
bad_ips = list(set(read_bad_ips).intersection(addresses))
你可以这样做:
bad_ips = Host.objects.filter(ipv4_address__in=read_bad_ips).values_list('ipv4_address', flat=True)
这将为您提供 read_bad_ips
列表中 ipv4_address
值的列表(可能是空的,可能不是)。
[编辑]:
由于您使用的是 sqlite 数据库并且此数据库有其局限性(由于您拥有大量值),您可以试试这个:
for addr in Host.objects.values_list('ipv4_address', flat=True).iterator():
if addr in read_bad_ips:
bad_ips.append(addr)
[编辑 2]:
尝试使用 set
的 intersection
方法,如下所示:
read_bad_ips = [ '500', 'to', '100000', 'ips', 'here', '...' ]
addresses = Host.objects.values_list('ipv4_address', flat=True)
bad_ips = list(set(read_bad_ips).intersection(addresses))
我正在 Django 1.10 中开发一个项目,我的一个应用程序要求我导入一个包含 500-100,000 个 IP 地址的列表,然后比较这 500-100,000 个IP 地址到存储在我的 SQLite3 数据库中的 ~25,000+ 个 IP 地址。不幸的是,这需要相当长的时间,这是我非常需要减少的。
我的数据库包含一个 Host
table 和一个名为 ipv4_address
.
这是相关的model.py:
class Host(models.Model):
ipv4_address = models.GenericIPAddressField(protocol='ipv4', default='0.0.0.0', unique=True)
这里是相关的 views.py:
bad_ips = []
read_bad_ips = [ '500', 'to', '100000', 'ips', 'here', '...' ]
for ip in read_bad_ips:
if Host.objects.filter(ipv4_address=ip).exists():
bad_ips.append(Host.objects.get(ipv4_address=ip))
其中 read_bad_ips
是 IP 地址列表,bad_ips
是我想要的存在于数据库 和 read_bad_ips
列表。
从 views.py 优化这段代码的最佳方法是什么?
谢谢!
编辑:@nik_m的解决方案解决了这场危机!
read_bad_ips = [ '500', 'to', '100000', 'ips', 'here', '...' ]
addresses = Host.objects.values_list('ipv4_address', flat=True)
bad_ips = list(set(read_bad_ips).intersection(addresses))
你可以这样做:
bad_ips = Host.objects.filter(ipv4_address__in=read_bad_ips).values_list('ipv4_address', flat=True)
这将为您提供 read_bad_ips
列表中 ipv4_address
值的列表(可能是空的,可能不是)。
[编辑]: 由于您使用的是 sqlite 数据库并且此数据库有其局限性(由于您拥有大量值),您可以试试这个:
for addr in Host.objects.values_list('ipv4_address', flat=True).iterator():
if addr in read_bad_ips:
bad_ips.append(addr)
[编辑 2]:
尝试使用 set
的 intersection
方法,如下所示:
read_bad_ips = [ '500', 'to', '100000', 'ips', 'here', '...' ]
addresses = Host.objects.values_list('ipv4_address', flat=True)
bad_ips = list(set(read_bad_ips).intersection(addresses))