Objavljeno 21. maj 2026.

← Svi članci

Kako je jedan indeks koji nedostaje pojeo 80% vremena zahteva

Studija slučaja iz produkcije: kako je jedan neefikasan pristup bazi postao skuplji od svega ostalog u zahtevu zajedno.

Sistem je već imao keširanje, pozadinske procese, unapred izračunate metapodatke i optimizovanu isporuku, ali je jedan upit i dalje dominirao životnim ciklusom zahteva.

Konačno rešenje nije bilo više infrastrukture. Bio je to složeni indeks usklađen sa načinom na koji aplikacija zaista pristupa podacima.

Usporenje nije bilo očigledno

Problemi sa performansama u produkciji retko se jasno najave. U ovom slučaju aplikacija nije otkazala, zahtevi nisu pucali, a praćenje infrastrukture nije odmah ukazalo na jednu pokvarenu komponentu. Sistem je jednostavno postao sporiji na određenim putanjama, naročito kada su „hladni“ podaci morali da se pripreme pre nego što stranica odgovori.

U početku su glavni osumnjičeni bili obrada slika, poništavanje keša, pristup fajl sistemu ili renderovanje aplikacije. To su bile razumne pretpostavke, jer je problematičan tok radio sa metapodacima slika i velikim skupovima podataka. Baza je učestvovala u zahtevu, ali u početku nije izgledala kao glavni izvor kašnjenja.

Detaljno profilisanje je promenilo tu pretpostavku. Kada je vremenska linija zahteva pažljivije pregledana, jedan upit ka bazi se izdvojio. Iznova je trošio najveći deo vremena zahteva, a njegova cena je rasla kako je rasla količina sačuvanih podataka.

Upit je izgledao bezazleno

Pojednostavljeni upit nije bio složen. Birao je ograničenu grupu zapisa kojima su metapodaci slike još nedostajali, sortirao ih po ID-ju i prosleđivao dalje na obradu.

SELECT id, source_image_id
FROM processed_image
WHERE metadata_exist = 0
ORDER BY id
LIMIT 100;

Na malom obimu ovakav upit može da izgleda potpuno prihvatljivo. Tabela je imala primarni ključ, aplikacija je imala i druge indekse, a rezultat je bio ograničen na samo 100 redova. Iz ugla aplikacije izgledalo je kao mala grupna operacija, a ne opasno usko grlo.

Problem nije bio broj vraćenih redova. Problem je bio koliko podataka baza mora da pregleda pre nego što sa sigurnošću vrati te redove traženim redosledom.

Postojeći indeksi nisu bili dovoljni

Česta greška u optimizaciji baze je pretpostavka da je tabela zaštićena samim tim što ima indekse. Indeksi nisu korisni sami po sebi. Korisni su kada odgovaraju načinu pristupa upita koji treba da se izvrši.

Ovaj upit je imao dva važna zahteva. Trebalo je da filtrira zapise po metadata_exist, a rezultat je trebalo da bude poređan po id. Indeks koji pomaže samo direktnu pretragu po ID-ju ne rešava ovakav pristup. Indeks koji pomaže samo filtriranju i dalje može da ostavi bazi dodatni posao sortiranja.

Bez indeksa koji pokriva oba dela upita, MySQL je morao da bira između nesavršenih strategija izvršenja. Mogao je da ide redom po primarnom ključu i za svaki red proverava uslov za metapodatke, ili da prvo filtrira pa da plati dodatnu cenu sortiranja. Nijedan put nije bio idealan za tabelu koja stalno raste.

Prava cena je bila prolazak kroz redove

Ključno otkriće došlo je kada se pogledalo dalje od vremena izvršenja. Trajanje upita je pokazalo da je nešto sporo, ali je plan izvršenja objasnio zašto. Baza je pregledala mnogo više redova nego što je vraćala.

Rows examined: 2,400,000
Rows returned: 100

Taj odnos je otkrio pravi problem. Poslovno gledano, upitu nisu trebali milioni redova, ali je način pristupa bazi terao nepotreban prolazak pre nego što je tražena grupa mogla da se vrati. Aplikacija je tražila 100 korisnih zapisa, a sistem za skladištenje je morao da prođe kroz mnogo veći deo podataka.

„Brzi upiti obično nisu stvar vraćanja manje redova. Stvar je u tome da baza pregleda manje redova.“

Rešenje je bio složeni indeks

Izmena je bila mala, ali je direktno odgovarala načinu na koji aplikacija pristupa podacima. Umesto generičkog indeksa, novi indeks je spojio kolonu za filtriranje i kolonu za redosled.

CREATE INDEX idx_metadata_exist_id
ON processed_image(metadata_exist, id);

Sa ovim indeksom baza je mogla da pronađe redove gde je metadata_exist = 0, zadrži ih poređane po id i stane čim dostigne limit grupe. To je skupo čitanje pretvorilo u ciljani prolazak kroz indeks.

Baza više nije morala da pregleda veliki deo tabele da bi vratila malu grupu. Mogla je da prođe kroz relevantan opseg indeksa i vrati tražene redove sa mnogo manje posla.

Rezultat je bio veći od same izmene

Razlika je bila velika. Upit koji je ranije trošio sekunde sada se završavao za milisekunde, jer baza više nije radila nepotreban prolazak.

Pre:
Vreme izvršenja: 4,8 sekundi
Pregledano redova: 2,4 miliona

Posle:
Vreme izvršenja: 35 milisekundi
Pregledano redova: 100

Poboljšanje nije pogodilo samo jedan upit. Kada je baza prestala da troši vreme na neefikasna čitanja, ceo sistem oko nje postao je predvidiviji. „Hladni“ zahtevi su se brže završavali, pozadinski procesi su se stabilizovali, zagrevanje keša je postalo jeftinije, a latencija zahteva ujednačenija pod opterećenjem.

Zato spori upiti retko utiču samo na sebe. Oni opterećuju ceo sistem: troše resurse baze, odlažu zavisne poslove i povećavaju nepredvidivost izvršenja zahteva.

Zašto keširanje nije sakrilo problem

Platforma je već imala keširanje, ali ono nije uklonilo uzrok. „Hladne“ putanje su i dalje morale da idu do baze, pozadinskim procesima su trebali sveži podaci, a poništavanje keša je značilo da će se neke skupe operacije uvek vraćati na kritičnu putanju.

Redis može da smanji ponovljeni posao, ali ne može neefikasan pristup da učini efikasnim. Ako sistem i dalje zavisi od sporog upita pri zagrevanju keša, pozadinskoj obradi ili generisanju svežih metapodataka, usko grlo ostaje. Možda se javlja ređe, ali kada se javi, i dalje pogađa produkciju.

Ovo je važna razlika između skrivanja latencije i njenog uklanjanja. Keširanje može biti odličan sloj optimizacije, ali ne sme da postane zamena za razumevanje načina na koji baza zaista opslužuje aplikaciju.

Zamka skaliranja

Bez profilisanja, ovaj problem je lako mogao da dovede do pogrešnog rešenja. Tim je mogao da poveća kapacitet servera, doda replike, proširi keširanje ili prebaci više posla u pozadinske procese. Svaka od tih izmena mogla je privremeno da ublaži simptome, ali nijedna ne bi ispravila neefikasan prolazak kroz bazu.

Skaliranje ima vrednost kada sistem već efikasno koristi resurse. Skaliranje neefikasnog pristupa obično povećava operativne troškove i složenost arhitekture, dok prvobitno usko grlo ostaje netaknuto.

U ovom slučaju, optimizacija sa najvećim efektom nije bila veća infrastruktura. Bila je to izmena koja je postojeću bazu oslobodila nepotrebnog posla.

Čemu nas ova studija slučaja uči

Glavna lekcija nije da svakom sporom upitu treba još jedan indeks. Prava lekcija je da produkcijski sistemi mogu da izgledaju optimizovano, a da i dalje sadrže jedan način pristupa koji dominira performansama. Keširanje, pozadinski procesi, CDN-ovi i podešavanje okruženja su korisni, ali ne uklanjaju potrebu za analizom planova upita.

Efikasna optimizacija baze počinje merenjem. Korisna pitanja su kako se podaci filtriraju, kako se sortiraju, koliko redova se pregleda, da li sortiranje može da se izbegne i da li baza može da stane ranije, čim pronađe traženi skup rezultata.

Dobar složeni indeks nije nasumična magija za performanse. On opisuje putanju kojom baza treba da prođe kroz podatke. Kada ta putanja odgovara stvarnom opterećenju aplikacije, razlika u performansama može biti dramatična.

Zaključak

Moderni inženjering brzo poseže za složenim rešenjima. Distribuirani sistemi, keširanje na edge-u, horizontalno skaliranje i asinhrona obrada imaju svoje mesto. Ali neka od najvrednijih poboljšanja performansi i dalje dolaze iz dubokog razumevanja jednog upita.

U ovom slučaju, jedan indeks koji je nedostajao učinio je upit ka bazi skupljim od svega ostalog u zahtevu zajedno. Rešenje je bilo jednostavno, ali je do njega dovelo profilisanje, analiza upita i pažnja prema tome kako se baza zaista kreće kroz podatke.

Najteži deo inženjeringa performansi nije uvek primena rešenja. Često je to pronalaženje pravog uskog grla pre nego što se oko pogrešnog problema doda još infrastrukture.

Brži sistemi kroz merljivu optimizaciju

RankSoft pomaže biznisima da poboljšaju performanse kroz profilisanje, optimizaciju baze, bezbednije puštanje izmena i merljiva poboljšanja sistema.

Zakaži sastanak →