{"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\/sv\/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":"Operativ analys i mikrotj\u00e4nstarkitektur: p\u0336o\u0336n\u0336a\u0336tt\u0336a\u0336 \u0336o\u0336c\u0336h\u0336 \u0336f\u0336o\u0336r\u0336k\u0336l\u0336a\u0336r\u0336a\u0336 hj\u00e4lpa och v\u00e4gleda Postgres FDW","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Mikrotj\u00e4nstarkitektur, precis som allt annat i denna v\u00e4rld, har sina f\u00f6rdelar och nackdelar. Vissa processer blir enklare med den, andra blir sv\u00e5rare. F\u00f6r att \u00e5stadkomma snabbare f\u00f6r\u00e4ndringar och b\u00e4ttre skalbarhet m\u00e5ste man g\u00f6ra vissa uppoffringar. En av dessa \u00e4r kompliceringen av analysen. Om man i ett monolitiskt system kan reducera all operativ analys till SQL-fr\u00e5gor mot en analytisk replika, s\u00e5 har varje tj\u00e4nst i en multitj\u00e4nstarkitektur sin egen databas, och det verkar som att man inte kan klara sig med en enda fr\u00e5ga (eller kanske kan?). F\u00f6r dem som \u00e4r intresserade av hur vi l\u00f6ste problemet med operativ analys i v\u00e5rt f\u00f6retag och hur vi har l\u00e4rt oss att leva med denna l\u00f6sning \u2013 v\u00e4lkomna.<\/p>\n<p><img decoding=\"async\" alt=\"Operativ analys i mikrotj\u00e4nstarkitektur: p\u0336o\u0336n\u0336a\u0336tt\u0336a\u0336 \u0336o\u0336c\u0336h\u0336 \u0336f\u0336o\u0336r\u0336k\u0336l\u0336a\u0336r\u0336a\u0336 hj\u00e4lpa och v\u00e4gleda Postgres FDW\" src=\"\/wp-content\/uploads\/2020\/04\/4296389f06d488999cc023dcaa3027f7.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nJag heter Pavel Sivash, och p\u00e5 DomKlik jobbar jag i teamet som ansvarar f\u00f6r underh\u00e5ll av det analytiska datalageret. V\u00e5r verksamhet kan grovt kategoriseras som dataengineering, men egentligen \u00e4r spektrum av uppgifter mycket bredare. Det handlar om standarder f\u00f6r dataengineering som ETL\/ELT, st\u00f6d och anpassning av verktyg f\u00f6r dataanalys samt utveckling av egna verktyg. Specifikt f\u00f6r operativ rapportering har vi valt att \"l\u00e5tsas\" att vi har ett monolitiskt system och ge analytikerna en databas d\u00e4r all n\u00f6dv\u00e4ndig information finns. <noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Vi har \u00f6verv\u00e4gt olika alternativ. Man skulle kunna bygga ett fullst\u00e4ndigt lagringssystem \u2014 vi provade till och med det, men \u00e4rligt talat lyckades vi aldrig f\u00e5 tillr\u00e4ckligt med frekventa f\u00f6r\u00e4ndringar i logiken att st\u00e4mma \u00f6verens med den relativt l\u00e5ngsamma processen f\u00f6r att bygga lagringen och g\u00f6ra \u00e4ndringar i den (om n\u00e5gon lyckades, skriv g\u00e4rna i kommentarerna hur). Man kunde ha sagt till analytikerna: \"Grabbar, l\u00e4r er python och jobba med analytiska repliker\", men det skulle inneb\u00e4ra ett extra krav p\u00e5 att rekrytera personal, och det verkade som n\u00e5got att undvika om m\u00f6jligt. Vi besl\u00f6t oss f\u00f6r att prova teknologin FDW (Foreign Data Wrapper): i grunden \u00e4r det en standard dblink som finns i SQL-standarden, men med ett mycket mer anv\u00e4ndarv\u00e4nligt gr\u00e4nssnitt. Baserat p\u00e5 detta skapade vi en l\u00f6sning som slutligen blev accepterad, och det \u00e4r d\u00e4r vi har stannat. Detaljerna kring detta \u00e4r \u00e4mnet f\u00f6r en separat artikel, och kanske f\u00f6r flera, eftersom vi har mycket att ber\u00e4tta: fr\u00e5n synkronisering av databasstrukturer till \u00e5tkomsthantering och anonymisering av personuppgifter. Det b\u00f6r ocks\u00e5 n\u00e4mnas att denna l\u00f6sning inte ers\u00e4tter verkliga analytiska databaser och lagringssystem; den l\u00f6ser bara en specifik uppgift.<\/p>\n<p>\u00d6vergripande ser det ut s\u00e5 h\u00e4r:<\/p>\n<p><img decoding=\"async\" alt=\"Operativ analys i mikrotj\u00e4nstarkitektur: p\u0336o\u0336n\u0336a\u0336tt\u0336a\u0336 \u0336o\u0336c\u0336h\u0336 \u0336f\u0336o\u0336r\u0336k\u0336l\u0336a\u0336r\u0336a\u0336 hj\u00e4lpa och v\u00e4gleda Postgres FDW\" src=\"\/wp-content\/uploads\/2020\/04\/574da29dfdb40706afe9e817e789a61b.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nDet finns en PostgreSQL-databas d\u00e4r anv\u00e4ndarna kan lagra sina arbetsdata, och det viktigaste \u00e4r att denna databas \u00e4r ansluten till analytiska repliker av alla tj\u00e4nster via FDW. Detta ger m\u00f6jlighet att skriva en fr\u00e5ga till flera databaser, oavsett om det handlar om: PostgreSQL, MySQL, MongoDB eller n\u00e5got annat (en fil, API, om det inte finns n\u00e5gon passande wrapper kan man skriva sin egen). S\u00e5, allt verkar bra! Ska vi avsluta h\u00e4r?<\/p>\n<p>Om allt slutade s\u00e5 snabbt och enkelt, skulle det antagligen inte finnas n\u00e5gon artikel.<\/p>\n<p>Det \u00e4r viktigt att tydligt f\u00f6rst\u00e5 hur Postgres hanterar beg\u00e4rningar till fj\u00e4rrservrar. Det verkar logiskt, men mycket ofta uppm\u00e4rksammar man inte detta: Postgres delar upp beg\u00e4ran i delar som k\u00f6rs p\u00e5 fj\u00e4rrservrar oberoende av varandra, samlar dessa data och g\u00f6r de slutgiltiga ber\u00e4kningarna sj\u00e4lv, s\u00e5 hastigheten f\u00f6r att utf\u00f6ra en beg\u00e4ran beror starkt p\u00e5 hur den \u00e4r skriven. Det b\u00f6r ocks\u00e5 p\u00e5pekas att n\u00e4r data kommer fr\u00e5n en fj\u00e4rrserver har de redan inga index, och inget som kan hj\u00e4lpa planeringsverktyget; d\u00e4rf\u00f6r kan vi endast hj\u00e4lpa och v\u00e4gleda det sj\u00e4lva. Och det \u00e4r just detta jag vill ber\u00e4tta mer om.<\/p>\n<h1>Ett enkelt f\u00f6rfr\u00e5gan och planen med den<\/h1>\n<p>\nF\u00f6r att visa hur PostgreSQL utf\u00f6r en fr\u00e5ga mot en tabell med 6 miljoner rader p\u00e5 en avl\u00e4gsen <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/sv\/server\/dts-dronten\/\"   title=\"servern\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"2589\">servern<\/a>, l\u00e5t oss titta p\u00e5 den enkla planen.<\/p>\n<pre><code class=\"sql\">f\u00f6rklara analysera detaljerat  \nV\u00c4LJ count(1)\nFR\u00c5N fdw_schema.table;\n\nAggregat  (kostnad=418383.23..418383.24 rader=1 bredd=8) (faktisk tid=3857.198..3857.198 rader=1 loopar=1)\n  Utdata: count(1)\n  -&gt;  Utl\u00e4ndsk skanning p\u00e5 fdw_schema.&quot;table&quot;  (kostnad=100.00..402376.14 rader=6402838 bredd=0) (faktisk tid=4.874..3256.511 rader=6406868 loopar=1)\n        Utdata: &quot;table&quot;.id, &quot;table&quot;.is_active, &quot;table&quot;.meta, &quot;table&quot;.created_dt\n        Fj\u00e4rr SQL: V\u00c4LJ NULL FR\u00c5N fdw_schema.table\nPlaneringstid: 0.986 ms\nExekveringstid: 3857.436 ms<\/code><\/pre>\n<p>\nAnv\u00e4ndningen av VERBOSE-instruktionen m\u00f6jligg\u00f6r att se den fr\u00e5ga som kommer att skickas till den avl\u00e4gsna servern och vars resultat vi f\u00e5r f\u00f6r vidare behandling (rad RemoteSQL).<\/p>\n<p>L\u00e5t oss g\u00e5 lite l\u00e4ngre och l\u00e4gga till n\u00e5gra filter i v\u00e5r fr\u00e5ga: ett p\u00e5 <b>boolean<\/b> f\u00e4ltet, ett p\u00e5 f\u00f6rekomsten <b>timestamp<\/b> inom intervallet och ett p\u00e5 <b>jsonb<\/b>.<\/p>\n<pre><code class=\"sql\">f\u00f6rklara analysera detaljerat\nV\u00c4LJ count(1)\nFR\u00c5N fdw_schema.table \nD\u00c4R is_active \u00e4r Sann\nOCH created_dt MELLAN AKTUELL_DATUM - INTERVAL '7 m\u00e5nader' \nOCH AKTUELL_DATUM - INTERVAL '6 m\u00e5nader'\nOCH meta-&gt;&gt;'source' = 'test';\n\nAggregat  (kostnad=577487.69..577487.70 rader=1 bredd=8) (faktisk tid=27473.818..25473.819 rader=1 loopar=1)\n  Utdata: count(1)\n  -&gt;  Utl\u00e4ndsk skanning p\u00e5 fdw_schema.&quot;table&quot;  (kostnad=100.00..577469.21 rader=7390 bredd=0) (faktisk tid=31.369..25372.466 rader=1360025 loopar=1)\n        Utdata: &quot;table&quot;.id, &quot;table&quot;.is_active, &quot;table&quot;.meta, &quot;table&quot;.created_dt\n        Filter: ((&quot;table&quot;.is_active \u00c4R SANT) OCH ((&quot;table&quot;.meta -&gt;&gt; 'source'::text) = 'test'::text) OCH (&quot;table&quot;.created_dt &gt;= (('nu'::cstring)::datum - '7 m\u00e5nader'::intervall)) OCH (&quot;table&quot;.created_dt &lt;= ((('nu'::cstring)::datum)::timestamp med tidszon - '6 m\u00e5nader'::intervall)))\n        Rader borttagna av filter: 5046843\n        Fj\u00e4rr SQL: V\u00c4LJ created_dt, is_active, meta FR\u00c5N fdw_schema.table\nPlaneringstid: 0.665 ms\nExekveringstid: 27474.118 ms<\/code><\/pre>\n<p>\nDet \u00e4r precis h\u00e4r som det finns en punkt som beh\u00f6ver uppm\u00e4rksammas vid skrivning av fr\u00e5gor. Filtren \u00f6verf\u00f6rdes inte till den avl\u00e4gsna servern, vilket betyder att PostgreSQL h\u00e4mtar alla 6 miljoner rader f\u00f6r att sedan lokalt filtrera (rad Filter) och utf\u00f6ra aggregationen. Nyckeln till framg\u00e5ng \u00e4r att skriva fr\u00e5gan s\u00e5 att filtren \u00f6verf\u00f6rs till den avl\u00e4gsna maskinen, s\u00e5 att vi f\u00e5r och aggregerar endast de n\u00f6dv\u00e4ndiga raderna. <\/p>\n<h1>Det \u00e4r verkligen lite surrealistiskt<\/h1>\n<p>\nMed booleanf\u00e4lt \u00e4r allt enkelt. Problemet i den ursprungliga fr\u00e5gan uppstod p\u00e5 grund av operatorn <b>is<\/b>. Om vi byter ut den mot <b>=<\/b>, f\u00e5r vi f\u00f6ljande resultat:<\/p>\n<pre><code class=\"sql\">f\u00f6rklara analysera detaljerat\nV\u00c4LJ count(1)\nFR\u00c5N fdw_schema.table\nD\u00c4R is_active = Sann\nOCH created_dt MELLAN AKTUELL_DATUM - INTERVAL '7 m\u00e5nader' \nOCH AKTUELL_DATUM - INTERVAL '6 m\u00e5nader'\nOCH meta-&gt;&gt;'source' = 'test';\n\nAggregat  (kostnad=508010.14..508010.15 rader=1 bredd=8) (faktisk tid=19064.314..19064.314 rader=1 loopar=1)\n  Utdata: count(1)\n  -&gt;  Utl\u00e4ndsk skanning p\u00e5 fdw_schema.&quot;table&quot;  (kostnad=100.00..507988.44 rader=8679 bredd=0) (faktisk tid=33.035..18951.278 rader=1360025 loopar=1)\n        Utdata: &quot;table&quot;.id, &quot;table&quot;.is_active, &quot;table&quot;.meta, &quot;table&quot;.created_dt\n        Filter: (((&quot;table&quot;.meta -&gt;&gt; 'source'::text) = 'test'::text) OCH (&quot;table&quot;.created_dt &gt;= (('nu'::cstring)::datum - '7 m\u00e5nader'::intervall)) OCH (&quot;table&quot;.created_dt &lt;= ((('nu'::cstring)::datum)::timestamp med tidszon - '6 m\u00e5nader'::intervall)))\n        Rader borttagna av filter: 3567989\n        Fj\u00e4rr SQL: V\u00c4LJ created_dt, meta FR\u00c5N fdw_schema.table D\u00c4R (is_active)\nPlaneringstid: 0.834 ms\nExekveringstid: 19064.534 ms<\/code><\/pre>\n<p>\nSom ni ser har filtret g\u00e5tt till den fj\u00e4rranslutna servern, och exekveringstiden har minskat fr\u00e5n 27 till 19 sekunder. <\/p>\n<p>Det \u00e4r v\u00e4rt att notera att operatorn <b>is<\/b> skiljer sig fr\u00e5n operatorn <b>=<\/b> i att den kan hantera v\u00e4rdet Null. Detta inneb\u00e4r att <b>is not True<\/b> i filtret l\u00e4mnar v\u00e4rdena Falskt och Null, medan <b>!= True<\/b> bara l\u00e4mnar v\u00e4rdena Falskt. D\u00e4rf\u00f6r, vid byte av operatorn <b>is not<\/b> b\u00f6r man ange tv\u00e5 villkor i filtret med operatorn OR, till exempel, <b>D\u00c4R (col != True) ELLER (col is null)<\/b>.<\/p>\n<p>Vi har kommit \u00f6verens om boolean, l\u00e5t oss g\u00e5 vidare. Under tiden \u00e5terst\u00e4ller vi filtret f\u00f6r booleska v\u00e4rden till sitt ursprungliga tillst\u00e5nd f\u00f6r att oberoende \u00f6verv\u00e4ga effekten av andra f\u00f6r\u00e4ndringar.<\/p>\n<h1>timestamptz? hz<\/h1>\n<p>\nDet h\u00e4nder ofta att man m\u00e5ste experimentera med hur man korrekt skriver en fr\u00e5ga som involverar fj\u00e4rrservrar, f\u00f6r att sedan leta efter f\u00f6rklaringar om varf\u00f6r det sker. Mycket av informationen om detta kan vara sv\u00e5r att hitta p\u00e5 Internet. I v\u00e5ra experiment har vi uppt\u00e4ckt att filtrering p\u00e5 ett fast datum fungerar utm\u00e4rkt, medan det vi f\u00f6rs\u00f6ker g\u00f6ra med dynamiskt angivna datum, som now() eller CURRENT_DATE, inte fungerar p\u00e5 samma s\u00e4tt. I v\u00e5rt exempel lade vi till ett filter f\u00f6r att kolumnen created_at skulle inneh\u00e5lla data exakt en m\u00e5nad tillbaka (MELLAN AKTUELL_DATUM \u2014 INTERVAL '7 m\u00e5nader' OCH AKTUELL_DATUM \u2014 INTERVAL '6 m\u00e5nader'). Vad gjorde vi i detta fall?<\/p>\n<pre><code class=\"sql\">f\u00f6rklara analysera detaljerat\nV\u00c4LJ count(1)\nFR\u00c5N fdw_schema.tabell \nD\u00c4R is_active \u00e4r Sant\nOCH created_dt &gt;= (V\u00c4LJ CURRENT_DATE::timestamptz - INTERVAL '7 m\u00e5nader') \nOCH created_dt &gt;'source' = 'test';\n\nSammanst\u00e4llning  (kostnad=306875.17..306875.18 rader=1 bredd=8) (faktisk tid=4789.114..4789.115 rader=1 loopar=1)\n  Utdata: count(1)\n  InitPlan 1 (\u00e5terger $0)\n    -&gt;  Resultat  (kostnad=0.00..0.02 rader=1 bredd=8) (faktisk tid=0.007..0.008 rader=1 loopar=1)\n          Utdata: ((('nu'::cstring)::datum)::tidsst\u00e4mpel med tidszon - '7 m\u00e5n'::intervall)\n  InitPlan 2 (\u00e5terger $1)\n    -&gt;  Resultat  (kostnad=0.00..0.02 rader=1 bredd=8) (faktisk tid=0.002..0.002 rader=1 loopar=1)\n          Utdata: ((('nu'::cstring)::datum)::tidsst\u00e4mpel med tidszon - '6 m\u00e5n'::intervall)\n  -&gt;  Utl\u00e4ndsk skanning p\u00e5 fdw_schema.\"tabell\"  (kostnad=100.02..306874.86 rader=105 bredd=0) (faktisk tid=23.475..4681.419 rader=1360025 loopar=1)\n        Utdata: \"tabell\".id, \"tabell\".is_active, \"tabell\".meta, \"tabell\".created_dt\n        Filter: ((\"tabell\".is_active \u00c4R SANT) OCH ((\"tabell\".meta -&gt;&gt; 'source'::text) = 'test'::text))\n        Rader borttagna av filter: 76934\n        Avl\u00e4gsen SQL: V\u00c4LJ is_active, meta FR\u00c5N fdw_schema.tabell D\u00c4R ((created_dt &gt;= $1::tidsst\u00e4mpel med tidszon)) OCH ((created_dt &lt; $2::tidsst\u00e4mpel med tidszon))\nPlaneringstid: 0.703 ms\nUtf\u00f6randetid: 4789.379 ms<\/code><\/pre>\n<p>\nVi f\u00f6reslog f\u00f6r planeringsverktyget att ber\u00e4kna datumet i underfr\u00e5gan och skicka den f\u00e4rdiga variabeln till filtret. Och denna rekommendation gav oss ett utm\u00e4rkt resultat, f\u00f6rfr\u00e5gan blev n\u00e4stan sex g\u00e5nger snabbare!<\/p>\n<p>\u00c5terigen, det \u00e4r viktigt att vara uppm\u00e4rksam: datatypen i underfr\u00e5gan m\u00e5ste vara densamma som f\u00f6r f\u00e4ltet vi filtrerar p\u00e5, annars kommer planeringsverktyget att besluta att eftersom typerna \u00e4r olika m\u00e5ste alla data f\u00f6rst h\u00e4mtas och sedan filtreras lokalt.<\/p>\n<p>Vi \u00e5terg\u00e5r till datumfiltret till sitt ursprungliga v\u00e4rde.<\/p>\n<h1>Freddy mot Jsonb<\/h1>\n<p>\n\u00d6verlag har booleska f\u00e4lt och datum redan accelererat v\u00e5r f\u00f6rfr\u00e5gan ganska mycket, men det fanns fortfarande en datatyp kvar. Striden med filtreringen p\u00e5 den, \u00e4rligt talat, \u00e4r fortfarande inte avslutad, \u00e4ven om d\u00e4r finns framsteg. S\u00e5 h\u00e4r lyckades vi skicka filtret f\u00f6r <b>jsonb<\/b> f\u00e4ltet till den fj\u00e4rrserver.<\/p>\n<pre><code class=\"sql\">f\u00f6rklara analysera detaljerat\nV\u00c4LJ count(1)\nFR\u00c5N fdw_schema.tabell \nD\u00c4R is_active \u00e4r Sant\nOCH created_dt MELLOM CURRENT_DATE - INTERVAL '7 m\u00e5nader' \nOCH CURRENT_DATE - INTERVAL '6 m\u00e5nader'\nOCH meta @&gt; '{\"source\":\"test\"}'::jsonb;\n\nSammanst\u00e4llning  (kostnad=245463.60..245463.61 rader=1 bredd=8) (faktisk tid=6727.589..6727.590 rader=1 loopar=1)\n  Utdata: count(1)\n  -&gt;  Utl\u00e4ndsk skanning p\u00e5 fdw_schema.\"tabell\"  (kostnad=1100.00..245459.90 rader=1478 bredd=0) (faktisk tid=16.213..6634.794 rader=1360025 loopar=1)\n        Utdata: \"tabell\".id, \"tabell\".is_active, \"tabell\".meta, \"tabell\".created_dt\n        Filter: ((\"tabell\".is_active \u00c4R SANT) OCH (\"tabell\".created_dt &gt;= (('nu'::cstring)::datum - '7 m\u00e5n'::intervall)) OCH (\"tabell\".created_dt  '{\"source\": \"test\"}'::jsonb))\nPlaneringstid: 0.747 ms\nUtf\u00f6randetid: 6727.815 ms<\/code><\/pre>\n<p>\nIst\u00e4llet f\u00f6r filtreringsoperatorer ska en operator f\u00f6r n\u00e4rvaro anv\u00e4ndas. <b>jsonb<\/b> i en annan. 7 sekunder ist\u00e4llet f\u00f6r ursprungliga 29. Detta \u00e4r hittills det enda framg\u00e5ngsrika s\u00e4ttet att \u00f6verf\u00f6ra filter genom <b>jsonb<\/b> till en fj\u00e4rrserver, men h\u00e4r \u00e4r det viktigt att ta h\u00e4nsyn till en begr\u00e4nsning: vi anv\u00e4nder version 9.6 av databasen, men fram till slutet av april planerar vi att slutf\u00f6ra de sista testerna och uppgradera till version 12. S\u00e5 snart vi har uppdaterat kommer vi att skriva om hur detta p\u00e5verkade oss, eftersom det finns m\u00e5nga f\u00f6r\u00e4ndringar som vi har stora f\u00f6rhoppningar p\u00e5: json_path, nytt beteende f\u00f6r CTE, push down (som funnits sedan version 10). Det skulle vara bra att prova snart.<\/p>\n<h1>Finish him<\/h1>\n<p>\nVi har kontrollerat hur varje \u00e4ndring p\u00e5verkar hastigheten f\u00f6r f\u00f6rfr\u00e5gan var f\u00f6r sig. L\u00e5t oss nu se vad som h\u00e4nder n\u00e4r alla tre filter \u00e4r korrekt skrivna.<\/p>\n<pre><code class=\"sql\">f\u00f6rklara analysera detaljerat\nV\u00c4LJ count(1)\nFR\u00c5N fdw_schema.table \nD\u00c4R is_active = Sann\nOCH created_dt &gt;= (V\u00c4LJ CURRENT_DATE::timestamptz - INTERVAL '7 m\u00e5nader') \nOCH created_dt  '{\"source\":\"test\"}'::jsonb;\n\nAggregat  (kostnad=322041.51..322041.52 rader=1 bredd=8) (faktisk tid=2278.867..2278.867 rader=1 loopar=1)\n  Utdata: count(1)\n  InitPlan 1 (returnerar $0)\n    -&gt;  Resultat  (kostnad=0.00..0.02 rader=1 bredd=8) (faktisk tid=0.010..0.010 rader=1 loopar=1)\n          Utdata: ((('nu'::cstring)::datum)::tidsst\u00e4mpel med tidszon - '7 m\u00e5n'::intervall)\n  InitPlan 2 (returnerar $1)\n    -&gt;  Resultat  (kostnad=0.00..0.02 rader=1 bredd=8) (faktisk tid=0.003..0.003 rader=1 loopar=1)\n          Utdata: ((('nu'::cstring)::datum)::tidsst\u00e4mpel med tidszon - '6 m\u00e5n'::intervall)\n  -&gt;  Utlandsunders\u00f6kning p\u00e5 fdw_schema.\"table\"  (kostnad=100.02..322041.41 rader=25 bredd=0) (faktisk tid=8.597..2153.809 rader=1360025 loopar=1)\n        Utdata: \"table\".id, \"table\".is_active, \"table\".meta, \"table\".created_dt\n        Fj\u00e4rr SQL: V\u00c4LJ NULL FR\u00c5N fdw_schema.table D\u00c4R (is_active) OCH ((created_dt &gt;= $1::tidsst\u00e4mpel med tidszon)) OCH ((created_dt  '{\"source\": \"test\"}'::jsonb))\nPlaneringstid: 0.820 ms\nExekveringstid: 2279.087 ms<\/code><\/pre>\n<p>\nJa, f\u00f6rfr\u00e5gan verkar mer komplex, det \u00e4r en oundviklig kostnad, men exekveringstiden \u00e4r 2 sekunder, vilket \u00e4r mer \u00e4n 10 g\u00e5nger snabbare! Och detta handlar om en enkel f\u00f6rfr\u00e5gan mot en relativt liten datam\u00e4ngd. Vid verkliga f\u00f6rfr\u00e5gningar har vi f\u00e5tt en \u00f6kning med upp till flera hundra g\u00e5nger.<\/p>\n<p>Sammanfattningsvis: Om du anv\u00e4nder PostgreSQL med FDW, kontrollera alltid att alla filter skickas till fj\u00e4rrservern, s\u00e5 blir du lycklig\u2026 \u00e5tminstone tills du n\u00e5r join mellan tabeller fr\u00e5n olika <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/sv\/server\/\"   title=\"servrar\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"1482\">servrar<\/a>. Men det \u00e4r redan en historia f\u00f6r en annan artikel.<\/p>\n<p>Tack f\u00f6r din uppm\u00e4rksamhet! Jag ser fram emot fr\u00e5gor, kommentarer och \u00e4ven ber\u00e4ttelser om din erfarenhet i kommentarerna.<br \/>\n<br \/>K\u00e4lla: <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.4 - 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\/sv\/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.4\" \/>\n\t\t<meta property=\"og:locale\" content=\"sv_SE\" \/>\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\/sv\/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\udd47Operativ analys i mikrotj\u00e4nstarkitektur: f\u00f6rst\u00e5 och f\u00f6renkla hj\u00e4lp och v\u00e4gledning Postgres FDW | ProHoster","description":"Mikrotj\u00e4nstarkitektur, precis som allt annat i denna v\u00e4rld, har sina f\u00f6rdelar och nackdelar. Vissa processer blir enklare med den, andra blir sv\u00e5rare.","canonical_url":"https:\/\/prohoster.info\/sv\/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":"sv_SE","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\/sv\/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\/sv\/wp-json\/wp\/v2\/posts\/79467","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/comments?post=79467"}],"version-history":[{"count":2,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts\/79467\/revisions"}],"predecessor-version":[{"id":159871,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts\/79467\/revisions\/159871"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/media\/79468"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/media?parent=79467"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/categories?post=79467"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/tags?post=79467"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}