Reputation: 2591
Trying to speed up the performance of my app, and post some analysis with debug toolbar I can see I am doing 68 queries.
I query the circuits for every showroom (68 of), I thought if I just query the circuits once, could I then requery the existing query instead of calling the DB again for each Circuit?
something like adding:
crData = Circuits.objects.only('circuit_preference','site_data__id')
then how to query crData again? to match each statement?
Current code below
# get shworoom data
srData = SiteData.objects.only('location','subnet').filter(is_live=True).exclude(site_type='Major Site')
for sr in srData:
site = SiteType()
site.type = checkRoute(sr.subnet)
site.location = sr.location
if 'MPLS' in site.type:
mpls = site.type.split('-')
try:
d = Circuits.objects.only('circuit_preference','site_data').filter(site_data__id=sr.id,provider=mpls[0],circuit_type__icontains=mpls[1])
site.preference = d[0].circuit_preference
except:
pass
elif site.type == '4G':
try:
d = Circuits.objects.only('circuit_preference','site_data').filter(site_data__id=sr.id,provider='EE',circuit_type__icontains=site.type)
site.preference = d[0].circuit_preference
except:
pass
elif site.type == 'DSL' or site.type == 'FIBRE':
try:
d = Circuits.objects.only('circuit_preference','site_data').filter(site_data__id=sr.id,circuit_type__icontains=site.type)
site.preference = d[0].circuit_preference
except:
pass
**EDIT: models below
class SiteData(models.Model):
location = models.CharField(max_length=50)
site_type = models.CharField(max_length=20, verbose_name="Site Type", \
choices=settings.SITE_TYPE)
subnet = models.GenericIPAddressField(protocol='IPv4')
bgp_as = models.CharField(max_length=6, verbose_name="BGP AS Number")
opening_date = models.DateField(verbose_name="Showroom opening date")
last_hw_refresh_date = models.DateField(verbose_name="Date of latest hardware refresh", \
blank=True, null=True)
is_live = models.BooleanField(default=False, verbose_name="Is this a live site?")
tel = models.CharField(max_length=20, blank=True, null=True)
notes = models.TextField(blank=True)
class Meta:
verbose_name = "Site Data"
verbose_name_plural = "Site Data"
ordering = ('location',)
def __unicode__(self):
return self.location
class Circuits(models.Model):
site_data = models.ForeignKey(SiteData, verbose_name="Site", on_delete=models.PROTECT)
order_no = models.CharField(max_length=200, verbose_name="Order No")
install_date = models.DateField(blank=True, null=True)
circuit_type = models.CharField(max_length=100, choices=settings.CIRCUIT_CHOICES)
circuit_preference = models.CharField(max_length=20, verbose_name="Circuit Preference", \
choices=settings.CIRCUIT_PREFERENCE, blank=True, null=True)
circuit_speed_down = models.DecimalField(max_digits=10, decimal_places=1, blank=True, null=True)
circuit_speed_up = models.DecimalField(max_digits=10, decimal_places=1, blank=True, null=True)
circuit_bearer = models.IntegerField(blank=True, null=True)
provider = models.CharField(max_length=200, choices=settings.PROVIDER_CHOICES)
ref_no = models.CharField(max_length=200, verbose_name="Reference No")
cost_per_month = models.DecimalField(decimal_places=2, max_digits=8)
contract_length = models.IntegerField(verbose_name="Contact length in years")
service_contacts = models.ForeignKey(ServiceContacts, on_delete=models.PROTECT)
subnet = models.GenericIPAddressField(protocol='IPv4', verbose_name="Subnet", \
blank=True, null=True)
default_gateway = models.GenericIPAddressField(protocol='IPv4', \
verbose_name="Default Gateway", blank=True, null=True)
subnet_mask = models.CharField(max_length=4, verbose_name="Subnet Mask", \
choices=settings.SUBNET_MASK_CHOICES, blank=True, null=True)
internet_device = models.ForeignKey(ConfigTemplates, \
verbose_name="is this circuit the active internet line for a device?", \
default=6, on_delete=models.PROTECT)
decommissioned = models.BooleanField(default=False, verbose_name="Decomission this circuit?")
Upvotes: 0
Views: 147
Reputation: 201
I was going to point you toward Pickling, but I suppose that doesn't make sense unless you need to cache the querysets to re-use in another location.
Actually I'm pretty sure querysets are pretty good for only hitting the database when they need to, which is when they're first evaluated. However, I think redeclaring the queryset would cause it to be re-evaluated, but if you create a list/dictionary of querysets I imagine you should be able to just re-use them without hitting the database again (unless you need to run new filters on them.) So I don't think you have much choice than to hit the database for each time you fetch a crData queryset, but you should at least be able to store the querysets and reuse them without it hitting the database for each one again.
Something like this should work I think. Would love to know if I'm wrong.
crData = []
for sr in srData:
# ...
crData.append(d)
for cr in crData:
# Do stuff
EDIT: Here's another relevant question: Django ORM and hitting DB
Upvotes: 1