Laravelలో N+1లను గుర్తించి, వృథా క్వెరీలను అరికట్టడం
పెర్ఫార్మెన్స్ (Performance) పనులు తరచుగా విసుగు పుట్టించేవిగా ఉంటాయి.
మీరు 80% లాటెన్సీని (latency) తగ్గించినట్లుగా ఉండే హీరో కథలు ఇక్కడ ఎప్పుడూ ఉండవు. చాలా రోజులు, ఇది కేవలం క్లీనప్ (cleaning up) చేయడం గురించి మాత్రమే ఉంటుంది. మీరు రన్ చేస్తున్నట్లు మీకు తెలియని క్వెరీలను మీరు గుర్తిస్తారు. ఆ తర్వాత, వాటిని తొలగిస్తారు.
మీ Laravel యాప్ పెరుగుతున్నట్లయితే, మీకు ఈ మూడు సమస్యలు ఎదురయ్యే అవకాశం ఉంది.
- దాగి ఉన్న N+1 క్వెరీలు (Hidden N+1 Queries)
మీరు చూడలేని దానిని మీరు సరిచేయలేరు. మీ లోకల్ ఎన్విరాన్మెంట్ (local environment)లో beyondcode/laravel-query-detector వంటి టూల్ను ఉపయోగించండి. మీరు ఎప్పుడు 'loop-and-lazy-load' ప్యాటర్న్ను ఉపయోగిస్తున్నారో ఇది మీకు తెలియజేస్తుంది.
దీనిని ప్రొడక్షన్లో (production) రన్ చేయకండి. ఇది ఓవర్హెడ్ (overhead)ను పెంచుతుంది. మీ యాప్ లోకల్ లేదా టెస్టింగ్ మోడ్లో ఉన్నప్పుడు మాత్రమే దీనిని రిజిస్టర్ చేయండి.
- ఈగర్ లోడింగ్ వృథా (Eager Loading Waste)
చాలామంది with()ని జోడించడం ద్వారా N+1 సమస్యలను పరిష్కరిస్తారు. కానీ ఇది కొత్త సమస్యను సృష్టిస్తుంది. మీ వ్యూ (view) ఇకపై ఉపయోగించని రిలేషన్షిప్ను మీరు ఈగర్-లోడ్ (eager-load) చేయవచ్చు.
ఒకవేళ రీడిజైన్ వల్ల టేబుల్ నుండి ఒక కాలమ్ తొలగించబడితే, మీరు మీ కంట్రోలర్లో దానికి సంబంధించిన with() కాల్ను కూడా తొలగించాలి. మీరు వృథా చేసే డేటా కోసం అనవసరంగా ఖర్చు చేస్తున్నారు.
ప్రతి ఈగర్ లోడ్ను ఒక క్లెయిమ్గా (claim) పరిగణించండి. మీరు ఆ డేటాను ఉపయోగించకపోతే, ఆ క్లెయిమ్ను తొలగించండి.
- ఒకే డేటాను మళ్ళీ లెక్కించడం (Recomputing the Same Data)
కొన్ని విలువలు మొత్తం రిక్వెస్ట్ (request) కాలం పాటు ఒకేలా ఉంటాయి. వాటిని మీరు పదేపదే లెక్కించడం వల్ల CPU వృథా అవుతుంది. దీనిని పరిష్కరించడానికి మెమోయిజేషన్ (memoization) ఉపయోగించండి.
Example:
protected ?string $defaultConnection = null;
public function getDefaultConnectionName(): string
{
return $this->defaultConnection ??= $this->resolveDefaultConnection();
}
??= ఆపరేటర్ విలువను ఒకసారి మాత్రమే లెక్కిస్తుంది మరియు మిగిలిన రిక్వెస్ట్ కోసం దానిని మళ్ళీ ఉపయోగిస్తుంది.
- డ్యాష్బోర్డ్ క్వెరీ ట్రాప్స్ (Dashboard Query Traps)
డ్యాష్బోర్డ్లు తరచుగా ప్రతి కార్డ్ కోసం విడివిడిగా count() క్వెరీని రన్ చేస్తాయి. మీకు ఆరు కార్డ్లు ఉంటే, మీరు ఆరు క్వెరీలను రన్ చేస్తున్నారు.
దానికి బదులుగా ఈ రెండు పనులు చేయండి:
- మీ కౌంట్లను గ్రూప్ చేయండి. ఒకే టేబుల్ యొక్క మొత్తం విలువలను (totals) ఒకే క్వెరీలో పొందండి.
- చిన్న కాష్ (cache)ను ఉపయోగించండి. డ్యాష్బోర్డ్ గణాంకాలు (stats) ప్రతి సెకనుకు లైవ్లో ఉండాల్సిన అవసరం లేదు. వాటిని ఐదు నిమిషాల పాటు కాష్ చేయండి.
ఒక విజిటర్ క్వెరీ ఖర్చును భరిస్తే, మిగిలిన వారందరికీ కాష్ చేయబడిన ఫలితం (cached result) అందుతుంది.
Final Tip: రిగ్రెషన్లను (Regressions) నివారించండి
డెవలపర్లు తర్వాత మళ్ళీ అదే తప్పు కోడ్ను జోడిస్తే, క్లీనప్ ప్రక్రియ విఫలమవుతుంది. మీ క్వెరీ కౌంట్లను అసెర్ట్ (assert) చేయడానికి Pestని ఉపయోగించండి. ఒక పేజీ ఎన్ని క్వెరీలను రన్ చేయవచ్చో ఒక పరిమితిని (ceiling) నిర్ణయించండి. ఒక డెవలపర్ N+1ని జోడిస్తే, టెస్ట్ ఫెయిల్ అవుతుంది.
ఆప్టిమైజేషన్ (Optimization) అంటే ప్రధానంగా తొలగించడం. ఉపయోగించని లోడ్లను తొలగించండి. మళ్ళీ లెక్కించే విలువలను తొలగించండి. అనవసరమైన క్వెరీలను తొలగించండి.
