AMcoder - javascript, python, java, html, php, sql

Django հարցումը երկար ժամանակ է պահանջում

Ես ստեղծել եմ հարցում 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, բայց չեմ կարող տեսնել, թե դա ինչ կլինի:

Որևէ մեկը առաջարկներ ունի՞: Շնորհակալություն.


  • itemdict[iteminfo.item.name] = iteminfo.item.itemloc_set.all().first().iloc_id-ն ակնհայտորեն առանձին հարցում կկատարի first()-ին զանգահարելու պատճառով: 17.03.2021
  • Շնորհակալություն պատասխանելու համար. Դուք կունենա՞ք հարցումը ձևավորելու ավելի լավ միջոց, որպեսզի բոլոր տվյալները վերադարձվեն մեկ sql հարցումով, իմանալով, որ յուրաքանչյուր itemloc_set-ում կա ընդամենը 1 գրառում: 17.03.2021
  • Եթե ​​երաշխավորված է, որ կա միայն մեկ ItemLoc օրինակ Item օրինակի համար, ապա պետք է օգտագործեք OneToOneField օտար բանալիի փոխարեն: 17.03.2021
  • Դա երաշխավորված է միայն չարխիվացված իրերի համար իմ դեպքում. սեղանի վրա արխիվացված իրերը թույլ չեն տալիս մեկից մեկին, այնպես որ սա այն կառուցվածքն է, որով ես խրված եմ: 17.03.2021

Պատասխանները:


1

Ես գտա երկու աղյուսակներից տվյալներ ստանալու այլ եղանակ՝ առանց հակադարձ հարցում օգտագործելու կամ «Նախաբեռնում» առարկաների աղյուսակի միջոցով.

itemdict = {}
iteminfos = ItemInfo.objects.all().select_related('item').order_by('item_id')
itemlocs = ItemLoc.objects.all().order_by('item_id')
for iteminfo, itemloc in zip(iteminfos, itemlocs):
    itemdict[iteminfo.item_id] = itemloc.iloc_id
context['itemdict'] = itemdict

Ես ստանում եմ նույն հրահանգը, ինչ իմ նախորդ շինարարության դեպքում, բայց հարցումների ընդհանուր թիվը նվազել է մինչև 4-ի, և ես սափրվել եմ գործարկման ժամանակից մոտ 3,5 վայրկյանով (այժմ մոտ 45 ակտիվ գրառումներով): Ես կարողացա օգտագործել item_id-ը և iloc_id-ը, ինչպես նաև խուսափեցի նրանց արժեքների համար select_related անելուց, քանի որ անունները հարակից աղյուսակների հիմնական դաշտերն են, ուստի արժեքը արտաքին բանալին է և ոչ թե ավտոմատ աճող թիվ:

Թվում է, թե այս դեպքում պահանջվող տվյալների բազայի եզակի կառուցվածքով, prefetch_related-ի օգտագործմամբ ավելի ստանդարտ մեթոդը տարբերակ չէր: Եթե ​​որևէ մեկը, ով կարդում է սա, տեսնում է prefetch_related-ի օգտագործման միջոց, ինձ դեռ կհետաքրքրի դա տեսնել:

17.03.2021
Նոր նյութեր

Օգտագործելով Fetch Vs Axios.Js-ը՝ HTTP հարցումներ կատարելու համար
JavaScript-ը կարող է ցանցային հարցումներ ուղարկել սերվեր և բեռնել նոր տեղեկատվություն, երբ դա անհրաժեշտ լինի: Օրինակ, մենք կարող ենք օգտագործել ցանցային հարցումը պատվեր ներկայացնելու,..

Տիրապետել հանգստության արվեստին. մշակողի ուղեցույց՝ ճնշման տակ ծաղկելու համար
Տիրապետել հանգստության արվեստին. մշակողի ուղեցույց՝ ճնշման տակ ծաղկելու համար Ինչպե՞ս հանգստացնել ձեր միտքը և աշխատեցնել ձեր պրոցեսորը: Ինչպես մնալ հանգիստ և զարգանալ ճնշման տակ...

Մեքենայի ուսուցում բանկային և ֆինանսների ոլորտում
Բարդ, խելացի անվտանգության համակարգերը և հաճախորդների սպասարկման պարզեցված ծառայությունները բիզնեսի հաջողության բանալին են: Ֆինանսական հաստատությունները, մասնավորապես, պետք է առաջ մնան կորի..

Ես AI-ին հարցրի կյանքի իմաստը, այն ինչ ասում էր, ցնցող էր:
Այն պահից ի վեր, երբ ես իմացա Արհեստական ​​ինտելեկտի մասին, ես հիացած էի այն բանով, թե ինչպես է այն կարողանում հասկանալ մարդկային նորմալ տեքստը, և այն կարող է առաջացնել իր սեփական արձագանքը դրա..

Ինչպես սովորել կոդավորումը Python-ում վագրի պես:
Սովորելու համար ծրագրավորման նոր լեզու ընտրելը բարդ է: Անկախ նրանից, թե դուք սկսնակ եք, թե առաջադեմ, դա օգնում է իմանալ, թե ինչ թեմաներ պետք է սովորել: Ծրագրավորման լեզվի հիմունքները, դրա..

C++-ի օրական բիթ(ե) | Ամենաերկար պալինդրոմային ենթաշարը
C++ #198-ի ամենօրյա բիթ(ե), Ընդհանուր հարցազրույցի խնդիր. Ամենաերկար պալինդրոմային ենթատող: Այսօր մենք կանդրադառնանք հարցազրույցի ընդհանուր խնդրին. Ամենաերկար palindromic substring...

Kydavra ICAReducer՝ ձեր տվյալների ծավալայինությունը նվազեցնելու համար
Ի՞նչ է ICAReducer-ը: ICAReducer-ն աշխատում է հետևյալ կերպ. այն նվազեցնում է նրանց միջև բարձր փոխկապակցված հատկանիշները մինչև մեկ սյունակ: Բավականին նման է PCAreducer-ին, չնայած այն..