Mir schreiwen an PostgreSQL op Sublight: 1 Host, 1 Dag, 1TB

Viru kuerzem hunn ech Iech gesot wéi Dir Standard Rezepter benotzt d'Performance vun SQL liesen Ufroen erhéijen aus der PostgreSQL Datebank. Haut wäerte mir schwätzen iwwer wéi Opnam kann méi effizient gemaach ginn an der Datebank ouni "Twists" an der Configuratioun ze benotzen - einfach andeems Dir d'Datestroum korrekt organiséiert.

Mir schreiwen an PostgreSQL op Sublight: 1 Host, 1 Dag, 1TB

#1. Sektiounen

En Artikel iwwer wéi a firwat et derwäert ass ze organiséieren applizéiert Partitionéierung "an Theorie" scho war, hei wäerte mir iwwer d'Praxis schwätzen fir e puer Approchen an eisem Iwwerwaachungsservice fir Honnerte vu PostgreSQL Serveren.

"Saachen vun Deeg vergaangen ..."

Am Ufank, wéi all MVP, huet eise Projet ënner enger zimlech liichter Belaaschtung ugefaang - d'Iwwerwaachung gouf nëmme fir déi zéng kritesch Serveren duerchgefouert, all Dëscher ware relativ kompakt ... Awer wéi d'Zäit vergaang ass, ass d'Zuel vun de iwwerwaachte Hosten ëmmer méi ginn , an nach eng Kéier hu mir probéiert eppes mat engem vun Dëscher 1.5TB an Gréisst, mir hu gemierkt, datt obwuel et méiglech war esou weider ze liewen, et ganz onbequem war.

D'Zäite ware bal wéi epesch Zäiten, verschidde Versioune vu PostgreSQL 9.x ware relevant, sou datt all Partitionéierung "manuell" muss gemaach ginn - duerch Dësch Ierfschaft an Ausléiser Routing mat Dynamik EXECUTE.

Mir schreiwen an PostgreSQL op Sublight: 1 Host, 1 Dag, 1TB
Déi resultéierend Léisung huet sech als universell genuch erausgestallt datt et op all Dëscher iwwersat ka ginn:

  • Eng eidel "Header" Elterentabelle gouf deklaréiert, wat alles beschriwwen huet néideg Indizes an Ausléiser.
  • De Rekord aus der Siicht vum Client gouf am "root" Dësch gemaach, an intern benotzt Routing Ausléiser BEFORE INSERT de Rekord gouf "physesch" an déi néideg Rubrik agebaut. Wann et nach net sou eppes war, hu mir eng Ausnahm gefaang an ...
  • ... duerch d'Benotzung CREATE TABLE ... (LIKE ... INCLUDING ...) gouf erstallt baséiert op der Schabloun vun der Elterendësch Sektioun mat enger Restriktioun op de gewënschte Datumsou datt wann d'Donnéeën erëmfonnt ginn, gëtt d'Liesen nëmmen dran gemaach.

PG10: éischte Versuch

Awer d'Partitionéierung duerch Ierfschaft war historesch net gutt gepasst fir mat engem aktive Schreifstroum oder enger grousser Zuel vu Kannerpartitionen ze handelen. Zum Beispill kënnt Dir drun erënneren datt den Algorithmus fir déi erfuerderlech Sektioun auswielen huet quadratesch Komplexitéit, datt et mat 100+ Sektiounen funktionnéiert, verstitt Dir selwer wéi ...

Am PG10 gouf dës Situatioun staark optimiséiert andeems d'Ënnerstëtzung ëmgesat gouf gebierteg Partitionéierung. Dofir hu mir direkt probéiert et direkt no der Migratioun vun der Späichere anzesetzen, awer ...

Wéi et sech erausgestallt huet nodeems Dir duerch d'Handbuch gegruewen huet, ass déi gebierteg opgedeelt Dësch an dëser Versioun:

  • ënnerstëtzt net Index Beschreiwunge
  • ënnerstëtzt net Ausléiser op et
  • kann keen "Nokommen" sinn
  • net ënnerstëtzen INSERT ... ON CONFLICT
  • kann net automatesch eng Rubrik generéieren

Nodeems mir e schmerzhafte Schlag op d'Stir mat enger Rake krut, hu mir gemierkt datt et onméiglech wier ouni d'Applikatioun z'änneren, a weider Fuerschung fir sechs Méint ausgestallt.

PG10: zweet Chance

Also hu mir ugefaang d'Problemer ze léisen, déi een nom aneren entstane sinn:

  1. Wéinst Ausléiser an ON CONFLICT Mir hu festgestallt, datt mir se nach hei an do brauchen, dofir hu mir eng Tëschestatioun gemaach fir se auszeschaffen Proxy Dësch.
  2. Gitt vum "Routing" lass an Ausléiser - dat ass, aus EXECUTE.
  3. Si hunn et separat erausgeholl Schabloun Dësch mat all Indexsou datt se net emol an der Proxy Tabelle präsent sinn.

Mir schreiwen an PostgreSQL op Sublight: 1 Host, 1 Dag, 1TB
Endlech, no all deem, hu mir den Haaptdësch gebierteg opgedeelt. D'Schafe vun enger neier Sektioun ass nach dem Gewësse vun der Applikatioun iwwerlooss.

"Sawing" Dictionnairen

Wéi an all analytesche System, hu mir och "Fakten" an "Schnëtt" (Wörterbuch). An eisem Fall hu si an dëser Kapazitéit gehandelt, z.B. Schabloun Kierper ähnlech lues Ufroen oder den Text vun der Ufro selwer.

"Fakten" goufe scho laang vum Dag opgedeelt, also hu mir roueg verouderte Rubriken geläscht, a si hunn eis net gestéiert (Logbicher!). Awer et war e Problem mat Dictionnairen ...

Net ze soen datt et der vill waren, awer ongeféier 100TB vun "Fakten" huet zu engem 2.5TB Wierderbuch gefouert. Dir kënnt näischt bequem aus esou engem Dësch läschen, Dir kënnt et net an enger adäquat Zäit kompriméieren, a schreift et lues a lues méi lues.

Wéi en Dictionnaire... dran soll all Entrée genee eemol presentéiert ginn... an dat stëmmt, mee!.. Keen hält eis dovun of engem separaten Wierderbuch fir all Dag! Jo, dëst bréngt eng gewësse Redundanz, awer et erlaabt:

  • schreiwen / liesen méi séier wéinst méi kleng Sektioun Gréisst
  • manner Erënnerung verbrauchen andeems se mat méi kompakten Indexen schaffen
  • manner Daten späicheren wéinst der Fähigkeit fir séier verännert ze läschen

Als Resultat vum ganze Komplex vu Moossnamen CPU Belaaschtung ass ëm ~30% erofgaang, Diskbelaaschtung ëm ~50%:

Mir schreiwen an PostgreSQL op Sublight: 1 Host, 1 Dag, 1TB
Zur selwechter Zäit hu mir weider genee datselwecht an d'Datebank geschriwwen, just mat manner Belaaschtung.

#2. Datebank Evolutioun a Refactoring

Also hu mir eis festgeluecht wat mir hunn all Dag huet seng eege Rubrik mat Daten. Eigentlech, CHECK (dt = '2018-10-12'::date) - an et gëtt e Partitionsschlëssel an d'Konditioun fir e Rekord an eng spezifesch Sektioun ze falen.

Well all Berichter an eisem Service am Kontext vun engem spezifeschen Datum gebaut sinn, sinn d'Indexe fir si zënter "net opgedeelt Zäiten" all Typen (Server, Datum, Plang Schabloun), (Server, Datum, Plan Node), (Datum, Feelerklass, Server)...

Awer elo liewen se op all Sektioun Är Kopien all esou Index ... A bannent all Rubrik Datum ass konstant... Et stellt sech eraus datt mir elo an all esou Index sinn gitt einfach eng konstante als ee vun de Felder, déi souwuel säi Volume wéi och d'Sichzäit dofir erhéicht, awer kee Resultat bréngt. Si hunn de Rake fir sech selwer gelooss, ooops ...

Mir schreiwen an PostgreSQL op Sublight: 1 Host, 1 Dag, 1TB
D'Richtung vun der Optimiséierung ass offensichtlech - einfach ewechzehuelen den Datum Feld aus all Index op opgedeelt Dëscher. Mat eise Bänn ass de Gewënn ongeféier 1 TB/Woch!

Loosst eis elo feststellen datt dësen Terabyte nach iergendwéi opgeholl muss ginn. Dat heescht, mir och den Disk soll elo manner lueden! Dëst Bild weist kloer den Effekt vun der Botzen, un déi mir eng Woch gewidmet hunn:

Mir schreiwen an PostgreSQL op Sublight: 1 Host, 1 Dag, 1TB

#3. D'Spëtzbelaaschtung "Verbreeden".

Ee vun de grousse Probleemer vu geluedene Systemer ass redundante Synchroniséierung e puer Operatiounen déi et net erfuerderen. Heiansdo "well se net gemierkt hunn", mol "dat war méi einfach esou", mä desto oder spéider musst Dir et lass ginn.

Loosst eis op dat viregt Bild zoomen a kucken datt mir eng Scheif hunn "Pumpen" ënner der Laascht mat duebel Amplituden tëscht benachbaren Echantillon, déi kloer "statistesch" soll net mat esou enger Zuel vun Operatiounen geschéien:

Mir schreiwen an PostgreSQL op Sublight: 1 Host, 1 Dag, 1TB

Dëst ass ganz einfach ze erreechen. Mir hu schonn ugefaang ze iwwerwaachen bal 1000 Serveren, jidderee gëtt vun engem getrennten logesche Fuedem veraarbecht, an all Fuedem setzt d'akkumuléiert Informatioun zréck, déi op eng gewësse Frequenz an d'Datebank geschéckt gëtt, sou eppes:

setInterval(sendToDB, interval)

De Problem hei läit genee an der Tatsaach, datt all thread fänken un ongeféier gläichzäiteg un, sou datt hir Sendungszäite bal ëmmer "op de Punkt" zesummekommen. Oops #2...

Glécklecherweis ass dëst ganz einfach ze fixéieren, engem "zoufälleg" opzebréngen dobäi no Zäit:

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

#4. Mir cache wat mir brauchen

Déi drëtt traditionell Highload Problem ass kee Cache wou hien ass kéint ginn.

Zum Beispill hu mir et méiglech gemaach a punkto Plangknäppchen ze analyséieren (all dës Seq Scan on users), awer direkt denken datt se zum gréissten Deel d'selwecht sinn - si hu vergiess.

Nee, natierlech gëtt näischt op d'Datebank erëm geschriwwen, dëst schneidt den Ausléiser mat INSERT ... ON CONFLICT DO NOTHING. Awer dës Donnéeën erreechen nach ëmmer d'Datebank, an et ass onnéideg liesen fir Konflikt ze kontrolléieren musse maachen. Oops #3...

Den Ënnerscheed an der Unzuel vun den Opzeechnungen, déi an d'Datebank geschéckt ginn ier / nom Caching aktivéiert ass, ass offensichtlech:

Mir schreiwen an PostgreSQL op Sublight: 1 Host, 1 Dag, 1TB

An dëst ass de begleetende Réckgang vun der Späicherbelaaschtung:

Mir schreiwen an PostgreSQL op Sublight: 1 Host, 1 Dag, 1TB

Total

"Terabyte-pro-Dag" kléngt just grujeleg. Wann Dir alles richteg maacht, dann ass dëst just 2^40 Bytes / 86400 Sekonnen = ~12.5MB/sdatt souguer Desktop IDE Schrauwen ofgehalen. 🙂

Awer eescht, och mat engem zéngfache "Skew" vun der Laascht am Dag, kënnt Dir ganz einfach d'Fähigkeiten vun modernen SSDs treffen.

Mir schreiwen an PostgreSQL op Sublight: 1 Host, 1 Dag, 1TB

Source: will.com

Setzt e Commentaire