{"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\/ro\/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":"Analiza opera\u021bional\u0103 \u00een arhitectura microserviciilor: p\u0336e\u0336n\u0336t\u0336r\u0336u\u0336 \u0336a\u0336 \u0336\u00een\u0336\u021b\u0336e\u0336l\u0336e\u0336g\u0336e\u0336 \u0336\u0219i\u0336 \u0336a\u0336 \u0336s\u0336u\u0336p\u0336o\u0336r\u0336t\u0336a\u0336 ajut\u0103 \u0219i sugereaz\u0103 Postgres FDW","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Arhitectura microserviciilor, la fel ca tot ce exist\u0103 \u00een aceast\u0103 lume, are at\u00e2t avantaje, c\u00e2t \u0219i dezavantaje. Unele procese devin mai simple, iar altele \u2014 mai complexe. \u00cen numele rapidit\u0103\u021bii schimb\u0103rilor \u0219i unei scalabilit\u0103\u021bi mai bune, trebuie s\u0103 facem anumite sacrificii. Unul dintre aceste sacrificii este complicarea analizei. Dac\u0103 \u00een monolit toat\u0103 analiza opera\u021bional\u0103 poate fi redus\u0103 la interog\u0103ri SQL c\u0103tre replica analitic\u0103, \u00een arhitectura multi-servicii fiecare serviciu are propria baz\u0103 de date \u0219i pare c\u0103 nu te po\u021bi descurca doar cu o singur\u0103 interogare (sau poate te po\u021bi?). Pentru cei interesa\u021bi de cum am rezolvat problema analizei opera\u021bionale \u00een compania noastr\u0103 \u0219i cum am \u00eenv\u0103\u021bat s\u0103 tr\u0103im cu aceast\u0103 solu\u021bie \u2014 bine a\u021bi venit.<\/p>\n<p><img decoding=\"async\" alt=\"Analiza opera\u021bional\u0103 \u00een arhitectura microserviciilor: p\u0336e\u0336n\u0336t\u0336r\u0336u\u0336 \u0336a\u0336 \u0336\u00een\u0336\u021b\u0336e\u0336l\u0336e\u0336g\u0336e\u0336 \u0336\u0219i\u0336 \u0336a\u0336 \u0336s\u0336u\u0336p\u0336o\u0336r\u0336t\u0336a\u0336 ajut\u0103 \u0219i sugereaz\u0103 Postgres FDW\" src=\"\/wp-content\/uploads\/2020\/04\/4296389f06d488999cc023dcaa3027f7.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nM\u0103 numesc Pavel Siva\u0219, iar la DomClick lucrez \u00een echipa responsabil\u0103 de \u00eentre\u021binerea depozitului de date analitice. Activitatea noastr\u0103 poate fi considerat\u0103 \u00een mod curent inginerie de date, \u00eens\u0103, de fapt, gama de sarcini este mult mai larg\u0103. Exist\u0103 sarcini standard pentru ingineria datelor ETL\/ELT, suport \u0219i adaptare a instrumentelor pentru analiza datelor \u0219i dezvoltarea propriilor instrumente. \u00cen special, pentru rapoartele opera\u021bionale, am decis s\u0103 'ne facem c\u0103 suntem un monolit' \u0219i s\u0103 le oferim anali\u0219tilor o singur\u0103 baz\u0103 \u00een care s\u0103 se reg\u0103seasc\u0103 toate datele necesare. <noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>\u00cen general, am luat \u00een considerare diferite op\u021biuni. Am putea construi un depozit complet \u2013 am \u00eencercat chiar, dar, s\u0103 fiu sincer, nu am reu\u0219it s\u0103 adapt\u0103m modific\u0103rile frecvente \u00een logic\u0103 cu procesul de construire a depozitului \u0219i de implementare a modific\u0103rilor, care era destul de lent (dac\u0103 cineva a reu\u0219it, v\u0103 rog s\u0103 scrie\u021bi \u00een comentarii cum). Am putea s\u0103 le spunem anali\u0219tilor: \u201eB\u0103ie\u021bi, \u00eenv\u0103\u021ba\u021bi python \u0219i folosi\u021bi replici analitice\u201d, dar aceasta ar fi o cerin\u021b\u0103 suplimentar\u0103 \u00een selec\u021bia personalului, iar p\u0103rea c\u0103 ar fi bine s\u0103 evit\u0103m asta, dac\u0103 este posibil. Am decis s\u0103 \u00eencerc\u0103m tehnologia FDW (Foreign Data Wrapper): \u00een esen\u021b\u0103, este un dblink standard, care face parte din standardul SQL, dar cu un interfa\u021b\u0103 mult mai convenabil\u0103. Pe baza acesteia, am dezvoltat o solu\u021bie care, \u00een final, a fost adoptat\u0103, pe care ne-am oprit. Detaliile sale sunt o tem\u0103 de articol separat, \u0219i poate chiar mai multe, deoarece vreau s\u0103 spun multe: de la sincronizarea schemelor bazelor de date p\u00e2n\u0103 la gestionarea accesului \u0219i anonimizarea datelor personale. De asemenea, trebuie men\u021bionat c\u0103 aceast\u0103 solu\u021bie nu este un substitut pentru bazele de date analitice reale \u0219i depozite; ea rezolv\u0103 doar o problem\u0103 specific\u0103.<\/p>\n<p>La un nivel superior, arat\u0103 astfel:<\/p>\n<p><img decoding=\"async\" alt=\"Analiza opera\u021bional\u0103 \u00een arhitectura microserviciilor: p\u0336e\u0336n\u0336t\u0336r\u0336u\u0336 \u0336a\u0336 \u0336\u00een\u0336\u021b\u0336e\u0336l\u0336e\u0336g\u0336e\u0336 \u0336\u0219i\u0336 \u0336a\u0336 \u0336s\u0336u\u0336p\u0336o\u0336r\u0336t\u0336a\u0336 ajut\u0103 \u0219i sugereaz\u0103 Postgres FDW\" src=\"\/wp-content\/uploads\/2020\/04\/574da29dfdb40706afe9e817e789a61b.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nExist\u0103 o baz\u0103 de date PostgreSQL, unde utilizatorii \u00ee\u0219i pot stoca datele de lucru, iar cel mai important \u2013 la aceast\u0103 baz\u0103 sunt conectate, prin FDW, replici analitice din toate serviciile. Aceasta ofer\u0103 posibilitatea de a scrie o interogare pentru mai multe baze, f\u0103r\u0103 a conta ce sunt acestea: PostgreSQL, MySQL, MongoDB sau altceva (fi\u0219ier, API, iar dac\u0103 nu exist\u0103 un wrapper adecvat, putem scrie unul propriu). Cam at\u00e2t, super! Ne descurc\u0103m?<\/p>\n<p>Dac\u0103 totul s-ar termina at\u00e2t de repede \u0219i simplu, probabil c\u0103 nici nu ar mai fi acest articol.<\/p>\n<p>Este important s\u0103 \u00een\u021belegem clar cum PostgreSQL proceseaz\u0103 interog\u0103rile c\u0103tre serverele externe. Acest lucru pare logic, totu\u0219i adesea nu se acord\u0103 aten\u021bie: PostgreSQL \u00eemparte interogarea \u00een p\u0103r\u021bi, care sunt executate pe serverele externe \u00een mod independent, adun\u0103 aceste date, iar calculul final este efectuat de el \u00eensu\u0219i, motiv pentru care viteza de execu\u021bie a interog\u0103rii va depinde foarte mult de modul \u00een care este scris\u0103. De asemenea, trebuie men\u021bionat: atunci c\u00e2nd datele vin de pe un server extern, nu au deja indexuri, nu au nimic care s\u0103 ajute planificatorul, prin urmare, singurii care pot ajuta \u0219i \u00eendruma suntem noi \u00een\u0219ine. \u0218i tocmai despre asta vreau s\u0103 vorbesc mai \u00een detaliu.<\/p>\n<h1>O solicitare simpl\u0103 \u0219i planul asociat<\/h1>\n<p>\nPentru a ar\u0103ta cum PostgreSQL execut\u0103 o interogare pe o mas\u0103 de 6 milioane de r\u00e2nduri pe serverul extern <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/ro\/server\/dts-dronten\/\"   title=\"server\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"2589\">server<\/a>, s\u0103 ne uit\u0103m la un plan simplu.<\/p>\n<pre><code class=\"sql\">explica analize verbose  \nSELECT count(1)\nFROM fdw_schema.table;\n\nAggregate  (cost=418383.23..418383.24 rows=1 width=8) (actual time=3857.198..3857.198 rows=1 loops=1)\n  Output: count(1)\n  -&gt;  Foreign Scan on fdw_schema.&quot;table&quot;  (cost=100.00..402376.14 rows=6402838 width=0) (actual time=4.874..3256.511 rows=6406868 loops=1)\n        Output: &quot;table&quot;.id, &quot;table&quot;.is_active, &quot;table&quot;.meta, &quot;table&quot;.created_dt\n        Remote SQL: SELECT NULL FROM fdw_schema.table\nPlanning time: 0.986 ms\nExecution time: 3857.436 ms<\/code><\/pre>\n<p>\nUtilizarea instruc\u021biunii VERBOSE permite vizualizarea interog\u0103rii care va fi trimis\u0103 la serverul extern \u0219i rezultatele pe care le vom ob\u021bine pentru procesarea ulterioar\u0103 (linia RemoteSQL).<\/p>\n<p>S\u0103 mergem pu\u021bin mai departe \u0219i s\u0103 ad\u0103ug\u0103m c\u00e2teva filtre \u00een interogarea noastr\u0103: unul pe <b>boolean<\/b> c\u00e2mp, unul pe apari\u021bia <b>timestamp<\/b> \u00een interval \u0219i unul pe <b>jsonb<\/b>.<\/p>\n<pre><code class=\"sql\">explica analize verbose\nSELECT count(1)\nFROM fdw_schema.table \nWHERE is_active is True\nAND created_dt BETWEEN CURRENT_DATE - INTERVAL '7 month' \nAND CURRENT_DATE - INTERVAL '6 month'\nAND meta-&gt;&gt;'source' = 'test';\n\nAggregate  (cost=577487.69..577487.70 rows=1 width=8) (actual time=27473.818..25473.819 rows=1 loops=1)\n  Output: count(1)\n  -&gt;  Foreign Scan on fdw_schema.&quot;table&quot;  (cost=100.00..577469.21 rows=7390 width=0) (actual time=31.369..25372.466 rows=1360025 loops=1)\n        Output: &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 IS TRUE) AND ((&quot;table&quot;.meta -&gt;&gt; 'source'::text) = 'test'::text) AND (&quot;table&quot;.created_dt &gt;= (('now'::cstring)::date - '7 mons'::interval)) AND (&quot;table&quot;.created_dt &lt;= ((('now'::cstring)::date)::timestamp with time zone - '6 mons'::interval)))\n        Rows Removed by Filter: 5046843\n        Remote SQL: SELECT created_dt, is_active, meta FROM fdw_schema.table\nPlanning time: 0.665 ms\nExecution time: 27474.118 ms<\/code><\/pre>\n<p>\nAici se afl\u0103 momentul cheie la care trebuie s\u0103 acord\u0103m aten\u021bie atunci c\u00e2nd scriem interog\u0103ri. Filtrele nu au fost transmise la serverul extern, ceea ce \u00eenseamn\u0103 c\u0103 pentru a le executa, PostgreSQL extrage toate cele 6 milioane de r\u00e2nduri, pentru a le filtra local (linia Filter) \u0219i a efectua agregarea. Secretul succesului este s\u0103 scriem interogarea astfel \u00eenc\u00e2t filtrele s\u0103 fie transmise pe ma\u0219ina extern\u0103, iar noi s\u0103 ob\u021binem \u0219i s\u0103 agreg\u0103m doar r\u00e2ndurile necesare. <\/p>\n<h1>Asta e o prostie boolean\u0103<\/h1>\n<p>\nCu c\u00e2mpurile boolean \u2014 totul e simplu. Problema din interogarea ini\u021bial\u0103 a ap\u0103rut din cauza operatorului <b>is<\/b>. Dac\u0103 \u00eel \u00eenlocuim cu <b>=<\/b>, vom ob\u021bine urm\u0103torul rezultat:<\/p>\n<pre><code class=\"sql\">explica analize verbose\nSELECT count(1)\nFROM fdw_schema.table\nWHERE is_active = True\nAND created_dt BETWEEN CURRENT_DATE - INTERVAL '7 month' \nAND CURRENT_DATE - INTERVAL '6 month'\nAND meta-&gt;&gt;'source' = 'test';\n\nAggregate  (cost=508010.14..508010.15 rows=1 width=8) (actual time=19064.314..19064.314 rows=1 loops=1)\n  Output: count(1)\n  -&gt;  Foreign Scan on fdw_schema.&quot;table&quot;  (cost=100.00..507988.44 rows=8679 width=0) (actual time=33.035..18951.278 rows=1360025 loops=1)\n        Output: &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) AND (&quot;table&quot;.created_dt &gt;= (('now'::cstring)::date - '7 mons'::interval)) AND (&quot;table&quot;.created_dt &lt;= ((('now'::cstring)::date)::timestamp with time zone - '6 mons'::interval)))\n        Rows Removed by Filter: 3567989\n        Remote SQL: SELECT created_dt, meta FROM fdw_schema.table WHERE (is_active)\nPlanning time: 0.834 ms\nExecution time: 19064.534 ms<\/code><\/pre>\n<p>\nDup\u0103 cum vede\u021bi, filtrul s-a mutat pe serverul extern, iar timpul de execu\u021bie a sc\u0103zut de la 27 la 19 secunde. <\/p>\n<p>Merit\u0103 men\u021bionat c\u0103 operatorul <b>is<\/b> este diferit de operatorul <b>=<\/b> prin faptul c\u0103 poate lucra cu valoarea Null. Aceasta \u00eenseamn\u0103 c\u0103 <b>is not True<\/b> \u00een filtrul va l\u0103sa valorile False \u0219i Null, \u00een timp ce <b>!= True<\/b> va p\u0103stra doar valorile False. Prin urmare, la \u00eenlocuirea operatorului <b>is not<\/b> ar trebui s\u0103 se transmit\u0103 \u00een filtru dou\u0103 condi\u021bii cu operatorul OR, de exemplu, <b>WHERE (col != True) OR (col is null)<\/b>.<\/p>\n<p>Am \u00een\u021beles boolean-ul, s\u0103 trecem mai departe. \u00centre timp, s\u0103 readucem filtrul pe valoarea boolean\u0103 \u00een forma sa ini\u021bial\u0103, pentru a examina independent efectul altor modific\u0103ri.<\/p>\n<h1>timestamptz? hz<\/h1>\n<p>\n\u00cen general, trebuie adesea s\u0103 experiment\u0103m cu modul corect de a scrie o interogare care implic\u0103 servere remote \u0219i abia apoi s\u0103 c\u0103ut\u0103m explica\u021bia de ce se \u00eent\u00e2mpl\u0103 a\u0219a. Exist\u0103 foarte pu\u021bin\u0103 informa\u021bie pe aceast\u0103 tem\u0103 pe Internet. Astfel, \u00een experimentele noastre am descoperit c\u0103 filtrul pe o dat\u0103 fix\u0103 merge perfect pe serverul remote, dar atunci c\u00e2nd dorim s\u0103 stabilim o dat\u0103 dinamic, de exemplu, now() sau CURRENT_DATE, acest lucru nu se \u00eent\u00e2mpl\u0103. \u00cen exemplul nostru, am ad\u0103ugat un astfel de filtru astfel \u00eenc\u00e2t coloana created_at s\u0103 con\u021bin\u0103 date exact cu 1 lun\u0103 \u00een urm\u0103 (BETWEEN CURRENT_DATE - INTERVAL &#8216;7 month&#8217; AND CURRENT_DATE - INTERVAL &#8216;6 month&#8217;). Ce am f\u0103cut \u00een acest caz?<\/p>\n<pre><code class=\"sql\">explica analiza detaliat\nSELECT count(1)\nFROM fdw_schema.table \nWHERE is_active is True\nAND created_dt &gt;= (SELECT CURRENT_DATE::timestamptz - INTERVAL '7 luni') \nAND created_dt &gt;'source' = 'test';\n\nAgregat  (cost=306875.17..306875.18 r\u00e2nduri=1 l\u0103\u021bime=8) (timp efectiv=4789.114..4789.115 r\u00e2nduri=1 bucle=1)\n  Ie\u0219ire: count(1)\n  InitPlan 1 (\u00eentors $0)\n    -&gt;  Rezultat  (cost=0.00..0.02 r\u00e2nduri=1 l\u0103\u021bime=8) (timp efectiv=0.007..0.008 r\u00e2nduri=1 bucle=1)\n          Ie\u0219ire: ((('now'::cstring)::date)::timestamp cu fus orar - '7 luni'::interval)\n  InitPlan 2 (\u00eentors $1)\n    -&gt;  Rezultat  (cost=0.00..0.02 r\u00e2nduri=1 l\u0103\u021bime=8) (timp efectiv=0.002..0.002 r\u00e2nduri=1 bucle=1)\n          Ie\u0219ire: ((('now'::cstring)::date)::timestamp cu fus orar - '6 luni'::interval)\n  -&gt;  Scanare extern\u0103 pe fdw_schema.\"table\"  (cost=100.02..306874.86 r\u00e2nduri=105 l\u0103\u021bime=0) (timp efectiv=23.475..4681.419 r\u00e2nduri=1360025 bucle=1)\n        Ie\u0219ire: \"table\".id, \"table\".is_active, \"table\".meta, \"table\".created_dt\n        Filtru: ((\"table\".is_active IS TRUE) AND ((\"table\".meta -&gt;&gt; 'source'::text) = 'test'::text))\n        R\u00e2nduri eliminate prin filtrare: 76934\n        SQL la distan\u021b\u0103: SELECT is_active, meta FROM fdw_schema.table WHERE ((created_dt &gt;= $1::timestamp cu fus orar)) AND ((created_dt &lt; $2::timestamp cu fus orar))\nTimp de planificare: 0.703 ms\nTimp de execu\u021bie: 4789.379 ms<\/code><\/pre>\n<p>\nAm sugerat planificatorului s\u0103 calculeze dinainte data \u00een subinterogare \u0219i s\u0103 transmit\u0103 deja variabila gata \u00een filtrul de date. Aceast\u0103 sugestie ne-a adus un rezultat excelent, interogarea a fost accelerat\u0103 de aproape \u0219ase ori!<\/p>\n<p>Din nou, este important s\u0103 fii atent: tipul de date din subinterogare trebuie s\u0103 fie acela\u0219i cu cel al c\u00e2mpului pe care filtr\u0103m, altfel planificatorul va considera c\u0103, av\u00e2nd tipuri diferite, este necesar mai \u00eent\u00e2i s\u0103 ob\u021binem toate datele \u0219i s\u0103 le filtr\u0103m local.<\/p>\n<p>S\u0103 return\u0103m filtrul pe dat\u0103 la valoarea ini\u021bial\u0103.<\/p>\n<h1>Freddy vs. Jsonb<\/h1>\n<p>\n\u00cen general, c\u00e2mpurile boolean \u0219i datele au fost suficient pentru a accelera interogarea noastr\u0103, totu\u0219i exista \u00eenc\u0103 un alt tip de date. Lupta cu filtrarea lui nu s-a \u00eencheiat, de\u0219i \u0219i aici exist\u0103 progrese. A\u0219adar, iat\u0103 cum am reu\u0219it s\u0103 transmitem filtrul pe <b>jsonb<\/b> c\u00e2mpul pe serverul la distan\u021b\u0103.<\/p>\n<pre><code class=\"sql\">explica analiza detaliat\nSELECT count(1)\nFROM fdw_schema.table \nWHERE is_active is True\nAND created_dt \u00ceNTRE CURRENT_DATE - INTERVAL '7 luni' \n\u0218I CURRENT_DATE - INTERVAL '6 luni'\nAND meta @&gt; '{\"source\":\"test\"}'::jsonb;\n\nAgregat  (cost=245463.60..245463.61 r\u00e2nduri=1 l\u0103\u021bime=8) (timp efectiv=6727.589..6727.590 r\u00e2nduri=1 bucle=1)\n  Ie\u0219ire: count(1)\n  -&gt;  Scanare extern\u0103 pe fdw_schema.\"table\"  (cost=1100.00..245459.90 r\u00e2nduri=1478 l\u0103\u021bime=0) (timp efectiv=16.213..6634.794 r\u00e2nduri=1360025 bucle=1)\n        Ie\u0219ire: \"table\".id, \"table\".is_active, \"table\".meta, \"table\".created_dt\n        Filtru: ((\"table\".is_active IS TRUE) AND (\"table\".created_dt &gt;= (('now'::cstring)::date - '7 luni'::interval)) AND (\"table\".created_dt  '{\"source\": \"test\"}'::jsonb))\nTimp de planificare: 0.747 ms\nTimp de execu\u021bie: 6727.815 ms<\/code><\/pre>\n<p>\nEste necesar s\u0103 folosim operatorul de existen\u021b\u0103 \u00een locul operatorilor de filtrare. <b>jsonb<\/b> \u00een alt\u0103 parte. 7 secunde \u00een loc de 29 ini\u021biale. P\u00e2n\u0103 acum, aceasta este singura variant\u0103 de succes pentru transmiterea filtrilor prin <b>jsonb<\/b> un server extern, dar aici este important s\u0103 \u021binem cont de o restric\u021bie: folosim versiunea bazei de date 9.6, dar p\u00e2n\u0103 la sf\u00e2r\u0219itul lunii aprilie planific\u0103m s\u0103 finaliz\u0103m ultimele teste \u0219i s\u0103 trecem la versiunea 12. C\u00e2nd ne vom actualiza, vom scrie cum a influen\u021bat, deoarece sunt multe schimb\u0103ri, pe care ne punem multe speran\u021be: json_path, un comportament nou CTE, push down (existent din versiunea 10). A\u0219 dori s\u0103 \u00eencerc c\u00e2t mai cur\u00e2nd.<\/p>\n<h1>Finish him<\/h1>\n<p>\nAm verificat cum fiecare modificare afecteaz\u0103 viteza interog\u0103rii pe r\u00e2nd. S\u0103 vedem acum ce se va \u00eent\u00e2mpla c\u00e2nd toate cele trei filtre sunt scrise corect.<\/p>\n<pre><code class=\"sql\">explain analyze verbose\nSELECT count(1)\nFROM fdw_schema.table\nWHERE is_active = True\nAND created_dt &gt;= (SELECT CURRENT_DATE::timestamptz - INTERVAL '7 month')\nAND created_dt  '{\"source\":\"test\"}'::jsonb;\n\nAggregate (cost=322041.51..322041.52 rows=1 width=8) (actual time=2278.867..2278.867 rows=1 loops=1)\n  Output: count(1)\n  InitPlan 1 (returns $0)\n    -&gt; Result (cost=0.00..0.02 rows=1 width=8) (actual time=0.010..0.010 rows=1 loops=1)\n          Output: ((('now'::cstring)::date)::timestamp with time zone - '7 mons'::interval)\n  InitPlan 2 (returns $1)\n    -&gt; Result (cost=0.00..0.02 rows=1 width=8) (actual time=0.003..0.003 rows=1 loops=1)\n          Output: ((('now'::cstring)::date)::timestamp with time zone - '6 mons'::interval)\n  -&gt; Foreign Scan on fdw_schema.\"table\" (cost=100.02..322041.41 rows=25 width=0) (actual time=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 with time zone)) AND ((created_dt  '{\"source\": \"test\"}'::jsonb))\nPlanning time: 0.820 ms\nExecution time: 2279.087 ms<\/code><\/pre>\n<p>\nDa, interogarea arat\u0103 mai complex\u0103, este o plat\u0103 for\u021bat\u0103, dar viteza de execu\u021bie este de 2 secunde, ceea ce este de peste 10 ori mai rapid! \u0218i vorbim aici despre o interogare simpl\u0103 pe un set de date relativ mic. La interog\u0103rile reale, am ob\u021binut un c\u00e2\u0219tig de p\u00e2n\u0103 la c\u00e2teva sute de ori.<\/p>\n<p>S\u0103 rezum\u0103m: dac\u0103 folosi\u021bi PostgreSQL cu FDW, verifica\u021bi \u00eentotdeauna dac\u0103 toate filtrele sunt trimise pe serverul extern, \u0219i ve\u021bi avea succes... Cel pu\u021bin p\u00e2n\u0103 nu ajunge\u021bi la join-uri \u00eentre tabele din diferite <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/ro\/server\/\"   title=\"servere\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"1482\">servere<\/a>. Dar aceasta este deja o poveste pentru un alt articol.<\/p>\n<p>Mul\u021bumesc pentru aten\u021bie! Voi fi bucuros s\u0103 aud \u00eentreb\u0103ri, comentarii, precum \u0219i pove\u0219ti despre experien\u021ba dumneavoastr\u0103 \u00een comentarii.<br \/>\n<br \/>Sursa: <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.2.1 - 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\/ro\/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<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"ro_RO\" \/>\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\/ro\/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\udd47Analiza operativ\u0103 \u00een arhitectura microserviciilor: a ajuta \u0219i a sf\u0103tui Postgres FDW | ProHoster","description":"Arhitectura microserviciilor, ca tot ce exist\u0103 \u00een aceast\u0103 lume, are avantajele \u0219i dezavantajele ei. Unele procese devin mai simple, altele mai complicate.","canonical_url":"https:\/\/prohoster.info\/ro\/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":"ro_RO","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\/ro\/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\/ro\/wp-json\/wp\/v2\/posts\/79467","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/comments?post=79467"}],"version-history":[{"count":2,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts\/79467\/revisions"}],"predecessor-version":[{"id":159871,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts\/79467\/revisions\/159871"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/media\/79468"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/media?parent=79467"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/categories?post=79467"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/tags?post=79467"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}