{"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\/de\/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":"Echtzeitanalytik in einer Mikroservice-Architektur: \u0336v\u0336e\u0336r\u0336s\u0336t\u0336a\u0336n\u0336d\u0336e\u0336n\u0336 \u0336u\u0336n\u0336d\u0336 \u0336e\u0336r\u0336l\u0336e\u0336i\u0336c\u0336h\u0336t\u0336en\u0336 helfen und beraten Postgres FDW","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Die Microservices-Architektur hat, wie alles in dieser Welt, ihre Vor- und Nachteile. Einige Prozesse werden einfacher, andere komplexer. Um eine schnellere Ver\u00e4nderung und bessere Skalierbarkeit zu erreichen, m\u00fcssen jedoch Opfer gebracht werden. Eines davon ist die Komplexit\u00e4t der Analytik. W\u00e4hrend man im Monolithen alle operativen Analysen auf SQL-Abfragen an die analytische Replikation reduzieren kann, hat jeder Dienst in einer Multi-Service-Architektur seine eigene Datenbank, und es scheint, als k\u00f6nnte man nicht mit einer einzigen Abfrage auskommen (oder vielleicht doch?). F\u00fcr diejenigen, die sich interessieren, wie wir das Problem der operativen Analytik in unserem Unternehmen gel\u00f6st haben und gelernt haben, mit dieser L\u00f6sung zu leben \u2013 willkommen.<\/p>\n<p><img decoding=\"async\" alt=\"Echtzeitanalytik in einer Mikroservice-Architektur: \u0336v\u0336e\u0336r\u0336s\u0336t\u0336a\u0336n\u0336d\u0336e\u0336n\u0336 \u0336u\u0336n\u0336d\u0336 \u0336e\u0336r\u0336l\u0336e\u0336i\u0336c\u0336h\u0336t\u0336en\u0336 helfen und beraten Postgres FDW\" src=\"\/wp-content\/uploads\/2020\/04\/4296389f06d488999cc023dcaa3027f7.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nMein Name ist Pawel Siwasch, ich arbeite bei DomKlik in einem Team, das f\u00fcr die Pflege des analytischen Data Warehouses verantwortlich ist. Unsere T\u00e4tigkeit kann bedingt der Datenengineering zugeordnet werden, ist aber in Wirklichkeit viel vielf\u00e4ltiger. Neben den Standardaufgaben im Datenengineering wie ETL\/ELT umfasst es die Unterst\u00fctzung und Anpassung von Werkzeugen zur Datenanalyse sowie die Entwicklung eigener Werkzeuge. Insbesondere f\u00fcr die operative Berichterstattung haben wir beschlossen, so zu tun, als h\u00e4tten wir einen Monolithen und den Analysten eine Datenbank zur Verf\u00fcgung zu stellen, in der alle f\u00fcr sie notwendigen Daten enthalten sind. <noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Wir haben insgesamt verschiedene Optionen in Betracht gezogen. Man h\u00e4tte ein vollst\u00e4ndiges Speicherhaus aufbauen k\u00f6nnen \u2014 wir haben es sogar ausprobiert, aber um ehrlich zu sein, ist es uns nicht gelungen, genug h\u00e4ufige \u00c4nderungen in der Logik mit dem relativ langsamen Prozess des Aufbaus des Speichers und der Anpassung daran in Einklang zu bringen (wenn jemandem dies gelungen ist, schreibt bitte in die Kommentare, wie). Man h\u00e4tte den Analysten sagen k\u00f6nnen: \u201eLeute, lernt Python und arbeitet mit den analytischen Repliken\u201c, aber das w\u00e4re ein zus\u00e4tzliches Kriterium bei der Personalauswahl gewesen, und wir dachten, dass wir dies, wenn m\u00f6glich, vermeiden sollten. Wir haben uns entschieden, die FDW (Foreign Data Wrapper) Technologie auszuprobieren: im Grunde ist das ein Standard-dblink, das im SQL-Standard vorhanden ist, jedoch mit einem viel benutzerfreundlicheren Interface. Auf dieser Grundlage haben wir eine L\u00f6sung entwickelt, die sich letztendlich bew\u00e4hrt hat, und auf der wir geblieben sind. Die Details dazu sind Thema eines separaten Artikels oder vielleicht sogar mehrerer, denn es gibt viel zu erz\u00e4hlen: von der Synchronisation der Datenbankschemas bis hin zum Zugriffsmanagement und der Anonymisierung pers\u00f6nlicher Daten. Es ist auch wichtig zu erw\u00e4hnen, dass diese L\u00f6sung keine echte analytische Datenbanken und Lager ersetzt, sie l\u00f6st lediglich eine spezifische Aufgabe.<\/p>\n<p>Auf oberster Ebene sieht es so aus:<\/p>\n<p><img decoding=\"async\" alt=\"Echtzeitanalytik in einer Mikroservice-Architektur: \u0336v\u0336e\u0336r\u0336s\u0336t\u0336a\u0336n\u0336d\u0336e\u0336n\u0336 \u0336u\u0336n\u0336d\u0336 \u0336e\u0336r\u0336l\u0336e\u0336i\u0336c\u0336h\u0336t\u0336en\u0336 helfen und beraten Postgres FDW\" src=\"\/wp-content\/uploads\/2020\/04\/574da29dfdb40706afe9e817e789a61b.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nEs gibt eine PostgreSQL-Datenbank, in der Benutzer ihre Arbeitsdaten speichern k\u00f6nnen, und das Wichtigste ist, dass diese Datenbank \u00fcber FDW mit den analytischen Repliken aller Dienste verbunden ist. Dies erm\u00f6glicht es, eine Abfrage an mehrere Datenbanken zu stellen, wobei es unerheblich ist, ob es sich um PostgreSQL, MySQL, MongoDB oder etwas anderes handelt (eine Datei, API; falls kein passender Wrapper vorhanden ist, kann man auch eigenen schreiben). So weit, so gut! Gehen wir auseinander?<\/p>\n<p>Wenn alles so schnell und einfach enden w\u00fcrde, dann g\u00e4be es wahrscheinlich diesen Artikel nicht.<\/p>\n<p>Es ist wichtig, genau zu verstehen, wie PostgreSQL Anfragen an entfernte Server verarbeitet. Das erscheint logisch, allerdings wird oft nicht darauf geachtet: PostgreSQL zerlegt die Anfrage in Teile, die unabh\u00e4ngig auf den entfernten Servern ausgef\u00fchrt werden, sammelt diese Daten und f\u00fchrt die finalen Berechnungen selbst durch. Daher h\u00e4ngt die Ausf\u00fchrungsgeschwindigkeit der Anfrage stark davon ab, wie sie formuliert ist. Man sollte auch beachten: Wenn die Daten von einem entfernten Server kommen, sind sie bereits nicht mehr indexiert und es gibt nichts, was dem Planer helfen k\u00f6nnte. Daher k\u00f6nnen nur wir ihm helfen und Anweisungen geben. Genau dar\u00fcber m\u00f6chte ich ausf\u00fchrlicher berichten.<\/p>\n<h1>Ein einfacher Abfrage- und Plan mit ihm<\/h1>\n<p>\nUm zu zeigen, wie PostgreSQL eine Abfrage auf einer Tabelle mit 6 Millionen Zeilen auf einem Remote-Server ausf\u00fchrt, <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/de\/server\/dts-dronten\/\"   title=\"Server\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"2589\">Server<\/a>, betrachten wir einen einfachen Plan.<\/p>\n<pre><code class=\"sql\">erkl\u00e4ren analysieren ausf\u00fchrlich  \nSELECT count(1)\nFROM fdw_schema.tabelle;\n\nAggregate  (Kosten=418383.23..418383.24 Zeilen=1 Breite=8) (tats\u00e4chliche Zeit=3857.198..3857.198 Zeilen=1 Schleifen=1)\n  Ausgabe: count(1)\n  -&gt;  Ausl\u00e4ndische Abtastung auf fdw_schema.&quot;tabelle&quot;  (Kosten=100.00..402376.14 Zeilen=6402838 Breite=0) (tats\u00e4chliche Zeit=4.874..3256.511 Zeilen=6406868 Schleifen=1)\n        Ausgabe: &quot;tabelle&quot;.id, &quot;tabelle&quot;.is_active, &quot;tabelle&quot;.meta, &quot;tabelle&quot;.created_dt\n        Remote SQL: SELECT NULL FROM fdw_schema.tabelle\nPlanungszeit: 0.986 ms\nAusf\u00fchrungszeit: 3857.436 ms<\/code><\/pre>\n<p>\nDie Verwendung der Anweisung VERBOSE erm\u00f6glicht es, die Abfrage zu sehen, die an den Remote-Server gesendet wird, und die Ergebnisse, die wir zur weiteren Verarbeitung erhalten (Zeile RemoteSQL).<\/p>\n<p>Gehen wir einen Schritt weiter und f\u00fcgen wir unserer Abfrage einige Filter hinzu: einen nach <b>boolean<\/b> Feld, einen nach Auftreten <b>timestamp<\/b> im Intervall und einen nach <b>jsonb<\/b>.<\/p>\n<pre><code class=\"sql\">erkl\u00e4ren analysieren ausf\u00fchrlich\nSELECT count(1)\nFROM fdw_schema.tabelle \nWHERE is_active is True\nAND created_dt BETWEEN CURRENT_DATE - INTERVAL '7 Monate' \nAND CURRENT_DATE - INTERVAL '6 Monate'\nAND meta-&gt;&gt;'source' = 'test';\n\nAggregate  (Kosten=577487.69..577487.70 Zeilen=1 Breite=8) (tats\u00e4chliche Zeit=27473.818..25473.819 Zeilen=1 Schleifen=1)\n  Ausgabe: count(1)\n  -&gt;  Ausl\u00e4ndische Abtastung auf fdw_schema.&quot;tabelle&quot;  (Kosten=100.00..577469.21 Zeilen=7390 Breite=0) (tats\u00e4chliche Zeit=31.369..25372.466 Zeilen=1360025 Schleifen=1)\n        Ausgabe: &quot;tabelle&quot;.id, &quot;tabelle&quot;.is_active, &quot;tabelle&quot;.meta, &quot;tabelle&quot;.created_dt\n        Filter: ((&quot;tabelle&quot;.is_active IS TRUE) AND ((&quot;tabelle&quot;.meta -&gt;&gt; 'source'::text) = 'test'::text) AND (&quot;tabelle&quot;.created_dt &gt;= (('jetzt'::cstring)::date - '7 Monate'::interval)) AND (&quot;tabelle&quot;.created_dt &lt;= ((('jetzt'::cstring)::date)::timestamp mit Zeitzone - '6 Monate'::interval)))\n        Zeilen durch Filter entfernt: 5046843\n        Remote SQL: SELECT created_dt, is_active, meta FROM fdw_schema.tabelle\nPlanungszeit: 0.665 ms\nAusf\u00fchrungszeit: 27474.118 ms<\/code><\/pre>\n<p>\nHier liegt genau der Punkt, auf den man beim Schreiben von Abfragen achten muss. Die Filter wurden nicht an den Remote-Server \u00fcbergeben, was bedeutet, dass PostgreSQL alle 6 Millionen Zeilen abruft, um sie dann lokal zu filtern (Zeile Filter) und eine Aggregation durchzuf\u00fchren. Der Schl\u00fcssel zum Erfolg liegt darin, die Abfrage so zu formulieren, dass die Filter an die Remote-Maschine \u00fcbergeben werden und wir nur die ben\u00f6tigten Zeilen erhalten und aggregieren. <\/p>\n<h1>Das ist eine sogenannte Boolean-Schei\u00dfe<\/h1>\n<p>\nBei boolean-Feldern ist alles einfach. Im urspr\u00fcnglichen Abfrage trat das Problem aufgrund des Operators auf, <b>is<\/b>. Wenn wir ihn durch <b>=<\/b>ersetzen, erhalten wir folgendes Ergebnis:<\/p>\n<pre><code class=\"sql\">erkl\u00e4ren analysieren ausf\u00fchrlich\nSELECT count(1)\nFROM fdw_schema.tabelle\nWHERE is_active = True\nAND created_dt BETWEEN CURRENT_DATE - INTERVAL '7 Monate' \nAND CURRENT_DATE - INTERVAL '6 Monate'\nAND meta-&gt;&gt;'source' = 'test';\n\nAggregate  (Kosten=508010.14..508010.15 Zeilen=1 Breite=8) (tats\u00e4chliche Zeit=19064.314..19064.314 Zeilen=1 Schleifen=1)\n  Ausgabe: count(1)\n  -&gt;  Ausl\u00e4ndische Abtastung auf fdw_schema.&quot;tabelle&quot;  (Kosten=100.00..507988.44 Zeilen=8679 Breite=0) (tats\u00e4chliche Zeit=33.035..18951.278 Zeilen=1360025 Schleifen=1)\n        Ausgabe: &quot;tabelle&quot;.id, &quot;tabelle&quot;.is_active, &quot;tabelle&quot;.meta, &quot;tabelle&quot;.created_dt\n        Filter: (((&quot;tabelle&quot;.meta -&gt;&gt; 'source'::text) = 'test'::text) AND (&quot;tabelle&quot;.created_dt &gt;= (('jetzt'::cstring)::date - '7 Monate'::interval)) AND (&quot;tabelle&quot;.created_dt &lt;= ((('jetzt'::cstring)::date)::timestamp mit Zeitzone - '6 Monate'::interval)))\n        Zeilen durch Filter entfernt: 3567989\n        Remote SQL: SELECT created_dt, meta FROM fdw_schema.tabelle WHERE (is_active)\nPlanungszeit: 0.834 ms\nAusf\u00fchrungszeit: 19064.534 ms<\/code><\/pre>\n<p>\nWie Sie sehen k\u00f6nnen, ist der Filter auf den entfernten Server verschoben, und die Ausf\u00fchrungszeit hat sich von 27 auf 19 Sekunden verk\u00fcrzt. <\/p>\n<p>Es ist erw\u00e4hnenswert, dass der Operator <b>is<\/b> sich vom Operator <b>=<\/b> dadurch unterscheidet, dass er mit dem Wert Null arbeiten kann. Das bedeutet, dass <b>is not True<\/b> im Filter die Werte False und Null bel\u00e4sst, w\u00e4hrend <b>!= True<\/b> nur die Werte False bel\u00e4sst. Daher sollten bei der Ersetzung des Operators <b>is not<\/b> zwei Bedingungen mit dem Operator OR im Filter \u00fcbergeben werden, zum Beispiel, <b>WHERE (col != True) OR (col is null)<\/b>.<\/p>\n<p>Mit Boolean haben wir es gekl\u00e4rt, machen wir weiter. Und lassen Sie uns den Filter f\u00fcr den booleschen Wert in den urspr\u00fcnglichen Zustand zur\u00fcckversetzen, um die Auswirkungen anderer \u00c4nderungen unabh\u00e4ngig zu betrachten.<\/p>\n<h1>timestamptz? hz<\/h1>\n<p>\nIm Allgemeinen muss man oft experimentieren, wie man die Abfrage richtig formuliert, wenn entfernte Server beteiligt sind, und dann irgendwie herausfinden, warum es so funktioniert. Es gibt sehr wenig Informationen dazu im Internet. In unseren Experimenten haben wir festgestellt, dass der Filter f\u00fcr ein festes Datum problemlos auf den Remote-Server \u00fcbertragen wird, aber wenn wir das Datum dynamisch angeben wollen, wie z.B. now() oder CURRENT_DATE, funktioniert das nicht. In unserem Beispiel haben wir einen solchen Filter hinzugef\u00fcgt, um sicherzustellen, dass die Spalte created_at Daten enth\u00e4lt, die genau einen Monat in der Vergangenheit liegen (BETWEEN CURRENT_DATE - INTERVAL '7 Monate' AND CURRENT_DATE - INTERVAL '6 Monate'). Was haben wir in diesem Fall unternommen?<\/p>\n<pre><code class=\"sql\">erkl\u00e4ren analysieren ausf\u00fchrlich\nSELECT count(1)\nFROM fdw_schema.table \nWHERE is_active is True\nAND created_dt &gt;= (SELECT CURRENT_DATE::timestamptz - INTERVAL '7 Monate') \nAND created_dt &gt;'source' = 'test';\n\nAggregate  (cost=306875.17..306875.18 rows=1 width=8) (tats\u00e4chliche Zeit=4789.114..4789.115 rows=1 loops=1)\n  Ausgabe: count(1)\n  InitPlan 1 (gibt $0 zur\u00fcck)\n    -&gt;  Ergebnis  (cost=0.00..0.02 rows=1 width=8) (tats\u00e4chliche Zeit=0.007..0.008 rows=1 loops=1)\n          Ausgabe: ((('now'::cstring)::date)::timestamp mit Zeitzone - '7 Monate'::intervall)\n  InitPlan 2 (gibt $1 zur\u00fcck)\n    -&gt;  Ergebnis  (cost=0.00..0.02 rows=1 width=8) (tats\u00e4chliche Zeit=0.002..0.002 rows=1 loops=1)\n          Ausgabe: ((('now'::cstring)::date)::timestamp mit Zeitzone - '6 Monate'::intervall)\n  -&gt;  Foreign Scan auf fdw_schema.\"table\"  (cost=100.02..306874.86 rows=105 width=0) (tats\u00e4chliche Zeit=23.475..4681.419 rows=1360025 loops=1)\n        Ausgabe: \"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        Entfernte Zeilen durch Filter: 76934\n        Remote SQL: SELECT is_active, meta FROM fdw_schema.table WHERE ((created_dt &gt;= $1::timestamp mit Zeitzone)) AND ((created_dt &lt; $2::timestamp mit Zeitzone))\nPlanungszeit: 0.703 ms\nAusf\u00fchrungszeit: 4789.379 ms<\/code><\/pre>\n<p>\nWir haben dem Planer geraten, das Datum im Unterabfrage im Voraus zu berechnen und die bereits vorbereitete Variable in den Filter zu \u00fcbergeben. Und diese Empfehlung hat uns ein hervorragendes Ergebnis gebracht, die Abfrage wurde fast sechs Mal schneller!<\/p>\n<p>Auch hier ist es wichtig, aufmerksam zu sein: der Datentyp in der Unterabfrage muss der gleiche sein wie das Feld, nach dem wir filtern, andernfalls wird der Planer feststellen, dass die Typen unterschiedlich sind und es notwendig ist, zun\u00e4chst alle Daten abzurufen und sie dann lokal zu filtern.<\/p>\n<p>Lassen Sie den Datumsfilter auf den urspr\u00fcnglichen Wert zur\u00fccksetzen.<\/p>\n<h1>Freddy vs. Jsonb<\/h1>\n<p>\nIm Grunde genommen haben die booleschen Felder und Daten bereits ausreiche Beschleunigung f\u00fcr unsere Abfrage gebracht, jedoch blieb noch ein weiterer Datentyp. Der Kampf mit der Filterung dar\u00fcber ist ehrlich gesagt noch nicht zu Ende, obwohl es auch hier Fortschritte gibt. So haben wir es geschafft, den Filter zu \u00fcbermitteln \u00fcber <b>jsonb<\/b> das Feld auf den entfernten Server.<\/p>\n<pre><code class=\"sql\">erkl\u00e4ren analysieren ausf\u00fchrlich\nSELECT count(1)\nFROM fdw_schema.table \nWHERE is_active is True\nAND created_dt BETWEEN CURRENT_DATE - INTERVAL '7 Monate' \nAND CURRENT_DATE - INTERVAL '6 Monate'\nAND meta @&gt; '{\"source\":\"test\"}'::jsonb;\n\nAggregate  (cost=245463.60..245463.61 rows=1 width=8) (tats\u00e4chliche Zeit=6727.589..6727.590 rows=1 loops=1)\n  Ausgabe: count(1)\n  -&gt;  Foreign Scan auf fdw_schema.\"table\"  (cost=1100.00..245459.90 rows=1478 width=0) (tats\u00e4chliche Zeit=16.213..6634.794 rows=1360025 loops=1)\n        Ausgabe: \"table\".id, \"table\".is_active, \"table\".meta, \"table\".created_dt\n        Filter: ((\"table\".is_active IS TRUE) AND (\"table\".created_dt &gt;= (('now'::cstring)::date - '7 Monate'::intervall)) AND (\"table\".created_dt  '{\"source\": \"test\"}'::jsonb))\nPlanungszeit: 0.747 ms\nAusf\u00fchrungszeit: 6727.815 ms<\/code><\/pre>\n<p>\nAnstelle von Filteroperatoren sollten Operatoren zur Existenzpr\u00fcfung verwendet werden <b>jsonb<\/b> in einem anderen. 7 Sekunden statt urspr\u00fcnglichen 29. Bis jetzt ist dies die einzige erfolgreiche Methode zur \u00dcbertragung von Filtern nach <b>jsonb<\/b> auf einen entfernten Server, aber hier ist ein wichtiges Einschr\u00e4nkungen zu beachten: wir verwenden die Version 9.6, planen aber bis Ende April die letzten Tests abzuschlie\u00dfen und auf Version 12 umzusteigen. Sobald wir aktualisiert haben, werden wir berichten, wie sich das ausgewirkt hat, denn es gibt viele vielversprechende \u00c4nderungen wie json_path, das neue Verhalten von CTE und Push Down (seit Version 10 vorhanden). Ich kann es kaum erwarten, das auszuprobieren.<\/p>\n<h1>Finish him<\/h1>\n<p>\nWir haben \u00fcberpr\u00fcft, wie jede \u00c4nderung die Anfragegeschwindigkeit einzeln beeinflusst. Lassen Sie uns nun ansehen, was passiert, wenn alle drei Filter korrekt geschrieben sind.<\/p>\n<pre><code class=\"sql\">erkl\u00e4ren analysiere ausf\u00fchrlich\nSELECT count(1)\nFROM fdw_schema.tabelle \nWHERE is_active = True\nAND created_dt &gt;= (SELECT CURRENT_DATE::timestamptz - INTERVAL '7 Monate') \nAND created_dt  '{\"source\":\"test\"}'::jsonb;\n\nAggregation (Kosten=322041.51..322041.52 Zeilen=1 Breite=8) (tats\u00e4chliche Zeit=2278.867..2278.867 Zeilen=1 Schleifen=1)\n  Ausgabe: count(1)\n  InitPlan 1 (gibt $0 zur\u00fcck)\n    -&gt; Ergebnis (Kosten=0.00..0.02 Zeilen=1 Breite=8) (tats\u00e4chliche Zeit=0.010..0.010 Zeilen=1 Schleifen=1)\n          Ausgabe: ((('jetzt'::cstring)::date)::timestamp mit Zeitzone - '7 Monate'::interval)\n  InitPlan 2 (gibt $1 zur\u00fcck)\n    -&gt; Ergebnis (Kosten=0.00..0.02 Zeilen=1 Breite=8) (tats\u00e4chliche Zeit=0.003..0.003 Zeilen=1 Schleifen=1)\n          Ausgabe: ((('jetzt'::cstring)::date)::timestamp mit Zeitzone - '6 Monate'::interval)\n  -&gt; Auslandsabfrage auf fdw_schema.\"tabelle\" (Kosten=100.02..322041.41 Zeilen=25 Breite=0) (tats\u00e4chliche Zeit=8.597..2153.809 Zeilen=1360025 Schleifen=1)\n        Ausgabe: \"tabelle\".id, \"tabelle\".is_active, \"tabelle\".meta, \"tabelle\".created_dt\n        Remote SQL: SELECT NULL FROM fdw_schema.tabelle WHERE (is_active) AND ((created_dt &gt;= $1::timestamp mit Zeitzone)) AND ((created_dt  '{\"source\": \"test\"}'::jsonb))\nPlanungszeit: 0.820 ms\nAusf\u00fchrungszeit: 2279.087 ms<\/code><\/pre>\n<p>\nJa, die Anfrage sieht komplizierter aus, das ist der Preis, den man zahlen muss, aber die Ausf\u00fchrungszeit betr\u00e4gt 2 Sekunden, was mehr als 10 Mal schneller ist! Und hierbei sprechen wir von einer einfachen Anfrage an einen relativ kleinen Datensatz. Bei realen Anfragen haben wir eine Steigerung von bis zu mehreren hundert Mal erzielt.<\/p>\n<p>Fassen wir zusammen: Wenn Sie PostgreSQL mit FDW verwenden, \u00fcberpr\u00fcfen Sie immer, ob alle Filter an den entfernten Server gesendet werden, und Sie werden gl\u00fccklich sein\u2026 zumindest bis Sie zu Joins zwischen Tabellen aus verschiedenen <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/de\/server\/\"   title=\"Server\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"1482\">Server<\/a>. Aber das ist schon die Geschichte f\u00fcr einen anderen Artikel.<\/p>\n<p>Danke f\u00fcr Ihre Aufmerksamkeit! Ich freue mich auf Fragen, Kommentare und Geschichten \u00fcber Ihre Erfahrungen in den Kommentaren.<br \/>\n<br \/>Quelle: <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.1.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\/de\/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.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"de_DE\" \/>\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\/de\/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\udd47Operative Analytik in der Mikrodiensten-Architektur: helfen und anleiten Postgres FDW | ProHoster","description":"Mikroservice-Architektur hat, wie alles in dieser Welt, ihre Vor- und Nachteile. Einige Prozesse werden dadurch einfacher, andere komplizierter.","canonical_url":"https:\/\/prohoster.info\/de\/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":"de_DE","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\/de\/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\/de\/wp-json\/wp\/v2\/posts\/79467","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/comments?post=79467"}],"version-history":[{"count":2,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/79467\/revisions"}],"predecessor-version":[{"id":159871,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/79467\/revisions\/159871"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media\/79468"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media?parent=79467"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/categories?post=79467"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/tags?post=79467"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}