{"id":79467,"date":"2020-04-27T07:42:23","date_gmt":"2020-04-27T05:42:23","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/operativnaya-analitika-v-mikroservisnoj-arhitekture-p%cc%b6o%cc%b6n%cc%b6ya%cc%b6t%cc%b6%cc%b6-%cc%b6i%cc%b6-%cc%b6p%cc%b6r%cc%b6o%cc%b6s%cc%b6t%cc%b6i%cc%b6t%cc%b6%cc%b6-pomoch-i-podskazat-postgres"},"modified":"2020-04-27T07:42:23","modified_gmt":"2020-04-27T05:42:23","slug":"operativnaya-analitika-v-mikroservisnoj-arhitekture-p%cc%b6o%cc%b6n%cc%b6ya%cc%b6t%cc%b6%cc%b6-%cc%b6i%cc%b6-%cc%b6p%cc%b6r%cc%b6o%cc%b6s%cc%b6t%cc%b6i%cc%b6t%cc%b6%cc%b6-pomoch-i-podskazat-postgres","status":"publish","type":"post","link":"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/operativnaya-analitika-v-mikroservisnoj-arhitekture-p%cc%b6o%cc%b6n%cc%b6ya%cc%b6t%cc%b6%cc%b6-%cc%b6i%cc%b6-%cc%b6p%cc%b6r%cc%b6o%cc%b6s%cc%b6t%cc%b6i%cc%b6t%cc%b6%cc%b6-pomoch-i-podskazat-postgres","title":{"rendered":"Operationel analyse i mikroservicesarkitektur: at forst\u00e5 og assistere Postgres FDW","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Mikroservicesarkitektur, ligesom alt andet i verden, har sine fordele og ulemper. Nogle processer bliver enklere, mens andre bliver mere komplicerede. I jagten p\u00e5 hastighed og bedre skalerbarhed m\u00e5 vi ofre noget. En af disse ofre er kompleksiteten i analysen. I en monolit kan al operationel analyse reduceres til SQL-foresp\u00f8rgsler til en analytisk replik, men i en multiservearkitektur har hver service sin egen database, og det virker som om, at vi ikke kan klare os med \u00e9n foresp\u00f8rgsel (eller kan vi?). For dem, der er interesserede i, hvordan vi l\u00f8ste problemet med operationel analyse i vores virksomhed og hvordan vi har l\u00e6rt at leve med denne l\u00f8sning - velkommen.<\/p>\n<p><img decoding=\"async\" alt=\"Operationel analyse i mikroservicesarkitektur: at forst\u00e5 og assistere Postgres FDW\" src=\"\/wp-content\/uploads\/2020\/04\/4296389f06d488999cc023dcaa3027f7.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nMit navn er Pavel Siva\u0161, og jeg arbejder i DomKlik i det team, der st\u00e5r for vedligeholdelsen af det analytiske datalager. Vores arbejde kan groft sagt klassificeres som data engineering, men i virkeligheden er opgavespektret meget bredere. Der er standard opgaver inden for data engineering som ETL\/ELT, st\u00f8tte og tilpasning af v\u00e6rkt\u00f8jer til dataanalyse samt udvikling af egne v\u00e6rkt\u00f8jer. Specifikt til operationel rapportering besluttede vi at 'lade som om' vi har en monolit og give analytikerne \u00e9n database, hvor alle de n\u00f8dvendige data vil v\u00e6re til stede. <noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Generelt set har vi overvejet forskellige muligheder. Vi kunne have bygget et fuldt lager \u2014 vi pr\u00f8vede endda, men \u00e6rligt talt lykkedes det ikke at f\u00e5 de hyppige \u00e6ndringer i logikken til at stemme overens med den ret langsomme proces med at bygge lageret og foretage \u00e6ndringer i det (hvis nogen har lykkes, s\u00e5 skriv i kommentarerne hvordan). Man kunne have sagt til analytikerne: \"Drenge, l\u00e6r python og brug analytiske replikaer\", men det ville have v\u00e6ret et ekstra krav til rekruttering, og det s\u00e5 vi helst ville undg\u00e5, hvis det var muligt. Vi besluttede at pr\u00f8ve teknologien FDW (Foreign Data Wrapper): grundl\u00e6ggende er det en standard dblink, der er en del af SQL-standarden, men med et langt mere brugervenligt interface. Baseret p\u00e5 det skabte vi en l\u00f8sning, som endte med at sl\u00e5 rod, og det var den, vi landede p\u00e5. Dens detaljer er et emne for en enkelt artikel, eller m\u00e5ske flere, da der er meget at fort\u00e6lle: fra synkronisering af database-skemaer til adgangsstyring og anonymisering af persondata. Det skal ogs\u00e5 n\u00e6vnes, at denne l\u00f8sning ikke er en erstatning for reelle analytiske databaser og lagre, men kun l\u00f8ser en specifik opgave.<\/p>\n<p>P\u00e5 et overordnet niveau ser det s\u00e5dan ud:<\/p>\n<p><img decoding=\"async\" alt=\"Operationel analyse i mikroservicesarkitektur: at forst\u00e5 og assistere Postgres FDW\" src=\"\/wp-content\/uploads\/2020\/04\/574da29dfdb40706afe9e817e789a61b.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nDer er en PostgreSQL-database, hvor brugerne kan opbevare deres arbejdsdata, og det vigtigste er, at denne database er forbundet til analytiske replikaer af alle tjenester via FDW. Det giver mulighed for at skrive en foresp\u00f8rgsel til flere databaser, uanset om det er: PostgreSQL, MySQL, MongoDB eller noget andet (en fil, API, hvis der ikke er en passende wrapper, kan man skrive sin egen). N\u00e5, det lyder godt, skal vi g\u00e5 hjem?<\/p>\n<p>Hvis alt sluttede s\u00e5 hurtigt og enkelt, ville der nok ikke v\u00e6re nogen artikler.<\/p>\n<p>Det er vigtigt klart at forst\u00e5, hvordan PostgreSQL behandler foresp\u00f8rgsler til fjerne servere. Det virker logisk, men ofte ignoreres det: PostgreSQL opdeler foresp\u00f8rgslen i dele, der udf\u00f8res p\u00e5 de fjerne servere uafh\u00e6ngigt, samler disse data og udf\u00f8rer de endelige beregninger selv, s\u00e5 hastigheden af foresp\u00f8rgslen vil afh\u00e6nge st\u00e6rkt af, hvordan den er skrevet. Det skal ogs\u00e5 bem\u00e6rkes: n\u00e5r data kommer fra en fjern server, har de ikke l\u00e6ngere indekser, der er intet, som kan hj\u00e6lpe planl\u00e6ggeren, derfor er det kun os, der kan give hj\u00e6lp og r\u00e5dgivning. Og netop det vil jeg gerne fort\u00e6lle mere om.<\/p>\n<h1>Simpel foresp\u00f8rgsel og planen med den<\/h1>\n<p>\nFor at vise, hvordan PostgreSQL udf\u00f8rer en foresp\u00f8rgsel til en tabel med 6 millioner r\u00e6kker p\u00e5 en ekstern <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/da\/server\/dts-dronten\/\"   title=\"serveren\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"2589\">serveren<\/a>, lad os se p\u00e5 en simpel plan.<\/p>\n<pre><code class=\"sql\">forklaring analyse detaljeret  \nV\u00c6LG t\u00e6ll(1)\nFRA fdw_schema.tabel;\n\nAggregat  (omkostning=418383.23..418383.24 r\u00e6kker=1 bredde=8) (faktisk tid=3857.198..3857.198 r\u00e6kker=1 loops=1)\n  Output: t\u00e6ll(1)\n  -&gt;  Fremmed Scanning p\u00e5 fdw_schema.&quot;tabel&quot;  (omkostning=100.00..402376.14 r\u00e6kker=6402838 bredde=0) (faktisk tid=4.874..3256.511 r\u00e6kker=6406868 loops=1)\n        Output: &quot;tabel&quot;.id, &quot;tabel&quot;.is_active, &quot;tabel&quot;.meta, &quot;tabel&quot;.created_dt\n        Fjern SQL: V\u00c6LG NULL FRA fdw_schema.tabel\nPlanl\u00e6gningstid: 0.986 ms\nUdf\u00f8relsestid: 3857.436 ms<\/code><\/pre>\n<p>\nBrug af instruktionen VERBOSE giver os mulighed for at se den foresp\u00f8rgsel, der sendes til den eksterne server, og resultaterne, som vi f\u00e5r til videre behandling (linje RemoteSQL).<\/p>\n<p>Lad os g\u00e5 lidt videre og tilf\u00f8je nogle filtre til vores foresp\u00f8rgsel: et efter <b>boolean<\/b> felt, et efter forekomst <b>timestamp<\/b> i intervallet og et efter <b>jsonb<\/b>.<\/p>\n<pre><code class=\"sql\">forklaring analyse detaljeret\nV\u00c6LG t\u00e6ll(1)\nFRA fdw_schema.tabel \nHVOR is_active er sandt\nOG created_dt MELLEM NUVENDEN_DATO - INTERVAL '7 m\u00e5neder' \nOG NUVENDEN_DATO - INTERVAL '6 m\u00e5neder'\nOG meta-&gt;&gt;'kilde' = 'test';\n\nAggregat  (omkostning=577487.69..577487.70 r\u00e6kker=1 bredde=8) (faktisk tid=27473.818..25473.819 r\u00e6kker=1 loops=1)\n  Output: t\u00e6ll(1)\n  -&gt;  Fremmed Scanning p\u00e5 fdw_schema.&quot;tabel&quot;  (omkostning=100.00..577469.21 r\u00e6kker=7390 bredde=0) (faktisk tid=31.369..25372.466 r\u00e6kker=1360025 loops=1)\n        Output: &quot;tabel&quot;.id, &quot;tabel&quot;.is_active, &quot;tabel&quot;.meta, &quot;tabel&quot;.created_dt\n        Filter: ((&quot;tabel&quot;.is_active ER SAND) OG ((&quot;tabel&quot;.meta -&gt;&gt; 'kilde'::tekst) = 'test'::tekst) OG (&quot;tabel&quot;.created_dt &gt;= (('nu'::cstring)::dato - '7 m\u00e5neder'::interval)) OG (&quot;tabel&quot;.created_dt &lt;= ((('nu'::cstring)::dato)::timestamp med tidszone - '6 m\u00e5neder'::interval)))\n        R\u00e6kker fjernet af filter: 5046843\n        Fjern SQL: V\u00c6LG created_dt, is_active, meta FRA fdw_schema.tabel\nPlanl\u00e6gningstid: 0.665 ms\nUdf\u00f8relsestid: 27474.118 ms<\/code><\/pre>\n<p>\nNetop her ligger det punkt, som man skal v\u00e6re opm\u00e6rksom p\u00e5, n\u00e5r man skriver foresp\u00f8rgsler. Filtrene blev ikke sendt til den eksterne server, hvilket betyder, at PostgreSQL tr\u00e6kker alle 6 millioner r\u00e6kker, for f\u00f8rst derefter at filtrere lokalt (linje Filter) og udf\u00f8re aggregationen. Hemmeligheden til succes er at skrive foresp\u00f8rgslen, s\u00e5 filtrene sendes til den eksterne maskine, og vi f\u00e5r kun de relevante r\u00e6kker til aggregationen. <\/p>\n<h1>Det er noget boligsds<\/h1>\n<p>\nMed boolean felter er det hele enkelt. Problemet i den oprindelige foresp\u00f8rgsel opstod p\u00e5 grund af operatoren <b>is<\/b>. Hvis vi erstatter den med <b>=<\/b>, f\u00e5r vi f\u00f8lgende resultat:<\/p>\n<pre><code class=\"sql\">forklaring analyse detaljeret\nV\u00c6LG t\u00e6ll(1)\nFRA fdw_schema.tabel\nHVOR is_active = sand\nOG created_dt MELLEM NUVENDEN_DATO - INTERVAL '7 m\u00e5neder' \nOG NUVENDEN_DATO - INTERVAL '6 m\u00e5neder'\nOG meta-&gt;&gt;'kilde' = 'test';\n\nAggregat  (omkostning=508010.14..508010.15 r\u00e6kker=1 bredde=8) (faktisk tid=19064.314..19064.314 r\u00e6kker=1 loops=1)\n  Output: t\u00e6ll(1)\n  -&gt;  Fremmed Scanning p\u00e5 fdw_schema.&quot;tabel&quot;  (omkostning=100.00..507988.44 r\u00e6kker=8679 bredde=0) (faktisk tid=33.035..18951.278 r\u00e6kker=1360025 loops=1)\n        Output: &quot;tabel&quot;.id, &quot;tabel&quot;.is_active, &quot;tabel&quot;.meta, &quot;tabel&quot;.created_dt\n        Filter: (((&quot;tabel&quot;.meta -&gt;&gt; 'kilde'::tekst) = 'test'::tekst) OG (&quot;tabel&quot;.created_dt &gt;= (('nu'::cstring)::dato - '7 m\u00e5neder'::interval)) OG (&quot;tabel&quot;.created_dt &lt;= ((('nu'::cstring)::dato)::timestamp med tidszone - '6 m\u00e5neder'::interval)))\n        R\u00e6kker fjernet af filter: 3567989\n        Fjern SQL: V\u00c6LG created_dt, meta FRA fdw_schema.tabel HVOR (is_active)\nPlanl\u00e6gningstid: 0.834 ms\nUdf\u00f8relsestid: 19064.534 ms<\/code><\/pre>\n<p>\nSom du kan se, fl\u00f8j filteret til den fjerne server, og udf\u00f8relsestiden faldt fra 27 til 19 sekunder. <\/p>\n<p>Det er vigtigt at bem\u00e6rke, at operatoren <b>is<\/b> adskiller sig fra operatoren <b>=<\/b> ved at den kan h\u00e5ndtere Null-v\u00e6rdier. Det betyder, at <b>is not True<\/b> i filteret vil efterlade v\u00e6rdierne False og Null, mens <b>!= True<\/b> kun vil efterlade v\u00e6rdierne False. Derfor, n\u00e5r man erstatter operatoren <b>is not<\/b> skal der gives to betingelser i filteret med operatoren OR, for eksempel, <b>HVOR (col != True) ELLER (col er null)<\/b>.<\/p>\n<p>Nu har vi styr p\u00e5 boolean, lad os komme videre. Men lad os f\u00f8rst s\u00e6tte filteret for boolske v\u00e6rdier tilbage til sin oprindelige tilstand, s\u00e5 vi uafh\u00e6ngigt kan se effekten af de andre \u00e6ndringer.<\/p>\n<h1>timestamptz? hz<\/h1>\n<p>\nOverordnet set er der ofte behov for at eksperimentere med, hvordan man korrekt skriver en foresp\u00f8rgsel, der involverer fjerntliggende servere, og derefter finde forklaringen p\u00e5, hvorfor det sker, som det g\u00f8r. Der er meget lidt information om dette at finde p\u00e5 internettet. I vores eksperimenter har vi opdaget, at filteret for en fast dato fungerer perfekt p\u00e5 den fjerntliggende server, men n\u00e5r vi \u00f8nsker at angive datoen dynamisk, for eksempel nu() eller NUVENDEN_DATO, sker der ikke det samme. I vores tilf\u00e6lde har vi tilf\u00f8jet et s\u00e5dant filter for at sikre, at kolonnen created_at indeholder data for pr\u00e6cist 1 m\u00e5ned siden (MELLEM NUVENDEN_DATO - INTERVAL '7 m\u00e5neder' OG NUVENDEN_DATO - INTERVAL '6 m\u00e5neder'). Hvad gjorde vi i dette tilf\u00e6lde?<\/p>\n<pre><code class=\"sql\">forklar analyser detaljeret\nSELECT count(1)\nFROM fdw_schema.table \nWHERE is_active is True\nAND created_dt &gt;= (SELECT CURRENT_DATE::timestamptz - INTERVAL '7 m\u00e5neder') \nAND created_dt &gt;'source' = 'test';\n\nAggregere  (omkostning=306875.17..306875.18 r\u00e6kker=1 bredde=8) (aktuel tid=4789.114..4789.115 r\u00e6kker=1 loops=1)\n  Output: count(1)\n  InitPlan 1 (returnerer $0)\n    -&gt;  Resultat  (omkostning=0.00..0.02 r\u00e6kker=1 bredde=8) (aktuel tid=0.007..0.008 r\u00e6kker=1 loops=1)\n          Output: ((('nu'::cstring)::date)::timestamp with time zone - '7 m\u00e5neder'::interval)\n  InitPlan 2 (returnerer $1)\n    -&gt;  Resultat  (omkostning=0.00..0.02 r\u00e6kker=1 bredde=8) (aktuel tid=0.002..0.002 r\u00e6kker=1 loops=1)\n          Output: ((('nu'::cstring)::date)::timestamp with time zone - '6 m\u00e5neder'::interval)\n  -&gt;  Foreign Scan on fdw_schema.\"table\"  (omkostning=100.02..306874.86 r\u00e6kker=105 bredde=0) (aktuel tid=23.475..4681.419 r\u00e6kker=1360025 loops=1)\n        Output: \"table\".id, \"table\".is_active, \"table\".meta, \"table\".created_dt\n        Filter: ((\"table\".is_active IS TRUE) AND ((\"table\".meta -&gt;&gt; 'source'::text) = 'test'::text))\n        R\u00e6kker fjernet af filter: 76934\n        Remote SQL: SELECT is_active, meta FROM fdw_schema.table WHERE ((created_dt &gt;= $1::timestamp with time zone)) AND ((created_dt &lt; $2::timestamp with time zone))\nPlanl\u00e6gningstid: 0.703 ms\nK\u00f8rselstid: 4789.379 ms<\/code><\/pre>\n<p>\nVi bad planl\u00e6ggeren om at beregne datoen p\u00e5 forh\u00e5nd i underforesp\u00f8rgslen og sende den f\u00e6rdige variabel i filteret. Og denne indikation gav os et glimrende resultat, foresp\u00f8rgslen blev n\u00e6sten 6 gange hurtigere!<\/p>\n<p>Igen er det vigtigt at v\u00e6re opm\u00e6rksom p\u00e5: datatypen i underforesp\u00f8rgslen skal v\u00e6re den samme som feltet vi filtrerer p\u00e5, ellers vil planl\u00e6ggeren konkludere, at da typerne er forskellige, skal alle data f\u00f8rst hentes, og s\u00e5 filtreres lokalt.<\/p>\n<p>Lad os g\u00e5 tilbage til filteret for datoen til dens oprindelige v\u00e6rdi.<\/p>\n<h1>Freddy vs. Jsonb<\/h1>\n<p>\nGenerelt har boolean felter og datoer allerede betydeligt forbedret vores foresp\u00f8rgsel, men der var stadig \u00e9n datatype tilbage. Kampen med filtreringen p\u00e5 dette felt er \u00e6rligt talt stadig ikke afsluttet, selvom der ogs\u00e5 her er fremskridt. S\u00e5dan lykkedes det os at overf\u00f8re filteret p\u00e5 <b>jsonb<\/b> feltet til den fjerne server.<\/p>\n<pre><code class=\"sql\">forklar analyser detaljeret\nSELECT count(1)\nFROM fdw_schema.table \nWHERE is_active is True\nAND created_dt BETWEEN CURRENT_DATE - INTERVAL '7 m\u00e5neder' \nAND CURRENT_DATE - INTERVAL '6 m\u00e5neder'\nAND meta @&gt; '{\"source\":\"test\"}'::jsonb;\n\nAggregere  (omkostning=245463.60..245463.61 r\u00e6kker=1 bredde=8) (aktuel tid=6727.589..6727.590 r\u00e6kker=1 loops=1)\n  Output: count(1)\n  -&gt;  Foreign Scan on fdw_schema.\"table\"  (omkostning=1100.00..245459.90 r\u00e6kker=1478 bredde=0) (aktuel tid=16.213..6634.794 r\u00e6kker=1360025 loops=1)\n        Output: \"table\".id, \"table\".is_active, \"table\".meta, \"table\".created_dt\n        Filter: ((\"table\".is_active IS TRUE) AND (\"table\".created_dt &gt;= (('nu'::cstring)::date - '7 m\u00e5neder'::interval)) AND (\"table\".created_dt  '{\"source\": \"test\"}'::jsonb))\nPlanl\u00e6gningstid: 0.747 ms\nK\u00f8rselstid: 6727.815 ms<\/code><\/pre>\n<p>\nI stedet for filtreringsoperatorer skal en tilstedev\u00e6relseoperator anvendes <b>jsonb<\/b> i en anden. 7 sekunder i stedet for de oprindelige 29. Indtil videre er dette den eneste vellykkede metode til at overf\u00f8re filtre ved <b>jsonb<\/b> til en fjernserver, men her er det vigtigt at tage hensyn til \u00e9n begr\u00e6nsning: vi bruger version 9.6 af databasen, men vi planl\u00e6gger at afslutte de sidste tests og migrere til version 12 inden udgangen af april. N\u00e5r vi er opdateret, skriver vi hvordan det har p\u00e5virket, da der er mange \u00e6ndringer, vi har store forh\u00e5bninger til: json_path, den nye adf\u00e6rd af CTE, push down (som eksisterer fra version 10). Vi gl\u00e6der os til at pr\u00f8ve det hurtigt.<\/p>\n<h1>Finish him<\/h1>\n<p>\nVi har unders\u00f8gt, hvordan hver \u00e6ndring p\u00e5virker foresp\u00f8rgsels hastigheden hver for sig. Lad os nu se, hvad der sker, n\u00e5r de tre filtre er korrekt skrevet.<\/p>\n<pre><code class=\"sql\">forklar analyser verbos\nSELECT count(1)\nFROM fdw_schema.table \nWHERE is_active = True\nAND created_dt &gt;= (SELECT CURRENT_DATE::timestamptz - INTERVAL '7 m\u00e5neder') \nAND created_dt  '{\"source\":\"test\"}'::jsonb;\n\nAggregat  (cost=322041.51..322041.52 rows=1 width=8) (faktisk tid=2278.867..2278.867 rows=1 loops=1)\n  Output: count(1)\n  InitPlan 1 (returnerer $0)\n    -&gt;  Resultat  (cost=0.00..0.02 rows=1 width=8) (faktisk tid=0.010..0.010 rows=1 loops=1)\n          Output: ((('nu'::cstring)::date)::timestamp med tidszone - '7 m\u00e5neder'::interval)\n  InitPlan 2 (returnerer $1)\n    -&gt;  Resultat  (cost=0.00..0.02 rows=1 width=8) (faktisk tid=0.003..0.003 rows=1 loops=1)\n          Output: ((('nu'::cstring)::date)::timestamp med tidszone - '6 m\u00e5neder'::interval)\n  -&gt;  Foreign Scan on fdw_schema.\"table\"  (cost=100.02..322041.41 rows=25 width=0) (faktisk tid=8.597..2153.809 rows=1360025 loops=1)\n        Output: \"table\".id, \"table\".is_active, \"table\".meta, \"table\".created_dt\n        Remote SQL: SELECT NULL FROM fdw_schema.table WHERE (is_active) AND ((created_dt &gt;= $1::timestamp med tidszone)) AND ((created_dt  '{\"source\": \"test\"}'::jsonb))\nPlanl\u00e6gningstid: 0.820 ms\nUdf\u00f8relsestid: 2279.087 ms<\/code><\/pre>\n<p>\nJa, foresp\u00f8rgslen ser mere kompleks ud, det er en tvungen omkostning, men udf\u00f8relseshastigheden er 2 sekunder, hvilket er mere end 10 gange hurtigere! Og dette taler vi om en simpel foresp\u00f8rgsel p\u00e5 et relativt lille datas\u00e6t. I reelle foresp\u00f8rgsler opn\u00e5ede vi gevinster p\u00e5 op til flere hundrede gange.<\/p>\n<p>Lad os opsummere: hvis du bruger PostgreSQL med FDW, skal du altid tjekke, at alle filtre sendes til den fjernserver, s\u00e5 vil du v\u00e6re lykkelig... I det mindste indtil du n\u00e5r til joins mellem tabeller fra forskellige <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/da\/server\/\"   title=\"servere\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"1482\">servere<\/a>. Men det er allerede en historie for en anden artikel.<\/p>\n<p>Tak for din opm\u00e6rksomhed! Jeg ser frem til at h\u00f8re sp\u00f8rgsm\u00e5l, kommentarer, samt historier om din erfaring i kommentarerne.<br \/>\n<br \/>Kilde: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/domclick\/blog\/498018\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430, \u043a\u0430\u043a \u0438 \u0432\u0441\u0435 \u0432 \u044d\u0442\u043e\u043c \u043c\u0438\u0440\u0435, \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0438 \u043f\u043b\u044e\u0441\u044b \u0438 \u0441\u0432\u043e\u0438 \u043c\u0438\u043d\u0443\u0441\u044b. \u041e\u0434\u043d\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b \u0441 \u043d\u0435\u0439 \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u043f\u0440\u043e\u0449\u0435, \u0434\u0440\u0443\u0433\u0438\u0435 \u2014 \u0441\u043b\u043e\u0436\u043d\u0435\u0435. \u0418 \u0432 \u0443\u0433\u043e\u0434\u0443 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0438 \u043b\u0443\u0447\u0448\u0435\u0439 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e\u0441\u0442\u0438 \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u0438\u043d\u043e\u0441\u0438\u0442\u044c \u0441\u0432\u043e\u0438 \u0436\u0435\u0440\u0442\u0432\u044b. \u041e\u0434\u043d\u0430 \u0438\u0437 \u043d\u0438\u0445 \u2014 \u0443\u0441\u043b\u043e\u0436\u043d\u0435\u043d\u0438\u0435 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0438. \u0415\u0441\u043b\u0438 \u0432 \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u0435 \u0432\u0441\u044e \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u0443\u044e \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0443 \u043c\u043e\u0436\u043d\u043e \u0441\u0432\u0435\u0441\u0442\u0438 \u043a SQL \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c \u043a \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0440\u0435\u043f\u043b\u0438\u043a\u0435, [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":79468,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-79467","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.3 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430, \u043a\u0430\u043a \u0438 \u0432\u0441\u0435 \u0432 \u044d\u0442\u043e\u043c \u043c\u0438\u0440\u0435, \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0438 \u043f\u043b\u044e\u0441\u044b \u0438 \u0441\u0432\u043e\u0438 \u043c\u0438\u043d\u0443\u0441\u044b. \u041e\u0434\u043d\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b \u0441 \u043d\u0435\u0439 \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u043f\u0440\u043e\u0449\u0435, \u0434\u0440\u0443\u0433\u0438\u0435 \u2014 \u0441\u043b\u043e\u0436\u043d\u0435\u0435.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/operativnaya-analitika-v-mikroservisnoj-arhitekture-p%cc%b6o%cc%b6n%cc%b6ya%cc%b6t%cc%b6%cc%b6-%cc%b6i%cc%b6-%cc%b6p%cc%b6r%cc%b6o%cc%b6s%cc%b6t%cc%b6i%cc%b6t%cc%b6%cc%b6-pomoch-i-podskazat-postgres\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"da_DK\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u0430\u044f \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0430 \u0432 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0435: \u043f\u0336\u043e\u0336\u043d\u0336\u044f\u0336\u0442\u0336\u044c\u0336 \u0336\u0438\u0336 \u0336\u043f\u0336\u0440\u0336\u043e\u0336\u0441\u0336\u0442\u0336\u0438\u0336\u0442\u0336\u044c\u0336 \u043f\u043e\u043c\u043e\u0447\u044c \u0438 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u0430\u0442\u044c Postgres FDW | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430, \u043a\u0430\u043a \u0438 \u0432\u0441\u0435 \u0432 \u044d\u0442\u043e\u043c \u043c\u0438\u0440\u0435, \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0438 \u043f\u043b\u044e\u0441\u044b \u0438 \u0441\u0432\u043e\u0438 \u043c\u0438\u043d\u0443\u0441\u044b. \u041e\u0434\u043d\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b \u0441 \u043d\u0435\u0439 \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u043f\u0440\u043e\u0449\u0435, \u0434\u0440\u0443\u0433\u0438\u0435 \u2014 \u0441\u043b\u043e\u0436\u043d\u0435\u0435.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/operativnaya-analitika-v-mikroservisnoj-arhitekture-p%cc%b6o%cc%b6n%cc%b6ya%cc%b6t%cc%b6%cc%b6-%cc%b6i%cc%b6-%cc%b6p%cc%b6r%cc%b6o%cc%b6s%cc%b6t%cc%b6i%cc%b6t%cc%b6%cc%b6-pomoch-i-podskazat-postgres\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-04-27T05:42:23+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-04-27T05:42:23+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Operationel analyse i mikrotjenestearkitektur: hj\u00e6lp og vejledning med Postgres FDW | ProHoster","description":"Mikrotjenestearkitektur, ligesom alt andet i denne verden, har sine fordele og ulemper. Nogle processer bliver lettere med den, andre bliver mere komplekse.","canonical_url":"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/operativnaya-analitika-v-mikroservisnoj-arhitekture-p%cc%b6o%cc%b6n%cc%b6ya%cc%b6t%cc%b6%cc%b6-%cc%b6i%cc%b6-%cc%b6p%cc%b6r%cc%b6o%cc%b6s%cc%b6t%cc%b6i%cc%b6t%cc%b6%cc%b6-pomoch-i-podskazat-postgres","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"da_DK","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u0430\u044f \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0430 \u0432 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0435: \u043f\u0336\u043e\u0336\u043d\u0336\u044f\u0336\u0442\u0336\u044c\u0336 \u0336\u0438\u0336 \u0336\u043f\u0336\u0440\u0336\u043e\u0336\u0441\u0336\u0442\u0336\u0438\u0336\u0442\u0336\u044c\u0336 \u043f\u043e\u043c\u043e\u0447\u044c \u0438 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u0430\u0442\u044c Postgres FDW | ProHoster","og:description":"\u041c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430, \u043a\u0430\u043a \u0438 \u0432\u0441\u0435 \u0432 \u044d\u0442\u043e\u043c \u043c\u0438\u0440\u0435, \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0438 \u043f\u043b\u044e\u0441\u044b \u0438 \u0441\u0432\u043e\u0438 \u043c\u0438\u043d\u0443\u0441\u044b. \u041e\u0434\u043d\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b \u0441 \u043d\u0435\u0439 \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u043f\u0440\u043e\u0449\u0435, \u0434\u0440\u0443\u0433\u0438\u0435 \u2014 \u0441\u043b\u043e\u0436\u043d\u0435\u0435.","og:url":"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/operativnaya-analitika-v-mikroservisnoj-arhitekture-p%cc%b6o%cc%b6n%cc%b6ya%cc%b6t%cc%b6%cc%b6-%cc%b6i%cc%b6-%cc%b6p%cc%b6r%cc%b6o%cc%b6s%cc%b6t%cc%b6i%cc%b6t%cc%b6%cc%b6-pomoch-i-podskazat-postgres","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-04-27T05:42:23+00:00","article:modified_time":"2020-04-27T05:42:23+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"79467","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 16:37:24","updated":"2026-02-09 21:38:01","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/79467","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/comments?post=79467"}],"version-history":[{"count":2,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/79467\/revisions"}],"predecessor-version":[{"id":159871,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/79467\/revisions\/159871"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media\/79468"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media?parent=79467"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/categories?post=79467"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/tags?post=79467"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}