PostgreSQL rašome apie sublight: 1 host, 1 day, 1TB

Neseniai aš jums pasakiau, kaip, naudojant standartinius receptus padidinti SQL skaitymo užklausų našumą iš PostgreSQL duomenų bazės. Šiandien mes kalbėsime apie tai, kaip įrašymas gali būti atliktas efektyviau duomenų bazėje, nenaudojant jokių konfigūracijos „tvistų“ – tiesiog teisingai sutvarkius duomenų srautus.

PostgreSQL rašome apie sublight: 1 host, 1 day, 1TB

#1. Skyrius

Straipsnis apie tai, kaip ir kodėl verta organizuoti pritaikytas skaidymas „teoriškai“ jau buvo, čia kalbėsime apie kai kurių metodų taikymo praktiką mūsų viduje stebėjimo paslauga šimtams PostgreSQL serverių.

"Praėjusių dienų dalykai..."

Iš pradžių, kaip ir bet kuris MVP, mūsų projektas prasidėjo gana nedideliu krūviu – stebėjimas buvo vykdomas tik dešimties svarbiausių serverių, visos lentelės buvo gana kompaktiškos... Tačiau laikui bėgant stebimų hostų vis daugėjo. , ir dar kartą bandėme ką nors padaryti su vienu iš stalai 1.5TB dydžio, supratome, kad nors galima ir toliau taip gyventi, bet tai buvo labai nepatogu.

Laikai buvo beveik kaip epiniai laikai, skirtingos PostgreSQL 9.x versijos buvo svarbios, todėl visas skaidymas turėjo būti atliekamas „rankiniu būdu“ – per lentelės paveldėjimas ir trigeriai maršrutizavimas su dinamine EXECUTE.

PostgreSQL rašome apie sublight: 1 host, 1 day, 1TB
Gautas sprendimas pasirodė pakankamai universalus, kad jį būtų galima išversti į visas lenteles:

  • Buvo paskelbta tuščia pirminė lentelė „antraštė“, kurioje viskas aprašyta būtini indeksai ir trigeriai.
  • Įrašas kliento požiūriu buvo padarytas „šakninėje“ lentelėje ir viduje naudojant maršruto parinkimo trigeris BEFORE INSERT įrašas buvo „fiziškai“ įterptas į reikiamą skyrių. Jei dar tokio dalyko nebuvo, pagavome išimtį ir...
  • … naudojant CREATE TABLE ... (LIKE ... INCLUDING ...) buvo sukurtas pagal pirminės lentelės šabloną skyrių su norimos datos apribojimukad gavus duomenis, skaitymas būtų atliekamas tik jame.

PG10: pirmasis bandymas

Tačiau skaidymas per paveldėjimą istoriškai nebuvo tinkamas aktyviam rašymo srautui ar daugybei antrinių skaidinių. Pavyzdžiui, galite prisiminti, kad reikiamo skyriaus pasirinkimo algoritmas turėjo kvadratinis sudėtingumas, kad veikia su 100+ sekcijų, patys suprantate kaip...

PG10 ši situacija buvo labai optimizuota įdiegus palaikymą vietinis skaidymas. Todėl iškart po saugyklos perkėlimo iš karto bandėme ją pritaikyti, bet...

Kaip paaiškėjo išnagrinėjus vadovą, šioje versijoje natūraliai suskaidyta lentelė yra:

  • nepalaiko indeksų aprašymų
  • nepalaiko jame veikiančių trigerių
  • negali būti kieno nors "palikuonis"
  • nepalaiko INSERT ... ON CONFLICT
  • negali automatiškai generuoti sekcijos

Sulaukę skaudaus smūgio grėbliu į kaktą, supratome, kad nepakeitus paraiškos neapsieis, ir tolesnius tyrimus atidėjome pusmečiui.

PG10: antra galimybė

Taigi, mes pradėjome vienas po kito spręsti iškilusias problemas:

  1. Kadangi sukelia ir ON CONFLICT Pastebėjome, kad mums jų vis tiek reikia čia ir ten, todėl padarėme tarpinį etapą, kad juos išspręstume tarpinio serverio lentelė.
  2. Atsikratė „maršruto“ trigeriuose – tai yra nuo EXECUTE.
  3. Jie išėmė jį atskirai šablono lentelė su visais indeksaiskad jų net nebūtų tarpinio serverio lentelėje.

PostgreSQL rašome apie sublight: 1 host, 1 day, 1TB
Galiausiai, po viso šito, pagrindinę lentelę suskirstėme savaime. Naujos skilties kūrimas vis dar paliekamas programos sąžinei.

„Pjovimo“ žodynai

Kaip ir bet kurioje analitinėje sistemoje, mes taip pat turėjome "faktai" ir "kirpimai" (žodynai). Mūsų atveju jie veikė, pavyzdžiui, šablono korpusas panašios lėtos užklausos arba pačios užklausos tekstas.

„Faktai“ jau seniai buvo skirstomi pagal dieną, tad pasenusias skiltis ramiai ištrynėme, ir jos mums netrukdė (logai!). Bet kilo problema su žodynais...

Negalima sakyti, kad jų buvo daug, bet maždaug 100 TB „faktų“ leido sukurti 2.5 TB žodyną. Negalite patogiai nieko ištrinti iš tokios lentelės, negalite jos pakankamai laiku suspausti, o rašymas į ją pamažu lėtėjo.

Kaip žodynas... jame kiekvienas įrašas turi būti pateiktas tiksliai vieną kartą... ir tai teisinga, bet!.. Niekas mums netrukdo turėti atskiras žodynas kiekvienai dienai! Taip, tai suteikia tam tikro pertekliaus, bet leidžia:

  • rašyti/skaityti greičiau dėl mažesnio skyriaus dydžio
  • sunaudoja mažiau atminties dirbant su kompaktiškesniais indeksais
  • saugoti mažiau duomenų dėl galimybės greitai pašalinti pasenusias

Dėl viso komplekso priemonių CPU apkrova sumažėjo ~30%, disko apkrova ~50%:

PostgreSQL rašome apie sublight: 1 host, 1 day, 1TB
Tuo pačiu metu mes ir toliau lygiai tą patį įrašėme į duomenų bazę, tik su mažesne apkrova.

#2. Duomenų bazės evoliucija ir pertvarkymas

Taigi apsisprendėme tuo, ką turime kiekviena diena turi savo skyrių su duomenimis. Tiesą sakant, CHECK (dt = '2018-10-12'::date) — ir yra skaidymo raktas bei sąlyga, kad įrašas pateks į konkrečią sekciją.

Kadangi visos mūsų paslaugos ataskaitos yra sukurtos konkrečios datos kontekste, jų indeksai nuo „neskirstymo laikų“ buvo visų tipų (serveris, Data, plano šablonas), (serveris, Data, plano mazgas), (Data, klaidų klasė, serveris), ...

Bet dabar jie gyvena kiekviename skyriuje savo kopijas kiekvienas toks indeksas... Ir kiekvienoje sekcijoje data yra konstanta... Pasirodo, dabar mes esame kiekviename tokiame indekse tiesiog įveskite konstantą kaip vienas iš laukų, kuris padidina tiek jo apimtį, tiek paieškos laiką, bet neduoda jokio rezultato. Grėblį jie paliko sau, oi...

PostgreSQL rašome apie sublight: 1 host, 1 day, 1TB
Optimizavimo kryptis akivaizdi – paprasta pašalinti datos lauką iš visų indeksų ant atskirtų lentelių. Atsižvelgiant į mūsų apimtis, pelnas yra maždaug 1TB per savaitę!

Dabar atkreipkime dėmesį, kad šį terabaitą vis tiek reikėjo kažkaip įrašyti. Tai yra, mes taip pat diskas dabar turėtų įkelti mažiau! Šiame paveikslėlyje aiškiai matomas valymo, kuriam skyrėme savaitę, efektas:

PostgreSQL rašome apie sublight: 1 host, 1 day, 1TB

#3. „Paskirstyti“ didžiausią apkrovą

Viena iš didžiausių pakrautų sistemų bėdų yra perteklinis sinchronizavimas kai kurios operacijos, kurioms to nereikia. Kartais „nes nepastebėdavo“, kartais „taip buvo lengviau“, bet anksčiau ar vėliau tenka atsikratyti.

Padidinkime ankstesnį paveikslėlį ir pamatysime, kad turime diską "siurbliai" po apkrova su dviguba amplitudė tarp gretimų mėginių, kas aiškiai „statistiškai“ neturėtų įvykti atliekant tokį operacijų skaičių:

PostgreSQL rašome apie sublight: 1 host, 1 day, 1TB

Tai gana lengva pasiekti. Jau pradėjome stebėti beveik 1000 serverių, kiekvieną apdoroja atskira loginė gija, ir kiekviena gija iš naujo nustato sukauptą informaciją, kuri tam tikru dažnumu bus siunčiama į duomenų bazę, maždaug taip:

setInterval(sendToDB, interval)

Problema čia slypi būtent tame, kad visos gijos prasideda maždaug tuo pačiu metu, todėl jų siuntimo laikas beveik visada sutampa „iki taško“. Oi #2...

Laimei, tai gana lengva ištaisyti, pridedant „atsitiktinį“ paleidimą pagal laiką:

setInterval(sendToDB, interval * (1 + 0.1 * (Math.random() - 0.5)))

#4. Mes talpiname tai, ko mums reikia

Trečioji tradicinė didelės apkrovos problema yra nėra talpyklos kur jis yra galėtų būti.

Pavyzdžiui, mes suteikėme galimybę analizuoti plano mazgus (visa tai Seq Scan on users), bet iš karto pagalvokite, kad jie didžiąja dalimi yra vienodi – jie pamiršo.

Ne, žinoma, į duomenų bazę vėl nieko neįrašoma, tai nutraukia trigerį INSERT ... ON CONFLICT DO NOTHING. Tačiau šie duomenys vis tiek pasiekia duomenų bazę, ir tai nereikalinga skaitykite, kad patikrintumėte, ar nėra konflikto turi daryti. Oi #3...

Į duomenų bazę siunčiamų įrašų skaičiaus skirtumas prieš įjungus / po talpyklos yra akivaizdus:

PostgreSQL rašome apie sublight: 1 host, 1 day, 1TB

Ir tai yra lydimas sandėliavimo apkrovos sumažėjimas:

PostgreSQL rašome apie sublight: 1 host, 1 day, 1TB

Iš viso

„Terabaitas per dieną“ tiesiog skamba baisiai. Jei viską darote teisingai, tai yra teisinga 2^40 baitų / 86400 sekundžių = ~12.5 MB/skad net darbalaukio IDE varžtai laikėsi. 🙂

Bet jei rimtai, net ir dešimteriopai „pakrypus“ apkrovai per dieną, galite lengvai patenkinti šiuolaikinių SSD galimybes.

PostgreSQL rašome apie sublight: 1 host, 1 day, 1TB

Šaltinis: www.habr.com

Добавить комментарий