V PostgreSQL pišemo na sublight: 1 host, 1 dan, 1TB

Pred kratkim sem vam povedal, kako z uporabo standardnih receptov povečajte zmogljivost bralnih poizvedb SQL iz baze podatkov PostgreSQL. Danes bomo govorili o tem, kako snemanje je lahko bolj učinkovito v podatkovni zbirki brez uporabe kakršnih koli "zasukov" v konfiguraciji - preprosto s pravilno organizacijo tokov podatkov.

V PostgreSQL pišemo na sublight: 1 host, 1 dan, 1TB

#1. Sekcija

Članek o tem, kako in zakaj se splača organizirati uporabljeno particioniranje "v teoriji" je že bilo, tukaj bomo govorili o praksi uporabe nekaterih pristopov znotraj našega storitev spremljanja za stotine strežnikov PostgreSQL.

"Stvari preteklih dni ..."

Sprva se je naš projekt, tako kot vsak MVP, začel pod dokaj majhno obremenitvijo - nadzor je potekal le za deset najbolj kritičnih strežnikov, vse tabele so bile razmeroma kompaktne ... Toda s časom je število nadzorovanih gostiteljev postajalo vedno večje. , in spet smo poskušali nekaj narediti z enim od mize velikosti 1.5 TB, smo ugotovili, da je bilo tako, čeprav je mogoče še naprej živeti, zelo neprijetno.

Časi so bili skoraj kot epski časi, ustrezne so bile različne različice PostgreSQL 9.x, zato je bilo treba vse particioniranje izvesti "ročno" - prek dedovanje tabel in sprožilci usmerjanje z dinamičnim EXECUTE.

V PostgreSQL pišemo na sublight: 1 host, 1 dan, 1TB
Dobljena rešitev se je izkazala za dovolj univerzalno, da jo je mogoče prevesti v vse tabele:

  • Navedena je bila prazna nadrejena tabela "glava", ki je vse opisala potrebne indekse in sprožilce.
  • Zapis z vidika naročnika je bil narejen v “root” tabeli in interno z uporabo sprožilec usmerjanja BEFORE INSERT zapis je bil "fizično" vstavljen v zahtevano rubriko. Če tega še ni bilo, smo ujeli izjemo in...
  • … z uporabo CREATE TABLE ... (LIKE ... INCLUDING ...) je bila ustvarjena na podlagi predloge nadrejene tabele rubriko z omejitvijo na želeni datumtako da se ob pridobivanju podatkov branje izvaja samo v njih.

PG10: prvi poskus

Toda particioniranje z dedovanjem v preteklosti ni bilo najbolj primerno za obravnavo aktivnega zapisovalnega toka ali velikega števila podrejenih particij. Na primer, lahko se spomnite, da je imel algoritem za izbiro zahtevanega razdelka kvadratna kompleksnost, da deluje s 100+ razdelki, sami razumete, kako ...

V PG10 je bila ta situacija močno optimizirana z uvedbo podpore izvorno particioniranje. Zato smo ga takoj poskusili uporabiti takoj po selitvi pomnilnika, vendar ...

Kot se je izkazalo po kopanju po priročniku, je izvorno particionirana tabela v tej različici:

  • ne podpira opisov kazal
  • ne podpira sprožilcev na njem
  • ne more biti nikogaršnji "potomec"
  • ne podpirajo INSERT ... ON CONFLICT
  • ne more samodejno ustvariti razdelka

Po bolečem udarcu z grabljami v čelo smo ugotovili, da brez spreminjanja aplikacije ne bo šlo, in nadaljnje raziskave odložili za šest mesecev.

PG10: druga priložnost

Tako smo začeli reševati težave, ki so se pojavile eno za drugo:

  1. Ker sproži in ON CONFLICT Ugotovili smo, da jih tu in tam še potrebujemo, zato smo naredili vmesno fazo, da jih obdelamo proxy tabela.
  2. Znebil se "usmerjanja" v sprožilcih – torej od EXECUTE.
  3. Ločeno so ga vzeli ven tabela predloge z vsemi indeksitako da sploh niso prisotni v proxy tabeli.

V PostgreSQL pišemo na sublight: 1 host, 1 dan, 1TB
Končno, po vsem tem, smo glavno mizo razdelili izvorno. Izdelava novega razdelka je še vedno prepuščena vesti aplikacije.

"Žaganje" slovarjev

Kot v vsakem analitičnem sistemu smo imeli tudi pri nas "dejstva" in "rezi" (slovarji). V našem primeru so v tej funkciji delovali npr. telo predloge podobne počasne poizvedbe ali besedilo same poizvedbe.

“Dejstva” so bila že dolgo razdeljena po dnevih, zato smo zastarele rubrike mirno brisali in nas niso motile (dnevniki!). Je bil pa problem s slovarji...

Ne rečem, da jih je bilo veliko, ampak približno 100 TB "dejstev" je povzročilo 2.5 TB slovarja. Iz take tabele ne moreš nič priročno izbrisati, stisniti je ne moreš v ustreznem času, pisanje vanjo pa je postopoma postalo počasnejše.

Kot slovar ... v njem mora biti vsak vnos predstavljen natanko enkrat ... in to je prav, vendar!.. Nihče nam ne preprečuje, da bi imeli za vsak dan poseben slovar! Da, to prinaša določeno redundanco, vendar omogoča:

  • pisati/brati hitreje zaradi manjše velikosti odseka
  • porabijo manj pomnilnika z delom s kompaktnejšimi indeksi
  • shrani manj podatkov zaradi zmožnosti hitre odstranitve zastarelih

Kot rezultat celotnega kompleksa ukrepov Obremenitev procesorja se je zmanjšala za ~30%, obremenitev diska za ~50%:

V PostgreSQL pišemo na sublight: 1 host, 1 dan, 1TB
Hkrati smo v bazo še naprej zapisovali popolnoma isto stvar, le z manjšo obremenitvijo.

#2. Razvoj baze podatkov in preoblikovanje

Tako smo se odločili za to, kar imamo vsak dan ima svoj del s podatki. Pravzaprav, CHECK (dt = '2018-10-12'::date) — in tam je particijski ključ in pogoj, da zapis spada v določen razdelek.

Ker so vsa poročila v naši storitvi zgrajena v kontekstu določenega datuma, so bili indeksi zanje od »neparticioniranih časov« vseh vrst (strežnik, Datum, Predloga načrta), (strežnik, Datum, vozlišče načrta), (Datum, razred napak, strežnik), ...

Zdaj pa živijo na vsakem odseku svoje kopije vsak tak indeks ... In znotraj vsakega razdelka datum je stalnica... Izkazalo se je, da smo zdaj v vsakem takem indeksu preprosto vnesite konstanto kot eno od polj, kar poveča obseg in čas iskanja po njem, vendar ne prinese nobenega rezultata. Grablje so pustili sami sebi, up...

V PostgreSQL pišemo na sublight: 1 host, 1 dan, 1TB
Smer optimizacije je očitna – preprosta odstranite datumsko polje iz vseh indeksov na pregrajenih mizah. Glede na naše količine je dobiček približno 1TB/teden!

Zdaj pa opozorimo, da je bilo treba ta terabajt še nekako posneti. Se pravi tudi mi disk naj bi zdaj manj nalagal! Ta slika jasno prikazuje učinek čiščenja, ki smo mu posvetili en teden:

V PostgreSQL pišemo na sublight: 1 host, 1 dan, 1TB

#3. "Razporeditev" konične obremenitve

Ena od velikih težav obremenjenih sistemov je redundantna sinhronizacija nekatere operacije, ki tega ne zahtevajo. Včasih »ker niso opazili«, včasih »je bilo lažje«, a prej ali slej se je treba znebiti.

Povečajmo prejšnjo sliko in vidimo, da imamo disk »črpa« pod obremenitvijo z dvojno amplitudo med sosednjimi vzorci, kar pa se pri tolikšnem številu operacij očitno »statistično« ne bi smelo zgoditi:

V PostgreSQL pišemo na sublight: 1 host, 1 dan, 1TB

To je zelo enostavno doseči. Monitoring smo že začeli skoraj 1000 strežnikov, vsako obdela ločena logična nit in vsaka nit ponastavi zbrane informacije, ki se pošiljajo v bazo podatkov ob določeni frekvenci, nekako takole:

setInterval(sendToDB, interval)

Težava je pri tem prav v tem, da vse niti se začnejo približno ob istem času, zato se njihovi časi pošiljanja skoraj vedno ujemajo »natančno«. Ups #2 ...

Na srečo je to zelo enostavno popraviti, dodajanje "naključnega" zagona po času:

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

#4. Predpomnimo, kar potrebujemo

Tretji tradicionalni problem visoke obremenitve je brez predpomnilnika kje je bi lahko biti.

Omogočili smo na primer analizo glede na vozlišča načrta (vsi ti Seq Scan on users), a takoj mislijo, da so večinoma enaki - pozabili so.

Ne, seveda se spet nič ne zapiše v bazo podatkov, to prekine sprožilec z INSERT ... ON CONFLICT DO NOTHING. Toda ti podatki še vedno dosežejo bazo podatkov in so nepotrebni branje za preverjanje konflikta narediti. Ups #3 ...

Razlika v številu zapisov, poslanih v bazo podatkov pred/po omogočenem predpomnjenju, je očitna:

V PostgreSQL pišemo na sublight: 1 host, 1 dan, 1TB

In to je spremljajoči padec obremenitve pomnilnika:

V PostgreSQL pišemo na sublight: 1 host, 1 dan, 1TB

Skupno

"Terabajt na dan" zveni samo strašljivo. Če narediš vse prav, potem je to samo 2^40 bajtov / 86400 sekund = ~12.5 MB/sda so zdržali celo vijaki IDE namizja. 🙂

Ampak resno, tudi z desetkratnim "nagibom" obremenitve čez dan lahko zlahka dosežete zmogljivosti sodobnih SSD-jev.

V PostgreSQL pišemo na sublight: 1 host, 1 dan, 1TB

Vir: www.habr.com

Dodaj komentar