Ես ստեղծել եմ հարցում get_context դասի վրա հիմնված դիտման մեջ, որտեղից ես ստեղծում եմ դիկտ, որը ուղարկում եմ Django ձևանմուշ՝ ձևաչափի կողքին ցուցադրելու համար: Վերադարձված գրառումների թիվը մոտ 40 է, և գործարկելու համար տևում է մոտ 5 վայրկյան, ինչը կվերածվի 30 կամ 40 վայրկյան տվյալների ամբողջական փաթեթով: Դիտելով Django Debug Toolbar SQL հարցումները՝ այն շարունակում է կատարել 40 լրացուցիչ հարցումներ՝ չնայած իմ հարցումների հավաքածուին ավելացնելով ճիշտ select_related և prefetch_related աղյուսակի համար նախատեսված ճիշտ ընտրություն:
Իմ մոդելները (այս օրինակի համար պարզեցված).
class Item(models.Model):
name = models.CharField(max_length=20, primary_key=True)
description = models.CharField(max_length=35, blank=True, null=True)
def __str__(self):
return f"{self.name}"
class ItemLocSite(models.Model):
name = models.CharField(max_length=10, primary_key=True)
models.CharField(max_length=10)
class Meta:
def __str__(self):
return f"{self.name}"
class ItemLoc(AbstractAddArchive):
item = models.ForeignKey(Item, on_delete=models.PROTECT)
iloc = models.ForeignKey(ItemLocSite, on_delete=models.SET_NULL, null=True, blank=True, related_name='iloc')
nloc = models.ForeignKey(ItemLocSite, on_delete=models.SET_NULL, null=True, blank=True, related_name='nloc')
cp_date = models.DateField(null=True, blank=True)
posted_by = models.ForeignKey(User, on_delete=models.PROTECT, max_length=10, null=True, blank=True)
class Meta:
def __str__(self):
return f"{self.item}"
class ItemInfo(AbstractAddArchive):
item = models.ForeignKey(Item, on_delete=models.PROTECT)
log_entry = models.ForeignKey(Log, on_delete=models.PROTECT, null=True, blank=True)
c = models.CharField(max_length=2, blank=True, null=True)
crec_log_entry = models.ForeignKey(InvLog, on_delete=models.PROTECT, related_name='crec_log_entry', blank=True, null=True)
csts = models.ForeignKey(ItemSts, on_delete=models.PROTECT, null=True, blank=True)
cfill = models.IntegerField(blank=True, null=True)
comment1 = models.CharField(max_length=45, blank=True, null=True)
comment2 = models.CharField(max_length=45, blank=True, null=True)
posted_by = models.ForeignKey(User, on_delete=models.PROTECT, max_length=10, null=True, blank=True)
posted_ts = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('item',) # This sets initial order of formset display
def __str__(self):
return f"{self.item_id}"
Իդեալում, ItemLoc-ը և ItemInfo-ն լինեին մեկ աղյուսակ, որը շատ ավելի կհեշտացներ ամեն ինչ, բայց համակարգի օգտագործման նկատառումներից ելնելով, դա համակարգի պահանջ է, որպեսզի տվյալները պահվեն երկու աղյուսակներում, որոնցից յուրաքանչյուրը կապված է Նյութի հետ, այնպես որ ես պետք է աշխատեմ դրա հետ:
Իմ հարցումը և հրահանգի կառուցումը.
itemdict = {}
iteminfos = ItemInfo.objects.all().select_related('item').prefetch_related('item__itemloc_set').order_by('item_id')
for iteminfo in iteminfos:
itemdict[iteminfo.item.name] = iteminfo.item.itemloc_set.all().first().iloc_id
context['itemdict'] = itemdict
Յուրաքանչյուր ակտիվ նյութի համար կլինի միայն 1 ակտիվ նյութ. հարցումը չի աշխատի առանց .first() ավելացնելու, թեև այն միակն է:
Django Debug Toolbar-ում ես տեսնում եմ, որ այս SQL հարցումն աշխատում է մեկ անգամ յուրաքանչյուր գրառման համար (այժմ կա ընդամենը 40, բայց հավանաբար կլինի 200 կամ ավելի, ինչը թարգմանվում է շատ այլ հարցումների)
SELECT ••• app_itemloc-ից ՈՐՏԵՂ (app_itemloc.archive_id IS NULL AND app_itemloc.item_id = 'AAA') ՊԱՏՎԻՐԵԼ ԸՍՏ app_itemloc.id ASC LIMIT 1
40 նմանատիպ հարցումներ:
Այս հարցումը կատարվում է համակարգի յուրաքանչյուր ակտիվ տարրի համար՝ ներկայումս 40: Յուրաքանչյուր անհատական հարցում արագ է կատարվում, բայց մեկ էջի համար այդքան անգամ վերադառնալով տվյալների բազա, էջի բեռնման ժամանակը մեծացնում է մոտ 5 վայրկյանով:
archive_id-ը մշակվում է հատուկ օբյեկտի կողմից, որն օգտագործվում է գրառումները արխիվացնելու համար, այնպես որ ցուցադրվում են միայն ակտիվ գրառումները (տես մոդելները. ItemInfo-ն և ItemLoc-ը ժառանգվում են AbstractAddArchive-ից): Չեմ կարծում, որ արխիվացումը պետք է կապ ունենա լրացուցիչ հարցումների հետ, բայց անհրաժեշտության դեպքում կարող է տրամադրել այդ լրացուցիչ կոդը: - երբեք չի լինի ավելի քան 200 կամ 300 ակտիվ գրառում:
Ես կմտածեի, որ itemloc հավաքածուի նախնական առբերումը կհավաքի անհրաժեշտ տվյալները, բայց ակնհայտ է, որ այստեղ բացակայում եմ select_related կամ prefetch_related, բայց չեմ կարող տեսնել, թե դա ինչ կլինի:
Որևէ մեկը առաջարկներ ունի՞: Շնորհակալություն.