Kirjutame PostgreSQL-is sublighti kohta: 1 host, 1 päev, 1 TB

Hiljuti rääkisin teile, kuidas standardsete retseptide abil suurendada SQL-i lugemispäringute jõudlust PostgreSQL andmebaasist. Täna räägime sellest, kuidas salvestamist saab teha tõhusamalt andmebaasis ilma konfiguratsioonis mingeid pöördeid kasutamata – lihtsalt andmevoogusid õigesti korraldades.

Kirjutame PostgreSQL-is sublighti kohta: 1 host, 1 päev, 1 TB

#1. Sektsioonide lõikamine

Artikkel sellest, kuidas ja miks tasub korraldada rakendatud partitsioonid "teoreetiliselt" on juba olnud, räägime siin mõningate lähenemisviiside rakendamise praktikast seireteenus sadade PostgreSQL-i serverite jaoks.

"Möödunud päevade asjad..."

Esialgu, nagu iga MVP, sai ka meie projekt alguse üsna väikese koormuse all - monitooringut tehti vaid kümnele kõige kriitilisemale serverile, kõik tabelid olid suhteliselt kompaktsed... Kuid mida aeg edasi, seda rohkem jälgitavate hostide arv muutus. , ja taaskord proovisime ühega midagi ette võtta lauad suurusega 1.5TB, saime aru, et kuigi oli võimalik niimoodi edasi elada, oli see väga ebamugav.

Ajad olid peaaegu nagu eepilised ajad, asjakohased olid PostgreSQL 9.x erinevad versioonid, nii et kogu partitsioonide jagamine tuli teha "käsitsi" - läbi tabeli pärimine ja päästikud marsruutimine dünaamilisega EXECUTE.

Kirjutame PostgreSQL-is sublighti kohta: 1 host, 1 päev, 1 TB
Saadud lahendus osutus piisavalt universaalseks, et seda saaks tõlkida kõikidesse tabelitesse:

  • Deklareeriti tühi "päise" ematabel, mis kirjeldas kõike vajalikud indeksid ja päästikud.
  • Kliendi vaatevinklist tehtud kirje tehti "juur" tabelis ja sisemiselt kasutades marsruutimise päästik BEFORE INSERT kirje sisestati "füüsiliselt" nõutavasse sektsiooni. Kui sellist asja veel polnud, siis tabasime erandi ja...
  • … kasutades CREATE TABLE ... (LIKE ... INCLUDING ...) loodi ülemtabeli malli põhjal jaotist piiranguga soovitud kuupäeva kohtanii et andmete hankimisel toimub lugemine ainult selles.

PG10: esimene katse

Pärimise kaudu partitsioonid ei ole aga ajalooliselt hästi sobinud aktiivse kirjutusvoo või suure hulga alampartitsioone käsitlemiseks. Näiteks võite meenutada, et vajaliku jaotise valimise algoritmil oli ruutkeskmine keerukus, et see töötab 100+ jaotisega, saate ise aru, kuidas...

PG10 puhul optimeeriti seda olukorda oluliselt tugiteenuste rakendamisega natiivne jaotus. Seetõttu proovisime seda kohe pärast salvestusruumi migreerimist kohe rakendada, kuid...

Nagu pärast juhendi läbikaevamist selgus, on selle versiooni algselt partitsioonitud tabel:

  • ei toeta indeksi kirjeldusi
  • ei toeta sellel päästikuid
  • ei saa olla kellegi "järglane"
  • ei toeta INSERT ... ON CONFLICT
  • ei saa jaotist automaatselt luua

Olles saanud rehaga valusa hoobi otsaesisele, mõistsime, et ilma rakendust muutmata ei saa hakkama, ja lükkasime edasised uuringud poole aasta võrra edasi.

PG10: teine ​​võimalus

Niisiis hakkasime tekkinud probleeme ükshaaval lahendama:

  1. Kuna vallandab ja ON CONFLICT Leidsime, et meil on neid ikka siin-seal vaja, nii et tegime vahepealse etapi, et need välja töötada puhverserveri tabel.
  2. Sai lahti "marsruutimisest" käivitajates – see tähendab alates EXECUTE.
  3. Nad võtsid selle eraldi välja mallitabel kõigi indeksideganii et neid pole isegi puhverserveri tabelis.

Kirjutame PostgreSQL-is sublighti kohta: 1 host, 1 päev, 1 TB
Lõpuks, pärast seda kõike, jagasime põhitabeli natiivselt. Uue jaotise loomine jääb ikkagi rakenduse südametunnistusele.

"Saagimise" sõnaraamatud

Nagu igas analüüsisüsteemis, oli ka meil "faktid" ja "kärped" (sõnaraamatud). Meie puhul tegutsesid nad selles ametis näiteks malli keha sarnased aeglased päringud või päringu enda tekst.

“Fakte” jaotati päevade kaupa juba pikka aega, nii et kustutasime rahulikult aegunud rubriigid ja need meid ei häirinud (logid!). Aga sõnaraamatutega oli probleem...

Mitte öelda, et neid oli palju, aga umbes 100 TB "fakte" andis tulemuseks 2.5 TB sõnastiku. Sellisest tabelist ei saa mugavalt midagi kustutada, õigel ajal tihendada ja sinna kirjutamine muutus järk-järgult aeglasemaks.

Nagu sõnastik... selles tuleks iga kirje esitada täpselt üks kord... ja see on õige, aga!.. Keegi ei keela meil seda teha iga päeva kohta eraldi sõnastik! Jah, see toob kaasa teatud koondamise, kuid võimaldab:

  • kirjutada/lugeda kiiremini väiksema sektsiooni suuruse tõttu
  • tarbivad vähem mälu kompaktsemate indeksitega töötades
  • salvestada vähem andmeid tänu võimalusele vananenud kiiresti eemaldada

Kogu meetmete kompleksi tulemusena CPU koormus vähenes ~30%, kettakoormus ~50%:

Kirjutame PostgreSQL-is sublighti kohta: 1 host, 1 päev, 1 TB
Samal ajal jätkasime täpselt sama asja kirjutamist andmebaasi, ainult et väiksema koormusega.

#2. Andmebaasi areng ja ümberkujundamine

Nii me leppisime sellega, mis meil on igal päeval on oma osa andmetega. tegelikult CHECK (dt = '2018-10-12'::date) — ja seal on partitsioonivõti ja tingimus, et kirje kuuluks konkreetsesse sektsiooni.

Kuna kõik meie teenuses olevad aruanded on koostatud kindla kuupäeva kontekstis, on nende indeksid alates "jaotuseta aegadest" olnud igat tüüpi (server, Kuupäev, plaani mall), (server, Kuupäev, plaani sõlm), (Kuupäev, Veaklass, Server), ...

Aga nüüd elavad nad igal lõigul teie koopiad iga selline indeks... Ja iga jaotise sees kuupäev on konstant... Selgub, et nüüd oleme igas sellises indeksis lihtsalt sisesta konstant ühe väljana, mis suurendab nii selle mahtu kui ka otsimisaega, kuid ei too mingit tulemust. Nad jätsid reha enda teada, oih...

Kirjutame PostgreSQL-is sublighti kohta: 1 host, 1 päev, 1 TB
Optimeerimise suund on ilmne – lihtne eemaldage kuupäevaväli kõigist indeksitest eraldatud laudadel. Arvestades meie mahtusid, on kasum umbes 1TB nädalas!

Nüüd paneme tähele, et see terabait tuli ikka kuidagi salvestada. See tähendab, et ka meie ketas peaks nüüd vähem laadima! Sellel pildil on selgelt näha puhastusest saadud efekt, millele pühendasime nädala:

Kirjutame PostgreSQL-is sublighti kohta: 1 host, 1 päev, 1 TB

#3. Tippkoormuse "hajutamine".

Laetud süsteemide üks suuremaid probleeme on üleliigne sünkroonimine mõned toimingud, mis seda ei nõua. Vahel “sest nad ei märganud”, vahel “oli nii lihtsam”, aga varem või hiljem tuleb sellest lahti saada.

Suurendame eelmist pilti ja vaatame, et meil on ketas “pumbad” topeltamplituudiga koormuse all külgnevate proovide vahel, mida selgelt "statistiliselt" ei tohiks sellise arvu toimingutega juhtuda:

Kirjutame PostgreSQL-is sublighti kohta: 1 host, 1 päev, 1 TB

Seda on üsna lihtne saavutada. Oleme juba alustanud jälgimist ligi 1000 serverit, iga lõim töödeldakse eraldi loogilise lõimega ja iga lõim lähtestab kogutud teabe, mis saadetakse andmebaasi teatud sagedusega, umbes nii:

setInterval(sendToDB, interval)

Probleem seisneb siin just selles, et kõik lõimed algavad ligikaudu samal ajal, seega langevad nende saatmisajad peaaegu alati kokku. Oih #2...

Õnneks on seda üsna lihtne parandada, "juhusliku" jooksu lisamine aja järgi:

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

#4. Me salvestame vahemällu, mida vajame

Kolmas traditsiooniline suure koormuse probleem on vahemälu pole kus ta on võiks olla.

Näiteks võimaldasime analüüsida plaani sõlmede järgi (kõik need Seq Scan on users), kuid arvan kohe, et need on suures osas samad – nad unustasid.

Ei, muidugi, andmebaasi ei kirjutata jälle midagi, see katkestab päästiku INSERT ... ON CONFLICT DO NOTHING. Kuid need andmed jõuavad ikkagi andmebaasi ja see pole vajalik konflikti kontrollimiseks lugemine peab tegema. Oi #3...

Andmebaasi saadetud kirjete arvu erinevus enne/pärast vahemällu salvestamise lubamist on ilmne:

Kirjutame PostgreSQL-is sublighti kohta: 1 host, 1 päev, 1 TB

Ja see on kaasnev laokoormuse langus:

Kirjutame PostgreSQL-is sublighti kohta: 1 host, 1 päev, 1 TB

Kogusummas

"Terabait-päevas" kõlab lihtsalt hirmutavalt. Kui teete kõik õigesti, on see lihtsalt 2^40 baiti / 86400 sekundit = ~12.5 MB/set isegi töölaua IDE kruvid pidasid. 🙂

Kuid tõsiselt, isegi päeva jooksul kümnekordse koormuse "viltu" korral saate hõlpsalt täita tänapäevaste SSD-de võimalusi.

Kirjutame PostgreSQL-is sublighti kohta: 1 host, 1 päev, 1 TB

Allikas: www.habr.com

Lisa kommentaar