డెవలపర్లు తరచుగా నన్ను ఒకే ప్రశ్న అడుగుతుంటారు: "నా API నెమ్మదిగా ఉంది. నేను ఎక్కడి నుండి ప్రారంభించాలి?" సాధారణంగా సర్వర్ను అప్గ్రేడ్ చేయడం లేదా RAMని రెట్టింపు చేయడం వంటి చర్యలు తీసుకుంటారు. దీనివల్ల ఖర్చు పెరుగుతుంది కానీ అసలు సమస్య పరిష్కారం కాదు. చాలా Laravel అప్లికేషన్లలో, సమస్య డేటాబేస్ లేయర్లో ఉంటుంది. ఫ్రేమ్వర్క్ యొక్క ఎలిగెంట్ సింటాక్స్ వల్ల ప్రతి Eloquent కాల్ చివరికి SQLగా మారుతుందని, మరియు SQL వద్దే సమస్యలు మొదలవుతాయని మర్చిపోవడం సులభం.
మీరు సర్వర్ సెట్టింగ్లను మార్చడానికి ముందే, మీ క్వెరీలను పద్ధతిగా పరిశీలించండి.
సరైన డయాగ్నోస్టిక్తో ప్రారంభించండి
చీకట్లో ఆప్టిమైజ్ చేయకండి. క్వెరీలను యాదృచ్ఛికంగా మార్చడం అనేది కేవలం ఊహ మాత్రమే, మరియు అటువంటి ఊహలు గంటల సమయాన్ని వృధా చేస్తాయి.
అత్యధిక మొత్తం సమయాన్ని తీసుకునే స్టేట్మెంట్లను మీరు కనుగొనాలి. మీ అప్లికేషన్ను నిజమైన లోడ్ (real load) కింద గమనించండి. Laravel Telescope ప్రతి రిక్వెస్ట్ సమయంలో ఎగ్జిక్యూట్ అయ్యే ప్రతి క్వెరీని టైమింగ్తో సహా స్పష్టంగా చూపిస్తుంది. Laravel Debugbar లోకల్ డెవలప్మెంట్ సమయంలో బ్రౌజర్లోనే వాటిని చూపిస్తుంది, తద్వారా మీరు తప్పులను వెంటనే గుర్తించవచ్చు. ప్రొడక్షన్లో సమస్యలను పట్టుకోవాలనుకున్నప్పుడు, MySQL Slow Query Log ని ఎనేబుల్ చేయండి. మీరు నిర్ణయించిన పరిమితిని మించిన స్టేట్మెంట్లను ఇది రికార్డ్ చేస్తుంది, ఇది చిన్న డేటాసెట్లలో కనిపించని సమస్యలను కనుగొనడానికి చాలా ఉపయోగపడుతుంది. మీరు పెద్ద అప్లికేషన్ను నడుపుతుంటే, Application Performance Monitoring (APM) టూల్ నెమ్మదైన HTTP ఎండ్పాయింట్లను నిర్దిష్ట డేటాబేస్ కాల్స్తో అనుసంధానించగలదు.
డేటాను రివ్యూ చేసేటప్పుడు, రెండు విషయాలను గమనించండి: ఎగ్జిక్యూషన్ సమయం (absolute execution time) మరియు కాల్ ఫ్రీక్వెన్సీ (call frequency). నలభై మిల్లీ సెకన్లు తీసుకునే క్వెరీ పెద్ద సమస్యలా అనిపించకపోవచ్చు, కానీ అది నిమిషానికి రెండు వేలసార్లు రన్ అవుతుందని తెలిస్తే పరిస్థితి మారుతుంది. గంటకు ఒకసారి రన్ అయ్యే మూడు సెకన్ల రిపోర్ట్ కంటే, ప్రతి పేజీలో రన్ అయ్యే అర సెకను లుకప్ (lookup) ఎక్కువ ప్రభావం చూపుతుంది. ముందుగా అధిక ప్రభావం చూపే సమస్యలను పరిష్కరించండి.
అన్నింటినీ అడగడం ఆపండి
SELECT * అనేది సౌకర్యవంతంగా ఉండవచ్చు, కానీ అది ఖరీదైనది కూడా. మీరు Model::all() అని రాసినప్పుడు లేదా కాలమ్స్ పేర్లు చెప్పకుండా రిజల్ట్ సెట్ను తీసుకున్నప్పుడు, MySQL ప్రతి రో (row) లోని ప్రతి ఫీల్డ్ను వెతుకుతుంది. ఇందులో పెద్ద టెక్స్ట్ ఫీల్డ్లు, JSON బ్లాబ్లు మరియు టేబుల్లో ఉన్న ఇతర అంశాలు కూడా ఉంటాయి. దీనివల్ల రిజల్ట్ సెట్ పెరుగుతుంది, మెమరీ వినియోగం పెరుగుతుంది మరియు రెస్పాన్స్ను సీరియలైజ్ చేయడానికి పట్టే సమయం కూడా పెరుగుతుంది.
స్పష్టంగా ఉండండి. మీ కంట్రోలర్కు కేవలం id, name, మరియు email ఫీల్డ్లు మాత్రమే అవసరమైతే, ఖచ్చితంగా వాటిని మాత్రమే అడగండి:
User::select('id', 'name', 'email')->get();
క్వెరీ బిల్డర్లో కూడా ఇదే సూత్రం వర్తిస్తుంది. చిన్న పేలోడ్లు నెట్వర్క్ ద్వారా వేగంగా ప్రయాణిస్తాయి మరియు మీ అప్లికేషన్ సర్వర్లో తక్కువ RAMని ఉపయోగిస్తాయి. ఇది చాలా తక్కువ ఖర్చుతో కూడిన పరిష్కారం, అయినప్పటికీ Laravel డిఫాల్ట్గా SELECT * ను ఉపయోగిస్తుంది కాబట్టి చాలామంది దీనిని వదిలేస్తుంటారు.
మార్పుల కోసం EXPLAIN ని ఉపయోగించండి
ముందుగా EXPLAIN రన్ చేయకుండా నెమ్మదైన క్వెరీని ఎప్పుడూ రీఫాక్టర్ చేయకండి. MySQLలో, EXPLAIN కీవర్డ్ క్వెరీ ఎగ్జిక్యూషన్ ప్లాన్ను చూపిస్తుంది. ఆప్టిమైజర్ మీ డేటాను ఎలా కనుగొనాలనుకుంటుందో ఇది స్పష్టంగా తెలియజేస్తుంది.
type కాలమ్ పై దృష్టి పెట్టండి. మీరు ALL అని చూస్తే, MySQL ఫుల్ టేబుల్ స్కాన్ (full table scan) చేస్తోందని అర్థం. అంటే మీ WHERE క్లాజ్ కోసం అది ప్రతి రోను చదువుతోంది. ఆప్టిమైజర్ ఇండెక్స్ను ఉపయోగిస్తుందో లేదో చూడటానికి key కాలమ్ను చూడండి. ఆ తర్వాత Extra కాలమ్ను తనిఖీ చేయండి. మీరు Using temporary లేదా Using filesort అని చూస్తే, మీ ప్రస్తుత స్ట్రక్చర్ క్వెరీని సరిగ్గా నిర్వహించలేక MySQL మధ్యంతర టేబుల్స్ను నిర్మిస్తోందని లేదా మెమరీలో సార్టింగ్ చేస్తోందని అర్థం.
మీ MySQL క్లయింట్లో EXPLAIN రన్ చేయండి, లేదా అవుట్పుట్ను ఫార్మాట్ చేసే టూల్ను ఉపయోగించండి. ప్లాన్ చూడగానే, సమస్య మిస్సింగ్ ఇండెక్స్ వల్లనా, తప్పుడు జాయిన్ (bad join) వల్లనా, లేదా ఇంజిన్ ఆప్టిమైజ్ చేయలేని ప్రిడికేట్ వల్లనా అనేది మీకు తెలుస్తుంది. అప్పుడు ఊహలు అవసరం ఉండదు.
ఉద్దేశపూర్వకంగా ఇండెక్సింగ్ చేయండి
లుకప్లను వేగవంతం చేయడానికి ఇండెక్స్లు అత్యంత శక్తివంతమైన సాధనాలు, కానీ అవి మీరు చేసే క్వెరీలకు సరిపోలినప్పుడు మాత్రమే పనిచేస్తాయి. సరైన ఇండెక్స్ లేకపోతే, MySQL ప్రతి రోను ఒక్కొక్కటిగా స్కాన్ చేస్తుంది. వెయ్యి రోలు ఉన్న టేబుల్పై డెవలప్మెంట్లో ఇది బాగానే అనిపించవచ్చు, కానీ పది మిలియన్ రోలు ఉన్న ప్రొడక్షన్లో ఇది భారీ సమస్యగా మారుతుంది.
WHERE క్లాజులలో తరచుగా కనిపించే ఫీల్డ్ల కోసం సింగిల్-కాలమ్ ఇండెక్స్లతో ప్రారంభించండి. మీరు నిరంతరం status ద్వారా ఫిల్టర్ చేస్తుంటే, status పై ఇండెక్స్ జోడించండి.
ఒక క్వెరీ బహుళ కాలమ్స్పై కలిపి ఫిల్టర్ చేసినప్పుడు, కాంపోజిట్ ఇండెక్స్ల (composite indexes) వైపు వెళ్లండి. ఇండెక్స్లోని కాలమ్స్ యొక్క క్రమం ముఖ్యం, ఎందుకంటే MySQL కాంపోజిట్ ఇండెక్స్లను ఎడమ నుండి కుడికి చదువుతుంది. దీనిని 'leftmost prefix rule' అంటారు. మీ క్వెరీ user_id ద్వారా వెతికి, ఆపై created_at ద్వారా ఆర్డర్ చేస్తే, (user_id, created_at) పై ఉన్న కాంపోజిట్ ఇండెక్స్ గణనీయంగా సహాయపడుతుంది. క్రమాన్ని రివర్స్ చేస్తే, ఆప్టిమైజర్ ఫిల్టర్ కోసం ఇండెక్స్ను ఉపయోగించకపోవచ్చు.
ప్రతి కాలమ్కు ఇండెక్స్ చేయకండి. ప్రతి ఇండెక్స్ ఇన్సర్ట్స్ (inserts), అప్డేట్స్ (updates) మరియు డిలీట్స్ (deletes) పై అదనపు భారాన్ని (overhead) పెంచుతుంది, ఎందుకంటే MySQL ఆ స్ట్రక్చర్ను నిర్వహించాల్సి ఉంటుంది. మీరు కొలమానాల (measurement) ద్వారా కనుగొన్న ప్యాటర్న్ల ఆధారంగా వాటిని జాగ్రత్తగా జోడించండి.
ఫంక్షన్లను కాలమ్స్ నుండి దూరంగా ఉంచండి
ఈ తప్పు ఇండెక్స్లను తెలియకుండానే నిలిపివేస్తుంది. మీరు WHERE క్లాజ్ లోపల ఒక కాలమ్ను ఫంక్షన్లో చుట్టినప్పుడు, MySQL చేయలేదు
