如何避免在 Django 循环中多次访问数据库?
How to avoid making multiple trips to database in Django loop?
目前这段代码似乎在每次循环迭代中都要进入数据库 (Postgres) 两到四次。首先获取(并创建)Type
,然后获取(并创建)Component
。有没有一种方法可以减少数据库访问次数?
models.py
:
class Component(models.Model):
long = models.TextField()
type = models.SmallForeignKey('Type', models.CASCADE)
class Type(models.Model):
type = models.TextField(unique=True)
class Point(models.Model):
components = models.ArrayField(models.IntegerField(), default=[])
def save_components(self, geocode):
_components = []
for c in geocode:
ct = Type.objects.get_or_create(type=c['types'][0])
_components.append(Component.objects.get_or_create(long=c['long_name'], type=ct).pk)
self.components = _components
self.save()
传入数据:
geocode = [
{
"long_name" : "Luray",
"types" : [ "locality", "political" ]
},
{
"long_name" : "Page County",
"types" : [ "administrative_area_level_2", "political" ]
},
{
"long_name" : "Virginia",
"types" : [ "administrative_area_level_1", "political" ]
},
{
"long_name" : "United States",
"types" : [ "country", "political" ]
}
]
很多时候,Django 在缓存数据库结果方面做得不错。如果你想有更多的控制权,你可以这样做(前提是你没有太多类型)
class Point(models.Model):
components = models.ArrayField(models.IntegerField(), default=[])
def save_components(self, geocode):
_components = []
_types = {t.type: t for t in Type.objects.all()}
for c in geocode:
ct = _types.get(c['types'][0], None)
if not ct:
ct = Type.objects.create(type=c['types'][0])
_components.append(Component.objects.get_or_create(long=c['long_name'], type=ct).pk)
self.components = _components
self.save()
这应该可以避免您一直查找现有类型。您还可以尝试推迟创建新类型和新组件(使用 get() 而不是 get_or_create() 并捕获 DoesNotExist 异常)并稍后在函数中使用批量插入(这里是 doc link)
目前这段代码似乎在每次循环迭代中都要进入数据库 (Postgres) 两到四次。首先获取(并创建)Type
,然后获取(并创建)Component
。有没有一种方法可以减少数据库访问次数?
models.py
:
class Component(models.Model):
long = models.TextField()
type = models.SmallForeignKey('Type', models.CASCADE)
class Type(models.Model):
type = models.TextField(unique=True)
class Point(models.Model):
components = models.ArrayField(models.IntegerField(), default=[])
def save_components(self, geocode):
_components = []
for c in geocode:
ct = Type.objects.get_or_create(type=c['types'][0])
_components.append(Component.objects.get_or_create(long=c['long_name'], type=ct).pk)
self.components = _components
self.save()
传入数据:
geocode = [
{
"long_name" : "Luray",
"types" : [ "locality", "political" ]
},
{
"long_name" : "Page County",
"types" : [ "administrative_area_level_2", "political" ]
},
{
"long_name" : "Virginia",
"types" : [ "administrative_area_level_1", "political" ]
},
{
"long_name" : "United States",
"types" : [ "country", "political" ]
}
]
很多时候,Django 在缓存数据库结果方面做得不错。如果你想有更多的控制权,你可以这样做(前提是你没有太多类型)
class Point(models.Model): components = models.ArrayField(models.IntegerField(), default=[]) def save_components(self, geocode): _components = [] _types = {t.type: t for t in Type.objects.all()} for c in geocode: ct = _types.get(c['types'][0], None) if not ct: ct = Type.objects.create(type=c['types'][0]) _components.append(Component.objects.get_or_create(long=c['long_name'], type=ct).pk) self.components = _components self.save()
这应该可以避免您一直查找现有类型。您还可以尝试推迟创建新类型和新组件(使用 get() 而不是 get_or_create() 并捕获 DoesNotExist 异常)并稍后在函数中使用批量插入(这里是 doc link)