Andmete pÀringute optimeerimine B2B teenuse nÀitel ehitajatele

Kuidas kasvatada andmebaasi pĂ€ringute arvu kĂŒmme korda, mitte liikudes jĂ”udsamale serverile ja sĂ€ilitada sĂŒsteemi töövĂ”ime? RÀÀgin, kuidas me vĂ”itlesime andmebaasi jĂ”udluse languse vastu, kuidas optimeerisime SQL-pĂ€ringuid, et teenindada vĂ”imalikult palju kasutajaid ja mitte suurendada arvutusressursside kulusid.

Ma teen teenuseid ehitusettevĂ”tete Ă€riprotsesside haldamiseks. Meiega töötab ligikaudu 3000 ettevĂ”tet. Iga pĂ€ev kasutab meie sĂŒsteemi ĂŒle 10 000 inimese 4-10 tundi. See lahendab erinevaid ĂŒlesandeid, sealhulgas planeerimine, teavitamine, hoiatamine, valideerimine jne. Me kasutame PostgreSQL 9.6. Andmebaasis on meil umbes 300 tabelit ja iga pĂ€ev tuleb sinna kuni 200 miljonit pĂ€ringut (10 000 erinevat). Keskmiselt on meil 3-4 tuhat pĂ€ringut sekundis, kĂ”ige aktiivsematel hetkedel ĂŒle 10 000 pĂ€ringu sekundis. Suur osa pĂ€ringutest on OLAP. Uute andmete lisamine, muudatused ja kustutamised on oluliselt vĂ€hem, seega OLTP koormus on suhteliselt vĂ€ike. KĂ”iki neid numbreid olen vĂ€lja toonud, et teil oleks vĂ”imalik hinnata meie projekti ulatust ning mĂ”ista, kui kasulik meie kogemus vĂ”ib teile olla.

Esimene pilt. LĂŒĂŒriiline

Kui me arenduse alustasime, ei mĂ”elnud me eriti sellele, milline koormus langeb andmebaasile ja mida me teeme, kui server enam ei suuda. Andmebaasi projekteerimisel jĂ€rgnesime ĂŒldistele soovitustele ja pĂŒĂŒdsime mitte endale jalga tulistada, kuid edasi liikudes olid ĂŒldised nĂ”uanded, nagu "Ă€rge kasutage mustrit Entity Attribute Values Me ei olnudun. Me projekteerisime lĂ€htudes normaliseerimise pĂ”himĂ”tetest, vĂ€ltides andmete liigset kordumist ning ei muretsenud teatud pĂ€ringute kiirendamise pĂ€rast. Kui esimesed kasutajad tulid, kohtasime jĂ”udlusprobleeme. Nagu tavaliselt, olime tĂ€iesti selleks ette valmistamata. Esimesed probleemid olid lihtsad. Enamasti lahenesid asjad uue indeksi lisamisega. Kuid tuli hetk, mil lihtsad tĂ€iendused enam ei töötanud. Teades, et meie kogemused ei piisa ja meil on ĂŒha raskem mĂ”ista, mis probleemide pĂ”hjused on, palkasime spetsialiste, kes aitasid meil serveri korralikult seadistada, monitorimise ĂŒhendada ning nĂ€itasid, kuhu vaadata, et saada. statistika.

Teine pilt. Statistika

Nii et meil on umbes 10 000 erinevat pÀringut, mis meie andmebaasis tÀidetakse ööpÀevas. Nendest 10 000-st on koletised, mida tÀidetakse 2-3 miljonit korda keskmise tÀitmisajaga 0,1-0,3 ms, ja on pÀringud, mille keskmine tÀitmisaja on 30 sekundit ja mis kutsutakse esile 100 korda pÀevas.

Kuna 10 tuhat pĂ€ringut polnud vĂ”imalik optimeerida, otsustasime, kuhu suunata jĂ”upingutused andmebaasi jĂ”udluse tĂ”stmiseks. PĂ€rast mitmeid iteratsioone hakkasime pĂ€ringud liigitama tĂŒĂŒpide jĂ€rgi.

TOP pÀringud

Need on kĂ”ige raskemad pĂ€ringud, mis vĂ”tavad kĂ”ige rohkem aega (kogu aeg). Need on pĂ€ringud, mida kas kutsutakse vĂ€ga sageli vĂ”i pĂ€ringud, mis vajavad vĂ€ga pikka tĂ€itmist (pikad ja sagedased pĂ€ringud on juba varasematel iteratsioonidel kiirusvĂ”itluses optimeeritud). Kokku kulutab server nende tĂ€itmiseks kĂ”ige rohkem aega. Oluline on eristada top pĂ€ringud ĂŒldise tĂ€itmise aja jĂ€rgi ja eraldi IO aja jĂ€rgi. Selliste pĂ€ringute optimeerimise viisid on veidi erinevad.

KĂ”igi ettevĂ”tete tavaline praktika on töötada TOP-pĂ€ringutega. Need on vĂ€he, ĂŒhe pĂ€ringu optimeerimine vĂ”ib vabastada 5-10% ressursse. Siiski, projekti „kĂŒpsemise” kĂ€igus muutub TOP-pĂ€ringute optimeerimine jĂ€rjest keerukamaks ĂŒlesandeks. KĂ”ik lihtsad meetodid on juba katsetatud ja isegi kĂ”ige „raske” pĂ€ring kasutab „ainult” 3-5% ressursse. Kui TOP-pĂ€ringud kokku kulutavad vĂ€hem kui 30-40% ajast, siis olete tĂ”enĂ€oliselt juba pingutanud selle nimel, et need töötaksid kiiresti, ja nĂŒĂŒd on aeg liikuda jĂ€rgmise grupi pĂ€ringute optimeerimisele.
JÀÀb vastata kĂŒsimusele, kui palju kĂ”rgeid pĂ€ringuid sellesse gruppi kuulutada. Ma vĂ”tan tavaliselt mitte vĂ€hem kui 10, kuid mitte rohkem kui 20. Proovin, et esimese ja viimase pĂ€ringu aega TOP-grupis erineks mitte rohkem kui 10 korda. St kui pĂ€ringute töötlemise aeg langeb jĂ€rsult 1. kohalt 10. kohale, siis vĂ”tan TOP-10, kui langus on sujuvam, siis suurendan grupi suurust 15 vĂ”i 20-ni.
Andmete pÀringute optimeerimine B2B teenuse nÀitel ehitajatele

Keskmikud (medium)

Need on kĂ”ik pĂ€ringud, mis lĂ€hevad kohe TOP-i jĂ€rel, vĂ€lja arvatud viimased 5–10%. Just nende pĂ€ringute optimeerimises peitub sageli vĂ”imalus serveri jĂ”udlust mĂ€rgatavalt tĂ”sta. Need pĂ€ringud vĂ”ivad moodustada kuni 80%. Kuid isegi kui nende osakaal ĂŒletab 50%, on aeg neile tĂ”sisemalt pilk heita.

SabapÀringud (tail)

Nagu öeldud, lĂ€hevad need pĂ€ringud viimaste hulka ja nendele kulub 5–10% ajast. Nendest vĂ”ib unustada ainult siis, kui te ei kasuta automaatseid analĂŒĂŒsivahendeid; siis vĂ”ib nende optimeerimine samuti odavalt kĂ€ia.

Kuidas hinnata iga gruppi?

Kasutangi SQL-pĂ€ringut, mis aitab sellist hindamist teha PostgreSQL-is (olen kindel, et paljudele muudele andmebaasisĂŒsteemidele on vĂ”imalik kirjutada sarnane pĂ€ring).

SQL-pÀring TOP-MEDIUM-TAIL gruppide suuruse hindamiseks

SELECT sum(time_top) AS sum_top, sum(time_medium) AS sum_medium, sum(time_tail) AS sum_tail
FROM
(
  SELECT CASE WHEN rn  20 AND rn  800              THEN tt_percent ELSE 0 END AS time_tail
  FROM (
    SELECT total_time / (SELECT sum(total_time) FROM pg_stat_statements) * 100 AS tt_percent, query,
    ROW_NUMBER () OVER (ORDER BY total_time DESC) AS rn
    FROM pg_stat_statements
    ORDER BY total_time DESC
  ) AS t
)
AS ts

PĂ€ringu tulemused - kolm veergu, millest igaĂŒks sisaldab protsenti ajast, mis kulub selle grupi pĂ€ringute töötlemiseks. PĂ€ringu sees on kaks numbrit (minu juhtumi jĂ€rgi on need 20 ja 800), mis eraldavad ĂŒhe grupi pĂ€ringud teistest.

Nii umbes jagunevad pÀringute osakaalid optimeerimise alguses ja praegu.

Andmete pÀringute optimeerimine B2B teenuse nÀitel ehitajatele

Diagrammist on nÀha, et TOP pÀringute osakaal on jÀrsult vÀhenenud, kuid "keskmike" osakaal on suurenenud.
Alguses sattusid TOP pĂ€ringutesse ilmsed vead. Aja jooksul lastehaigused kadusid, TOP pĂ€ringute osakaal vĂ€henes ja tuli pingutada ĂŒha rohkem, et aeglaseid pĂ€ringuid kiirendada.

PÀringute tekstide saamiseks kasutame jÀrgmist pÀringut

SELECT * FROM (
  SELECT ROW_NUMBER () OVER (ORDER BY total_time DESC) AS rn, total_time / (SELECT sum(total_time) FROM pg_stat_statements) * 100 AS tt_percent, query
  FROM pg_stat_statements
  ORDER BY total_time DESC
) AS T
WHERE
rn  20 AND rn  800  -- TAIL

Siin on nimekiri kÔige sagedamini kasutatud meetoditest, mis aitasid meil TOP pÀringute kiirus tÔsta:

  • SĂŒsteemi ĂŒmberkujundamine, nĂ€iteks teate loogika ĂŒlekandmine sĂ”numi vahemenetlusele, mitte perioodilised pĂ€ringud andmebaasi.
  • Indeksite lisamine vĂ”i muutmine
  • ORM pĂ€ringute ĂŒmberkirjutamine puhtaks SQL-iks
  • Andmete paindliku laadimise loogika ĂŒmberkirjutamine
  • Andmete denormaliseerimise kaudu vahemĂ€llu salvestamine. NĂ€iteks, meil on tabelite seos Tarne -> Arve -> Taotlus -> Soovitus. See tĂ€hendab, et iga tarne on seotud taotlusega lĂ€bi teiste tabelite. Et mitte siduda kĂ”iki tabeleid igas pĂ€ringus, oleme dubleerinud viite taotlusele Tarne tabelis.
  • Staatiliste tabelite ja harva muutuvate tabelite vahemĂ€llu salvestamine programmi mĂ€lu.

MĂ”nikord tĂ”id muudatused kaasa ulatusliku uuenduse, kuid andsid 5-10% sĂŒsteemi koormuse vĂ€henemist ja olid Ă”igustatud. Aja jooksul sai tulu ĂŒha vĂ€iksemaks ja uuendus muutus ĂŒha tĂ”siseks.

Siis pöörasime tĂ€helepanu teisele pĂ€ringute grupile – keskmike grupp. Selles on palju rohkem pĂ€ringuid ja tundus, et kogu grupi analĂŒĂŒs vĂ”ib vĂ”tta vĂ€ga palju aega. Siiski osutus enamik pĂ€ringutest optimeerimiseks vĂ€ga lihtsaks ja paljud probleemid kordusid kĂŒmneid kordi erinevates variantides. Siin on mĂ”ned tĂŒĂŒpilised optimeerimised, mida rakendasime kĂŒmnetele sarnastele pĂ€ringutele, ja iga optimeeritud pĂ€ringute grupp vĂ€hendas andmebaasi koormust 3-5%.

  • Kasutame EXISTS-i, mitte COUNT-i ja tĂ€ielikku tabeli skaneerimist.
  • Vabanesime DISTINCT-ist (ĂŒhtset retsepti pole, aga mĂ”nikord on kerge sellest loobuda, kiirendades pĂ€ringut 10–100 korda).

    NĂ€iteks, kui soovime kĂŒsida kĂ”iki juhte suurel kohaletoimetamiste tabelil (DELIVERY).

    SELECT DISTINCT P.ID, P.FIRST_NAME, P.LAST_NAME
    FROM DELIVERY D JOIN PERSON P ON D.DRIVER_ID = P.ID
    

    tegime pÀringu suhteliselt vÀikesele tabelile PERSON.

    SELECT P.ID, P.FIRST_NAME, P.LAST_NAME
    FROM PERSON
    WHERE EXISTS(SELECT D.ID FROM DELIVERY WHERE D.DRIVER_ID = P.ID)
    

    Tundub, et kasutasime korreleerivat alamkĂŒsitlust, kuid see annab ĂŒle 10-kordse kiiruskasvu.

  • Paljuski loobusime COUNT-ist tĂ€ielikult ja
    asendasime selle umbkaudse vÀÀrtuse arvutamisega.
  • asetatakse
    UPPER(s) LIKE JOHN%’ 
    

    kasutame

    s ILIKE “John%”
    

Iga konkreetne pĂ€ring suudeti mĂ”nikord kiiruselt tĂ”sta 3-1000 korda. Kuigi tulemused olid muljetavaldavad, tundus alguses, et pole mĂ”tet optimeerida pĂ€ringut, mis kestab 10 ms, kuulub kolmanda saja kĂ”ige keerukama pĂ€ringu hulka ja ĂŒldise koormuse ajal veedab andmebaasis ainult sajandik protsenti. Rakendades sama retsepti rĂŒhmale sarnastele pĂ€ringutele suutsime saavutada mitme protsendi vĂ”rra paremad tulemused. Aja sÀÀstmiseks kĂ”igi sadade pĂ€ringute kĂ€sitsi lĂ€bi vaatamist, kirjutasime mĂ”ned lihtsad skriptid, mis regulaaravalduste abil leidsid sarnased pĂ€ringud. LĂ”puks vĂ”imaldas automaatne pĂ€ringute grupi otsing meil veelgi paremini oma tulemuslikkust tĂ”sta, kulutades sellele tagasihoidlikult aega.

Oleme juba kolm aastat töötanud sama riistvaraga. Keskmine koormus on umbes 30%, tipukoormuse ajal ulatub see 70%ni. KĂŒsimuste ja kasutajate arv on kasvanud umbes kĂŒmme korda. Ja see kĂ”ik on tĂ€nu pidevale nende TOP-MEDIUM pĂ€ringugruppide jĂ€lgimisele. Nii pea, kui mĂ”ni uus pĂ€ring ilmub TOP-gruppi, analĂŒĂŒsime seda kohe ja pĂŒĂŒame kiirusest maksimumi vĂ”tta. MEDIUM-gruppi vaatame kord nĂ€dalas ĂŒle pĂ€ringuanalĂŒĂŒsi skriptide abil. Kui leiame uusi pĂ€ringuid, mida me juba teame, kuidas optimeerida, muudame neid kiiresti. MĂ”nikord avastame uusi optimeerimise viise, mida saab rakendada kohe mitmele pĂ€ringule.

Meie prognooside kohaselt suudab praegune server taluda kasutajate arvu suurenemist veel 3-5 korda. TĂ”si, meil on veel ĂŒks trump varrukas – me ei ole veel SELECT-pĂ€ringuid peegeldusele viinud, nagu soovitatakse. Kuid me ei tee seda teadlikult, kuna soovime esmalt tĂ€ielikult Ă€ra kasutada „nutika“ optimeerimise vĂ”imalusi, enne kui lĂŒlitame sisse „raskema suured relvad“.
Kriitiline ĂŒlevaade tehtud tööst vĂ”ib viidata, et tasub kaaluda vertikaalset skaleerimist. Osta vĂ”imsam server, selle asemel et raisata spetsialistide aega. Server ei pruugi olla kallis, eriti kuna meie vertikaalse skaleerimise piirangud pole veel ammendunud. Siiski on kĂŒmme korda kasvanud vaid pĂ€ringute arv. Aastate jooksul on sĂŒsteemi funktsionaalsus suurenenud ja nĂŒĂŒd on pĂ€ringute variantide arv kasvanud. Funktsionaalsus, mis oli, saab tĂ€iendava efektiivsuse tĂ€nu vahemĂ€llu, kasutades vĂ€hem pĂ€ringute arvu, kuid vĂ€hem tĂ”husate pĂ€ringute asemel. Seega vĂ”ib julgelt korrutada veel 5, et saada reaalne kiirusetegur. Seega vĂ”ib kĂ”ige tagasihoidlikumate arvutuste kohaselt öelda, et kiirusetegur on vĂ€hemalt 50 korda. Serveri vertikaalne skaleerimine 50 korda oleks olnud kallim. Eriti arvestades, et kord tehtud optimeerimine töötab pidevalt, samas kui renditud serveri arve tuleb iga kuu.

Allikas: habr.com

Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster