Rydym yn ysgrifennu yn PostgreSQL ar sublight: 1 gwesteiwr, 1 diwrnod, 1TB

Yn ddiweddar dywedais wrthych sut, gan ddefnyddio ryseitiau safonol cynyddu perfformiad ymholiadau darllen SQL o gronfa ddata PostgreSQL. Heddiw byddwn yn siarad am sut gellir gwneud recordio yn fwy effeithlon yn y gronfa ddata heb ddefnyddio unrhyw “troi” yn y ffurfwedd - yn syml trwy drefnu'r llif data yn gywir.

Rydym yn ysgrifennu yn PostgreSQL ar sublight: 1 gwesteiwr, 1 diwrnod, 1TB

#1. Adranu

Erthygl am sut a pham ei bod yn werth trefnu rhaniad cymhwysol “mewn theori” eisoes wedi bod, yma byddwn yn siarad am yr arfer o gymhwyso rhai dulliau o fewn ein gwasanaeth monitro ar gyfer cannoedd o weinyddion PostgreSQL.

"Pethau'r dyddiau a fu ..."

I ddechrau, fel unrhyw MVP, dechreuodd ein prosiect o dan lwyth eithaf ysgafn - dim ond ar gyfer y deg gweinydd mwyaf hanfodol y gwnaed gwaith monitro, roedd pob bwrdd yn gymharol gryno ... Ond wrth i amser fynd rhagddo, daeth nifer y gwesteiwyr a fonitrwyd yn fwy a mwy , ac unwaith eto ceisiasom wneud rhywbeth ag un o tablau 1.5TB mewn maint, sylweddolom, er ei bod yn bosibl parhau i fyw fel hyn, ei fod yn anghyfleus iawn.

Roedd yr amseroedd bron fel amseroedd epig, roedd fersiynau gwahanol o PostgreSQL 9.x yn berthnasol, felly roedd yn rhaid gwneud yr holl raniad "â llaw" - trwy etifeddiaeth tabl a sbardunau llwybro gyda deinamig EXECUTE.

Rydym yn ysgrifennu yn PostgreSQL ar sublight: 1 gwesteiwr, 1 diwrnod, 1TB
Daeth yr ateb a ddeilliodd o hyn i fod yn ddigon cyffredinol fel y gellid ei gyfieithu i bob tabl:

  • Cyhoeddwyd tabl rhiant “pennawd” gwag, a ddisgrifiodd y cyfan mynegeion a sbardunau angenrheidiol.
  • Gwnaethpwyd y cofnod o safbwynt y cleient yn y tabl “gwraidd”, a'i ddefnyddio'n fewnol sbardun llwybro BEFORE INSERT mewnosodwyd y cofnod “yn gorfforol” yn yr adran ofynnol. Os nad oedd y fath beth eto, fe wnaethon ni ddal eithriad a ...
  • … trwy ddefnyddio CREATE TABLE ... (LIKE ... INCLUDING ...) ei greu yn seiliedig ar dempled y tabl rhiant adran gyda chyfyngiad ar y dyddiad a ddymunirfel pan fydd data yn cael ei adfer, darllen yn cael ei berfformio yn unig ynddo.

PG10: ymgais gyntaf

Ond yn hanesyddol nid yw rhannu trwy etifeddiaeth wedi bod yn addas iawn ar gyfer delio â ffrwd ysgrifennu weithredol neu nifer fawr o raniad plant. Er enghraifft, gallwch gofio bod gan yr algorithm ar gyfer dewis yr adran ofynnol cymhlethdod cwadratig, ei fod yn gweithio gyda 100+ o adrannau, rydych chi'ch hun yn deall sut ...

Yn PG10 optimeiddiwyd y sefyllfa hon yn fawr trwy weithredu cefnogaeth rhaniad brodorol. Felly, gwnaethom geisio ei gymhwyso ar unwaith yn syth ar ôl mudo'r storfa, ond ...

Fel y digwyddodd ar ôl cloddio trwy'r llawlyfr, y tabl rhaniad brodorol yn y fersiwn hon yw:

  • nid yw'n cefnogi disgrifiadau mynegai
  • nid yw'n cefnogi sbardunau arno
  • Ni all fod yn “ddisgynnydd” unrhyw un
  • peidiwch â chefnogi INSERT ... ON CONFLICT
  • Ni all gynhyrchu adran yn awtomatig

Wedi cael ergyd boenus i’r talcen gyda rhaca, sylweddolom y byddai’n amhosib gwneud heb addasu’r cais, a gohirio ymchwil pellach am chwe mis.

PG10: ail gyfle

Felly, fe ddechreuon ni ddatrys y problemau a gododd fesul un:

  1. Oherwydd sbardunau a ON CONFLICT Gwelsom fod eu hangen arnom o hyd yma ac acw, felly gwnaethom gam canolradd i'w gweithio allan tabl dirprwy.
  2. Cael gwared ar "llwybro" in triggers - hynny yw, o EXECUTE.
  3. Fe wnaethon nhw ei dynnu allan ar wahân tabl templed gyda'r holl fynegeionfel nad ydynt hyd yn oed yn bresennol yn y tabl dirprwy.

Rydym yn ysgrifennu yn PostgreSQL ar sublight: 1 gwesteiwr, 1 diwrnod, 1TB
Yn olaf, ar ôl hyn i gyd, rhannwyd y prif fwrdd yn frodorol. Mae creu adran newydd yn dal i gael ei adael i gydwybod y cais.

Geiriaduron “llifio”.

Fel mewn unrhyw system ddadansoddol, roedd gennym ni hefyd "ffeithiau" a "thoriadau" (geiriaduron). Yn ein hachos ni, yn rhinwedd y swydd hon fe wnaethant weithredu, er enghraifft, corff templed ymholiadau araf tebyg neu destun yr ymholiad ei hun.

Cafodd “ffeithiau” eu rhannu fesul dydd ers amser maith yn barod, felly fe wnaethom ddileu adrannau hen ffasiwn yn dawel, ac nid oeddent yn ein poeni (boncyffion!). Ond roedd problem gyda geiriaduron...

Nid i ddweud bod yna lawer ohonyn nhw, ond yn fras Arweiniodd 100TB o “ffeithiau” at eiriadur 2.5TB. Ni allwch ddileu unrhyw beth o fwrdd o'r fath yn gyfleus, ni allwch ei gywasgu mewn digon o amser, ac yn raddol daeth ysgrifennu ato yn arafach.

Fel geiriadur... ynddo, dylid cyflwyno pob cofnod yn union unwaith... ac mae hyn yn gywir, ond!.. Does neb yn ein rhwystro rhag cael geiriadur ar wahân ar gyfer pob diwrnod! Ydy, mae hyn yn dod â diswyddiad penodol, ond mae'n caniatáu:

  • ysgrifennu/darllen yn gyflymach oherwydd maint yr adran lai
  • defnyddio llai o gof trwy weithio gyda mynegeion mwy cryno
  • storio llai o ddata oherwydd y gallu i gael gwared ar hen ffasiwn yn gyflym

O ganlyniad i'r holl gymhleth o fesurau Gostyngodd llwyth CPU ~30%, llwyth disg ~50%:

Rydym yn ysgrifennu yn PostgreSQL ar sublight: 1 gwesteiwr, 1 diwrnod, 1TB
Ar yr un pryd, fe wnaethom barhau i ysgrifennu'r un peth yn union i'r gronfa ddata, gyda llai o lwyth.

#2. Esblygiad cronfa ddata ac ailffactorio

Felly fe wnaethom setlo ar yr hyn sydd gennym mae gan bob dydd ei adran ei hun gyda data. Mewn gwirionedd, CHECK (dt = '2018-10-12'::date) — ac mae allwedd rhaniad a'r amod i gofnod ddisgyn i adran benodol.

Gan fod yr holl adroddiadau yn ein gwasanaeth wedi'u hadeiladu yng nghyd-destun dyddiad penodol, mae'r mynegeion ar eu cyfer ers “amseroedd heb raniad” wedi bod o bob math. (Gweinydd, dyddiad, Templed Cynllun), (Gweinydd, dyddiad, nod cynllun), (dyddiad, Dosbarth gwall, Gweinydd), ...

Ond yn awr y maent yn byw ar bob adran eich copïau pob mynegai o'r fath... Ac o fewn pob adran dyddiad yn gyson... Mae'n ymddangos bod yn awr rydym ym mhob mynegai o'r fath dim ond mynd i mewn cysonyn fel un o'r meysydd, sy'n cynyddu ei gyfaint a'r amser chwilio amdano, ond nid yw'n dod ag unrhyw ganlyniad. Gadawsant y rhaca iddyn nhw eu hunain, wps...

Rydym yn ysgrifennu yn PostgreSQL ar sublight: 1 gwesteiwr, 1 diwrnod, 1TB
Mae cyfeiriad optimeiddio yn amlwg - yn syml dileu'r maes dyddiad o bob mynegai ar fyrddau rhanedig. O ystyried ein cyfrolau, mae'r ennill yn ymwneud 1TB yr wythnos!

Nawr gadewch i ni nodi bod yn rhaid i'r terabyte hwn gael ei gofnodi rywsut o hyd. Hynny yw, ninnau hefyd dylai'r ddisg nawr lwytho llai! Mae'r llun hwn yn dangos yn glir yr effaith a gafwyd o'r glanhau, y gwnaethom neilltuo wythnos iddo:

Rydym yn ysgrifennu yn PostgreSQL ar sublight: 1 gwesteiwr, 1 diwrnod, 1TB

#3. “Lledaenu” y llwyth brig

Un o drafferthion mawr systemau llwythog yw cysoni diangen rhai gweithrediadau nad oes eu hangen. Weithiau “am na wnaethon nhw sylwi”, weithiau “roedd hi’n haws felly”, ond yn hwyr neu’n hwyrach mae’n rhaid i chi gael gwared arno.

Gadewch i ni chwyddo i mewn ar y llun blaenorol a gweld bod gennym ddisg “pympiau” o dan y llwyth gydag osgled dwbl rhwng samplau cyfagos, sy’n amlwg yn “ystadegol” na ddylai ddigwydd gyda chymaint o weithrediadau:

Rydym yn ysgrifennu yn PostgreSQL ar sublight: 1 gwesteiwr, 1 diwrnod, 1TB

Mae hyn yn eithaf hawdd i'w gyflawni. Rydym eisoes wedi dechrau monitro bron i 1000 o weinyddion, mae pob un yn cael ei brosesu gan edau rhesymegol ar wahân, ac mae pob edefyn yn ailosod y wybodaeth gronedig i'w hanfon i'r gronfa ddata ar amlder penodol, rhywbeth fel hyn:

setInterval(sendToDB, interval)

Mae'r broblem yma yn gorwedd yn union yn y ffaith bod mae pob llinyn yn dechrau tua'r un amser, felly mae eu hamseroedd anfon bron bob amser yn cyd-daro “i'r pwynt.” Wps #2...

Yn ffodus, mae hyn yn eithaf hawdd i'w drwsio, ychwanegu rhediad “ar hap”. erbyn amser:

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

#4. Rydym yn cadw'r hyn sydd ei angen arnom

Y drydedd broblem llwyth traddodiadol yw dim cache lle mae e gallai fod.

Er enghraifft, gwnaethom hi'n bosibl dadansoddi o ran nodau cynllun (y rhain i gyd Seq Scan on users), ond meddyliwch ar unwaith eu bod, gan mwyaf, yr un peth — anghofiasant.

Na, wrth gwrs, nid oes dim yn cael ei ysgrifennu i'r gronfa ddata eto, mae hyn yn torri oddi ar y sbardun gyda INSERT ... ON CONFLICT DO NOTHING. Ond mae'r data hwn yn dal i gyrraedd y gronfa ddata, ac mae'n ddiangen darllen i wirio am wrthdaro gorfod gwneud. Wps #3...

Mae'r gwahaniaeth yn nifer y cofnodion a anfonwyd i'r gronfa ddata cyn/ar ôl caching yn amlwg:

Rydym yn ysgrifennu yn PostgreSQL ar sublight: 1 gwesteiwr, 1 diwrnod, 1TB

A dyma'r gostyngiad cysylltiedig yn y llwyth storio:

Rydym yn ysgrifennu yn PostgreSQL ar sublight: 1 gwesteiwr, 1 diwrnod, 1TB

Yn gyfan gwbl

Mae “Terabyte-y-dydd” yn swnio'n frawychus. Os gwnewch bopeth yn iawn, yna mae hyn yn unig 2^40 beit / 86400 eiliad = ~12.5MB/sbod hyd yn oed sgriwiau IDE bwrdd gwaith a gynhaliwyd. 🙂

Ond o ddifrif, hyd yn oed gyda “sgiw” ddegplyg o'r llwyth yn ystod y dydd, gallwch chi fodloni galluoedd SSDs modern yn hawdd.

Rydym yn ysgrifennu yn PostgreSQL ar sublight: 1 gwesteiwr, 1 diwrnod, 1TB

Ffynhonnell: hab.com

Ychwanegu sylw