ડેવલપર્સ અવારનવાર મને એક જ પ્રશ્ન પૂછે છે: "મારી API ધીમી છે. મારે ક્યાંથી શરૂઆત કરવી જોઈએ?" સામાન્ય રીતે પ્રતિક્રિયા સર્વર અપગ્રેડ કરવાની અથવા RAM બમણી કરવાની હોય છે. તેમાં ખર્ચ થાય છે અને તે ભાગ્યે જ મૂળ કારણને ઠીક કરે છે. મોટાભાગની Laravel એપ્લિકેશન્સમાં, બોટલનેક (bottleneck) ડેટાબેઝ લેયરમાં હોય છે. ફ્રેમવર્કનું સુંદર સિન્ટેક્સ એ ભૂલી જવું સરળ બનાવે છે કે દરેક Eloquent કોલ અંતે SQL બની જાય છે, અને SQL એ જ જગ્યા છે જ્યાં સમસ્યાઓ શરૂ થાય છે.

સર્વર સેટિંગ્સને અડતા પહેલા, તમારી ક્વેરીઝ પર પદ્ધતિસર કામ કરો.

સાચા નિદાનથી શરૂઆત કરો

અંધારામાં ઓપ્ટિમાઇઝેશન ન કરો. ક્વેરીઝને રેન્ડમલી ફરીથી લખવી એ માત્ર અટકળ છે, અને અટકળથી કલાકોનો બગાડ થાય છે.

તમારે એવા સ્ટેટમેન્ટ્સ શોધવાની જરૂર છે જે સૌથી વધુ કુલ સમય લે છે. વાસ્તવિક લોડ હેઠળ તમારી એપ્લિકેશનનું નિરીક્ષણ કરો. Laravel Telescope તમને રિક્વેસ્ટ દરમિયાન એક્ઝિક્યુટ થયેલી દરેક ક્વેરીનો સમય સાથે સ્પષ્ટ વ્યુ આપે છે. Laravel Debugbar લોકલ ડેવલપમેન્ટ દરમિયાન બ્રાઉઝરમાં જ આ ક્વેરીઝ બતાવે છે જેથી તમે તરત જ વિસંગતતાઓ શોધી શકો. જ્યારે તમારે પ્રોડક્શનમાં સમસ્યાઓ પકડવી હોય, ત્યારે MySQL Slow Query Log સક્ષમ કરો. તે તમે વ્યાખ્યાયિત કરેલા થ્રેશોલ્ડ (threshold) કરતા વધુ સમય લેતા સ્ટેટમેન્ટ્સને રેકોર્ડ કરે છે, જે નાના ડેટાસેટ્સમાં ન દેખાતી અણધારી સમસ્યાઓ શોધવા માટે આદર્શ છે. જો તમે કંઈક મોટું ચલાવતા હોવ, તો Application Performance Monitoring ટૂલ ધીમા HTTP એન્ડપોઈન્ટ્સને ચોક્કસ ડેટાબેઝ કોલ્સ સાથે જોડી શકે છે.

જ્યારે તમે ડેટાની સમીક્ષા કરો, ત્યારે બે વસ્તુઓ જુઓ: એક્ઝિક્યુશનનો કુલ સમય અને કોલની આવૃત્તિ (frequency). 40 મિલીસેકન્ડ લેતી ક્વેરી નુકસાનકારક લાગતી નથી, જ્યાં સુધી તમને ખબર ન પડે કે તે દર મિનિટે બે હજાર વાર ચાલે છે. કલાકે એક વાર ચાલતો ત્રણ સેકન્ડનો રિપોર્ટ, દરેક પેજ પર ચાલતા અડધા સેકન્ડના લુકઅપ કરતા ઓછો મહત્વનો હોઈ શકે છે. પહેલા ઉચ્ચ-અસરકારક (high-impact) સમસ્યાઓને ઠીક કરો.

બધું જ માંગવાનું બંધ કરો

SELECT * અનુકૂળ છે, પણ તે મોંઘું પણ છે. જ્યારે તમે Model::all() લખો છો અથવા કોલમનું નામ આપ્યા વિના રિઝલ્ટ સેટ મેળવો છો, ત્યારે MySQL દરેક મેચ થયેલ રો (row) માટે દરેક ફિલ્ડને ખેંચી લાવે છે. તેમાં મોટા ટેક્સ્ટ ફિલ્ડ્સ, JSON બ્લોબ્સ અને ટેબલમાં રહેલી અન્ય કોઈપણ વસ્તુઓનો સમાવેશ થાય છે. પરિણામે રિઝલ્ટ સેટ વધે છે, મેમરીનો વપરાશ વધે છે અને રિસ્પોન્સને સિરીયલાઈઝ કરવામાં લાગતો સમય પણ વધે છે.

સ્પષ્ટ રહો. જો તમારા કંટ્રોલરને ફક્ત id, name, અને email ફિલ્ડ્સની જ જરૂર હોય, તો ફક્ત તે જ માંગો:

User::select('id', 'name', 'email')->get();

ક્વેરી બિલ્ડરમાં પણ આ જ સિદ્ધાંત લાગુ પડે છે. નાનું પેલોડ (payload) નેટવર્ક પર ઝડપથી મુસાફરી કરે છે અને તમારા એપ્લિકેશન સર્વર પર ઓછી RAM વાપરે છે. આ ઉપલબ્ધ સૌથી સસ્તા અને અસરકારક ઉપાયોમાંનો એક છે, છતાં તેને અવગણવો સરળ છે કારણ કે Laravel માં SELECT * ડિફોલ્ટ બિહેવિયર છે.

EXPLAIN ને તમારા ફેરફારોમાં માર્ગદર્શક બનવા દો

EXPLAIN ચલાવ્યા વિના ક્યારેય ધીમી ક્વેરીને રિફેક્ટર ન કરો. MySQL માં, EXPLAIN કીવર્ડ ક્વેરી એક્ઝિક્યુશન પ્લાન બતાવે છે. તે બરાબર દર્શાવે છે કે ઓપ્ટિમાઇઝર તમારા ડેટાને કેવી રીતે શોધવાનો ઈરાદો રાખે છે.

type કોલમ પર ધ્યાન આપો. જો તમે ALL જુઓ છો, તો MySQL ફૂલ ટેબલ સ્કેન કરી રહ્યું છે. તેનો અર્થ એ છે કે તે તમારા WHERE ક્લોઝને સંતોષવા માટે દરેક રો વાંચી રહ્યું છે. ઓપ્ટિમાઇઝર ઇન્ડેક્સનો ઉપયોગ કરી રહ્યું છે કે નહીં તે જોવા માટે key કોલમ જુઓ. ત્યારબાદ Extra કોલમ તપાસો. જો તમને Using temporary અથવા Using filesort દેખાય, તો તેનો અર્થ છે કે MySQL વચગાળાના ટેબલ્સ બનાવી રહ્યું છે અથવા મેમરીમાં સોર્ટિંગ કરી રહ્યું છે કારણ કે તમારી વર્તમાન રચના ક્વેરીને વ્યવસ્થિત રીતે સંતોષી શકતી નથી.

તમારા MySQL ક્લાયન્ટમાં EXPLAIN ચલાવો, અથવા આઉટપુટને ફોર્મેટ કરવા માટે કોઈ ટૂલનો ઉપયોગ કરો. એકવાર તમે પ્લાન જોઈ લો, પછી તમે જાણી શકશો કે સમસ્યા ખૂટતા ઇન્ડેક્સની છે, ખરાબ જોઈનની છે, કે પછી એવા પ્રિડિકેટ (predicate) ની છે જેને એન્જિન ઓપ્ટિમાઇઝ કરી શકતું નથી. હવે અટકળ કરવાની જરૂર રહેશે નહીં.

હેતુપૂર્વક ઇન્ડેક્સિંગ કરો

લુકઅપ્સને ઝડપી બનાવવા માટે ઇન્ડેક્સ સૌથી શક્તિશાળી સાધન છે, પરંતુ તે ત્યારે જ કામ કરે છે જ્યારે તે તમારી ક્વેરી સાથે મેળ ખાય છે. યોગ્ય ઇન્ડેક્સ વિના, MySQL રો-બાય-રો સ્કેન કરે છે. હજારો રો ધરાવતા ટેબલ પર ડેવલપમેન્ટ દરમિયાન તે બરાબર લાગી શકે છે, પરંતુ દસ મિલિયન રો ધરાવતા ટેબલ પર પ્રોડક્શનમાં તે નિષ્ફળ જઈ શકે છે.

WHERE ક્લોઝમાં વારંવાર દેખાતા ફિલ્ડ્સ માટે સિંગલ-કોલમ ઇન્ડેક્સથી શરૂઆત કરો. જો તમે સતત status દ્વારા ફિલ્ટર કરતા હોવ, તો status પર ઇન્ડેક્સ ઉમેરો.

જ્યારે કોઈ ક્વેરી એકસાથે અનેક કોલમ પર ફિલ્ટર કરે છે, ત્યારે કમ્પોઝિટ (composite) ઇન્ડેક્સ તરફ આગળ વધો. ઇન્ડેક્સની અંદર કોલમનો ક્રમ મહત્વનો છે કારણ કે MySQL કમ્પોઝિટ ઇન્ડેક્સને ડાબેથી જમણે વાંચે છે. આને 'leftmost prefix rule' કહેવામાં આવે છે. જો તમારી ક્વેરી user_id દ્વારા શોધે છે અને પછી created_at દ્વારા ઓર્ડર કરે છે, તો (user_id, created_at) પરનો કમ્પોઝિટ ઇન્ડેક્સ નોંધપાત્ર રીતે મદદ કરે છે. જો તમે ક્રમ ઉલટાવી દો, તો ઓપ્ટિમાઇઝર ફિલ્ટર માટે ઇન્ડેક્સનો ઉપયોગ કદાચ ન પણ કરે.

દરેક કોલમ પર ઇન્ડેક્સ ન કરો. દરેક ઇન્ડેક્સ ઇન્સર્ટ, અપડેટ અને ડિલીટમાં વધારાનો બોજ (overhead) ઉમેરે છે કારણ કે MySQL એ તેની રચના જાળવી રાખવી પડે છે. માપન દરમિયાન તમે જે પેટર્ન શોધી હોય તેના આધારે જ ઇન્ડેક્સ ઉમેરો.

કોલમ્સથી ફંક્શન્સને દૂર રાખો

આ ભૂલ ઇન્ડેક્સને (indexes) છૂપી રીતે નિષ્ક્રિય કરી દે છે. જ્યારે તમે WHERE ક્લોઝની અંદર કોઈ કોલમને ફંક્શનમાં લપેટી દો (wrap કરો), ત્યારે MySQL કરી શકતું નથી