{"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\/pt\/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":"An\u00e1lise em tempo real na arquitetura de microsservi\u00e7os: ajudar e orientar Postgres FDW","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>A arquitetura de microsservi\u00e7os, assim como tudo neste mundo, tem suas vantagens e desvantagens. Alguns processos se tornam mais simples, enquanto outros se tornam mais complexos. E, em nome da velocidade das mudan\u00e7as e de uma melhor escalabilidade, \u00e9 preciso fazer sacrif\u00edcios. Um deles \u00e9 a complexidade da an\u00e1lise. Enquanto em um mon\u00f3lito toda a an\u00e1lise operacional pode ser reduzida a consultas SQL a uma r\u00e9plica anal\u00edtica, na arquitetura de m\u00faltiplos servi\u00e7os, cada servi\u00e7o possui seu pr\u00f3prio banco de dados, e parece que n\u00e3o \u00e9 poss\u00edvel contornar isso com uma \u00fanica consulta (ou talvez seja?). Para aqueles que est\u00e3o interessados em como resolvemos o problema da an\u00e1lise operacional em nossa empresa e como aprendemos a conviver com essa solu\u00e7\u00e3o \u2014 sejam bem-vindos.<\/p>\n<p><img decoding=\"async\" alt=\"An\u00e1lise em tempo real na arquitetura de microsservi\u00e7os: ajudar e orientar Postgres FDW\" src=\"\/wp-content\/uploads\/2020\/04\/4296389f06d488999cc023dcaa3027f7.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nMeu nome \u00e9 Pavel Sivash, e na Domclick trabalho na equipe respons\u00e1vel pela manuten\u00e7\u00e3o do armaz\u00e9m de dados anal\u00edticos. Nossa atividade pode ser resumida como engenharia de dados, mas, na verdade, o espectro de tarefas \u00e9 muito mais amplo. Existem as fun\u00e7\u00f5es padr\u00e3o da engenharia de dados, como ETL\/ELT, suporte e adapta\u00e7\u00e3o de ferramentas para an\u00e1lise de dados, e o desenvolvimento de nossas pr\u00f3prias ferramentas. Em particular, para relat\u00f3rios operacionais, decidimos \"fingir\" que temos um mon\u00f3lito e dar aos analistas um \u00fanico banco de dados, que contenha todas as informa\u00e7\u00f5es necess\u00e1rias para eles. <noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>No geral, consideramos v\u00e1rias op\u00e7\u00f5es. Poder\u00edamos construir um armazenamento completo \u2014 at\u00e9 tentamos, mas, para ser honesto, n\u00e3o conseguimos alinhar as mudan\u00e7as frequentes na l\u00f3gica com o processo relativamente lento de constru\u00e7\u00e3o do armazenamento e a inclus\u00e3o de altera\u00e7\u00f5es nele (se algu\u00e9m conseguiu, escreva nos coment\u00e1rios como). Poder\u00edamos ter dito aos analistas: \"Pessoal, aprendam Python e usem r\u00e9plicas anal\u00edticas\", mas isso seria um requisito adicional na sele\u00e7\u00e3o de pessoal e parecia que poder\u00edamos evitar esse custo, se poss\u00edvel. Decidimos experimentar a tecnologia FDW (Foreign Data Wrapper): essencialmente, \u00e9 um dblink padr\u00e3o que existe no padr\u00e3o SQL, mas com uma interface muito mais conveniente. Com base nisso, criamos uma solu\u00e7\u00e3o que acabou se consolidando e foi a que escolhemos. Os detalhes dela s\u00e3o tema de um artigo \u00e0 parte, ou talvez mais de um, j\u00e1 que h\u00e1 muito a se contar: desde a sincroniza\u00e7\u00e3o de esquemas de bancos at\u00e9 a gest\u00e3o de acesso e a desidentifica\u00e7\u00e3o de dados pessoais. Tamb\u00e9m \u00e9 necess\u00e1rio esclarecer que esta solu\u00e7\u00e3o n\u00e3o substitui bancos anal\u00edticos reais e armaz\u00e9ns de dados; ela resolve apenas uma tarefa espec\u00edfica.<\/p>\n<p>Em um n\u00edvel mais alto, isso parece assim:<\/p>\n<p><img decoding=\"async\" alt=\"An\u00e1lise em tempo real na arquitetura de microsservi\u00e7os: ajudar e orientar Postgres FDW\" src=\"\/wp-content\/uploads\/2020\/04\/574da29dfdb40706afe9e817e789a61b.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nH\u00e1 um banco de dados PostgreSQL, onde os usu\u00e1rios podem armazenar seus dados de trabalho, e o mais importante \u2014 a esse banco est\u00e1 conectado, atrav\u00e9s do FDW, as r\u00e9plicas anal\u00edticas de todos os servi\u00e7os. Isso possibilita escrever uma consulta para v\u00e1rios bancos, independentemente de serem: PostgreSQL, MySQL, MongoDB ou qualquer outra coisa (um arquivo, API, se n\u00e3o houver um wrapper adequado, voc\u00ea pode escrever o seu pr\u00f3prio). Bem, isso \u00e9 tudo, maravilha! Vamos embora?<\/p>\n<p>Se tudo terminasse t\u00e3o rapidamente e facilmente, provavelmente n\u00e3o haveria artigo algum.<\/p>\n<p>\u00c9 importante ter uma compreens\u00e3o clara de como o PostgreSQL processa consultas a servidores remotos. Isso parece l\u00f3gico, no entanto, muitas vezes n\u00e3o se presta aten\u00e7\u00e3o a isso: o PostgreSQL divide a consulta em partes que s\u00e3o executadas nos servidores remotos de forma independente, coleta esses dados e realiza os c\u00e1lculos finais, portanto, a velocidade de execu\u00e7\u00e3o da consulta depender\u00e1 muito de como ela \u00e9 escrita. Tamb\u00e9m \u00e9 importante observar: quando os dados chegam de um servidor remoto, eles j\u00e1 n\u00e3o possuem \u00edndices, n\u00e3o t\u00eam nada que ajude o planejador, portanto, s\u00f3 podemos ajudar e orientar usando nosso pr\u00f3prio trabalho. E \u00e9 exatamente isso que quero detalhar mais.<\/p>\n<h1>Consulta simples e plano com ele<\/h1>\n<p>\nPara mostrar como o PostgreSQL executa uma consulta em uma tabela com 6 milh\u00f5es de linhas remotamente <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/pt\/server\/dts-dronten\/\"   title=\"servidor\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"2589\">servidor<\/a>, vamos dar uma olhada em um plano simples.<\/p>\n<pre><code class=\"sql\">explicar analisar detalhadamente  \nSELECIONAR count(1)\nDE fdw_schema.tabela;\n\nAgregado  (custo=418383.23..418383.24 linhas=1 largura=8) (tempo real 3857.198..3857.198 linhas=1 loops=1)\n  Sa\u00edda: count(1)\n  -&gt;  Escaneamento Externo em fdw_schema.&quot;tabela&quot;  (custo=100.00..402376.14 linhas=6402838 largura=0) (tempo real 4.874..3256.511 linhas=6406868 loops=1)\n        Sa\u00edda: &quot;tabela&quot;.id, &quot;tabela&quot;.is_active, &quot;tabela&quot;.meta, &quot;tabela&quot;.created_dt\n        SQL Remota: SELECIONE NULL DE fdw_schema.tabela\nTempo de planejamento: 0.986 ms\nTempo de execu\u00e7\u00e3o: 3857.436 ms<\/code><\/pre>\n<p>\nO uso da instru\u00e7\u00e3o VERBOSE permite ver a consulta que ser\u00e1 enviada ao servidor remoto e os resultados que obteremos para processamento adicional (linha RemoteSQL).<\/p>\n<p>Vamos dar um passo al\u00e9m e adicionar alguns filtros \u00e0 nossa consulta: um por <b>booleano<\/b> campo, um por ocorr\u00eancia <b>timestamp<\/b> em intervalo e um por <b>jsonb<\/b>.<\/p>\n<pre><code class=\"sql\">explicar analisar detalhadamente\nSELECIONAR count(1)\nDE fdw_schema.tabela \nONDE is_active \u00e9 Verdadeiro\nE created_dt ENTRE DATA_ATUAL - INTERVALO '7 meses' \nE DATA_ATUAL - INTERVALO '6 meses'\nE meta-&gt;&gt;'source' = 'teste';\n\nAgregado  (custo=577487.69..577487.70 linhas=1 largura=8) (tempo real 27473.818..25473.819 linhas=1 loops=1)\n  Sa\u00edda: count(1)\n  -&gt;  Escaneamento Externo em fdw_schema.&quot;tabela&quot;  (custo=100.00..577469.21 linhas=7390 largura=0) (tempo real 31.369..25372.466 linhas=1360025 loops=1)\n        Sa\u00edda: &quot;tabela&quot;.id, &quot;tabela&quot;.is_active, &quot;tabela&quot;.meta, &quot;tabela&quot;.created_dt\n        Filtro: ((&quot;tabela&quot;.is_active \u00c9 VERDADEIRO) E ((&quot;tabela&quot;.meta -&gt;&gt; 'source'::texto) = 'teste'::texto) E (&quot;tabela&quot;.created_dt &gt;= (('agora'::cstring)::data - '7 meses'::intervalo)) E (&quot;tabela&quot;.created_dt &lt;= ((('agora'::cstring)::data)::timestamp com fuso hor\u00e1rio - '6 meses'::intervalo)))\n        Linhas removidas pelo filtro: 5046843\n        SQL Remota: SELECIONE created_dt, is_active, meta DE fdw_schema.tabela\nTempo de planejamento: 0.665 ms\nTempo de execu\u00e7\u00e3o: 27474.118 ms<\/code><\/pre>\n<p>\n\u00c9 exatamente aqui que est\u00e1 o ponto a ser observado ao escrever consultas. Os filtros n\u00e3o foram enviados para o servidor remoto, o que significa que, para execut\u00e1-los, o PostgreSQL puxa todas as 6 milh\u00f5es de linhas para depois filtrar localmente (linha Filter) e realizar a agrega\u00e7\u00e3o. O segredo do sucesso \u00e9 escrever a consulta de forma que os filtros sejam enviados \u00e0 m\u00e1quina remota, resultando apenas nas linhas que precisamos. <\/p>\n<h1>Isso \u00e9 uma bobagem booleano<\/h1>\n<p>\nCom campos booleanos, tudo \u00e9 simples. No pedido original, o problema surgiu devido ao operador <b>is<\/b>. Se substituirmos por <b>=<\/b>, obteremos o seguinte resultado:<\/p>\n<pre><code class=\"sql\">explicar analisar detalhadamente\nSELECIONAR count(1)\nDE fdw_schema.tabela\nONDE is_active = Verdadeiro\nE created_dt ENTRE DATA_ATUAL - INTERVALO '7 meses' \nE DATA_ATUAL - INTERVALO '6 meses'\nE meta-&gt;&gt;'source' = 'teste';\n\nAgregado  (custo=508010.14..508010.15 linhas=1 largura=8) (tempo real 19064.314..19064.314 linhas=1 loops=1)\n  Sa\u00edda: count(1)\n  -&gt;  Escaneamento Externo em fdw_schema.&quot;tabela&quot;  (custo=100.00..507988.44 linhas=8679 largura=0) (tempo real 33.035..18951.278 linhas=1360025 loops=1)\n        Sa\u00edda: &quot;tabela&quot;.id, &quot;tabela&quot;.is_active, &quot;tabela&quot;.meta, &quot;tabela&quot;.created_dt\n        Filtro: (((&quot;tabela&quot;.meta -&gt;&gt; 'source'::texto) = 'teste'::texto) E (&quot;tabela&quot;.created_dt &gt;= (('agora'::cstring)::data - '7 meses'::intervalo)) E (&quot;tabela&quot;.created_dt &lt;= ((('agora'::cstring)::data)::timestamp com fuso hor\u00e1rio - '6 meses'::intervalo)))\n        Linhas removidas pelo filtro: 3567989\n        SQL Remota: SELECIONE created_dt, meta DE fdw_schema.tabela ONDE (is_active)\nTempo de planejamento: 0.834 ms\nTempo de execu\u00e7\u00e3o: 19064.534 ms<\/code><\/pre>\n<p>\nComo voc\u00ea pode ver, o filtro foi para o servidor remoto, e o tempo de execu\u00e7\u00e3o diminuiu de 27 para 19 segundos. <\/p>\n<p>Vale a pena notar que o operador <b>is<\/b> diferencia-se do operador <b>=<\/b> porque ele pode lidar com o valor Nulo. Isso significa que <b>n\u00e3o \u00e9 Verdadeiro<\/b> no filtro deixar\u00e1 valores Falsos e Nulos, enquanto que <b>!= Verdadeiro<\/b> deixar\u00e1 apenas valores Falsos. Portanto, ao substituir o operador <b>n\u00e3o \u00e9<\/b> deve-se passar no filtro duas condi\u00e7\u00f5es com o operador OU, por exemplo, <b>ONDE (col != Verdadeiro) OU (col \u00e9 nulo)<\/b>.<\/p>\n<p>Resolvido o booleano, vamos seguir em frente. Enquanto isso, vamos retornar o filtro sobre o valor booleano ao seu estado original, para analisar de forma independente o efeito de outras mudan\u00e7as.<\/p>\n<h1>timestamptz? hz<\/h1>\n<p>\nNa verdade, muitas vezes \u00e9 necess\u00e1rio experimentar como escrever corretamente uma consulta que envolva servidores remotos e, em seguida, procurar a explica\u00e7\u00e3o do porqu\u00ea isso acontece. H\u00e1 muito poucas informa\u00e7\u00f5es sobre isso dispon\u00edveis na Internet. Assim, em nossos experimentos, descobrimos que o filtro por uma data fixa vai para o servidor remoto sem problemas, mas quando tentamos definir a data dinamicamente, como now() ou DATA_ATUAL, isso n\u00e3o acontece. No nosso exemplo, adicionamos esse filtro para que a coluna created_at contivesse dados de exatamente 1 m\u00eas atr\u00e1s (BETWEEN DATA_ATUAL - INTERVALO '7 meses' E DATA_ATUAL - INTERVALO '6 meses'). O que fizemos nesse caso?<\/p>\n<pre><code class=\"sql\">explica\u00e7\u00e3o analisa detalhada\nSELECIONE count(1)\nDE fdw_schema.tabela \nONDE is_active \u00e9 Verdadeiro\nE created_dt &gt;= (SELECIONE CURRENT_DATE::timestamptz - INTERVALO '7 meses') \nE created_dt &gt;'source' = 'teste';\n\nAgrega\u00e7\u00e3o  (custo=306875.17..306875.18 linhas=1 largura=8) (tempo real 4789.114..4789.115 linhas=1 loops=1)\n  Sa\u00edda: count(1)\n  InitPlan 1 (retorna $0)\n    -&gt;  Resultado  (custo=0.00..0.02 linhas=1 largura=8) (tempo real 0.007..0.008 linhas=1 loops=1)\n          Sa\u00edda: ((('agora'::cstring)::data)::timestamp com fuso hor\u00e1rio - '7 meses'::intervalo)\n  InitPlan 2 (retorna $1)\n    -&gt;  Resultado  (custo=0.00..0.02 linhas=1 largura=8) (tempo real 0.002..0.002 linhas=1 loops=1)\n          Sa\u00edda: ((('agora'::cstring)::data)::timestamp com fuso hor\u00e1rio - '6 meses'::intervalo)\n  -&gt;  Escaneamento Externo em fdw_schema.\"tabela\"  (custo=100.02..306874.86 linhas=105 largura=0) (tempo real 23.475..4681.419 linhas=1360025 loops=1)\n        Sa\u00edda: \"tabela\".id, \"tabela\".is_active, \"tabela\".meta, \"tabela\".created_dt\n        Filtro: ((\"tabela\".is_active \u00c9 VERDADEIRO) E ((\"tabela\".meta -&gt;&gt; 'source'::texto) = 'teste'::texto))\n        Linhas removidas pelo filtro: 76934\n        SQL Remoto: SELECIONE is_active, meta DE fdw_schema.tabela ONDE ((created_dt &gt;= $1::timestamp com fuso hor\u00e1rio)) E ((created_dt &lt; $2::timestamp com fuso hor\u00e1rio))\nTempo de planejamento: 0.703 ms\nTempo de execu\u00e7\u00e3o: 4789.379 ms<\/code><\/pre>\n<p>\nN\u00f3s dissemos ao planejador para calcular antecipadamente a data na subconsulta e passar uma vari\u00e1vel j\u00e1 pronta para o filtro. E essa dica nos deu um resultado excelente, a consulta ficou quase 6 vezes mais r\u00e1pida!<\/p>\n<p>Mais uma vez, \u00e9 importante ter cuidado: o tipo de dado na subconsulta deve ser o mesmo que o do campo pelo qual filtramos, caso contr\u00e1rio, o planejador decidir\u00e1 que como os tipos s\u00e3o diferentes, \u00e9 necess\u00e1rio obter todos os dados e filtrar localmente.<\/p>\n<p>Vamos retornar o filtro de data para seu valor original.<\/p>\n<h1>Freddy vs. Jsonb<\/h1>\n<p>\nDe fato, os campos booleanos e as datas j\u00e1 aceleraram bastante nossa consulta, mas ainda havia um tipo de dado restante. A batalha para filtr\u00e1-lo, honestamente, ainda n\u00e3o acabou, embora tenhamos feito progressos aqui tamb\u00e9m. Ent\u00e3o, aqui est\u00e1 como conseguimos passar o filtro por <b>jsonb<\/b> campo para o servidor remoto.<\/p>\n<pre><code class=\"sql\">explica\u00e7\u00e3o analisa detalhada\nSELECIONE count(1)\nDE fdw_schema.tabela \nONDE is_active \u00e9 Verdadeiro\nE created_dt ENTRE CURRENT_DATE - INTERVALO '7 meses' \nE CURRENT_DATE - INTERVALO '6 meses'\nE meta @&gt; '{\"source\":\"teste\"}'::jsonb;\n\nAgrega\u00e7\u00e3o  (custo=245463.60..245463.61 linhas=1 largura=8) (tempo real 6727.589..6727.590 linhas=1 loops=1)\n  Sa\u00edda: count(1)\n  -&gt;  Escaneamento Externo em fdw_schema.\"tabela\"  (custo=1100.00..245459.90 linhas=1478 largura=0) (tempo real 16.213..6634.794 linhas=1360025 loops=1)\n        Sa\u00edda: \"tabela\".id, \"tabela\".is_active, \"tabela\".meta, \"tabela\".created_dt\n        Filtro: ((\"tabela\".is_active \u00c9 VERDADEIRO) E (\"tabela\".created_dt &gt;= (('agora'::cstring)::data - '7 meses'::intervalo)) E (\"tabela\".created_dt  '{\"source\": \"teste\"}'::jsonb))\nTempo de planejamento: 0.747 ms\nTempo de execu\u00e7\u00e3o: 6727.815 ms<\/code><\/pre>\n<p>\nEm vez de operadores de filtragem, deve-se usar o operador de exist\u00eancia de um <b>jsonb<\/b> em outro. 7 segundos em vez dos 29 originais. At\u00e9 agora, esta \u00e9 a \u00fanica op\u00e7\u00e3o bem-sucedida de transfer\u00eancia de filtros por <b>jsonb<\/b> para um servidor remoto, mas aqui \u00e9 importante considerar uma limita\u00e7\u00e3o: estamos usando a vers\u00e3o 9.6 do banco de dados, no entanto, at\u00e9 o final de abril, planejamos concluir os \u00faltimos testes e migrar para a vers\u00e3o 12. Assim que atualizarmos, escreveremos sobre como isso afetou, pois h\u00e1 muitas mudan\u00e7as nas quais temos grandes esperan\u00e7as: json_path, novo comportamento de CTE, push down (existente desde a vers\u00e3o 10). Estamos ansiosos para experimentar.<\/p>\n<h1>Acabe com ele<\/h1>\n<p>\nVerificamos como cada altera\u00e7\u00e3o afeta a velocidade da consulta individualmente. Agora vamos ver o que acontece quando os tr\u00eas filtros s\u00e3o escritos corretamente.<\/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>\nSim, a consulta parece mais complexa, \u00e9 um pre\u00e7o a ser pago, mas a velocidade de execu\u00e7\u00e3o \u00e9 de 2 segundos, o que \u00e9 mais de 10 vezes mais r\u00e1pido! E estamos falando de uma consulta simples a um conjunto de dados relativamente pequeno. Nas consultas reais, vimos aumentos de at\u00e9 v\u00e1rias centenas de vezes.<\/p>\n<p>Vamos resumir: se voc\u00ea estiver usando PostgreSQL com FDW, sempre verifique se todos os filtros est\u00e3o sendo enviados para o servidor remoto, e voc\u00ea ser\u00e1 feliz... Pelo menos, at\u00e9 voc\u00ea chegar aos joins entre tabelas de diferentes <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/pt\/server\/\"   title=\"servidores\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"1482\">servidores<\/a>. Mas essa \u00e9 uma hist\u00f3ria para outro artigo.<\/p>\n<p>Obrigado pela aten\u00e7\u00e3o! Ficarei feliz em ouvir perguntas, coment\u00e1rios, bem como hist\u00f3rias sobre sua experi\u00eancia nos coment\u00e1rios.<br \/>\n<br \/>Fonte: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/domclick\/blog\/498018\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430, \u043a\u0430\u043a \u0438 \u0432\u0441\u0435 \u0432 \u044d\u0442\u043e\u043c \u043c\u0438\u0440\u0435, \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0438 \u043f\u043b\u044e\u0441\u044b \u0438 \u0441\u0432\u043e\u0438 \u043c\u0438\u043d\u0443\u0441\u044b. \u041e\u0434\u043d\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b \u0441 \u043d\u0435\u0439 \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u043f\u0440\u043e\u0449\u0435, \u0434\u0440\u0443\u0433\u0438\u0435 \u2014 \u0441\u043b\u043e\u0436\u043d\u0435\u0435. \u0418 \u0432 \u0443\u0433\u043e\u0434\u0443 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0438 \u043b\u0443\u0447\u0448\u0435\u0439 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e\u0441\u0442\u0438 \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u0438\u043d\u043e\u0441\u0438\u0442\u044c \u0441\u0432\u043e\u0438 \u0436\u0435\u0440\u0442\u0432\u044b. \u041e\u0434\u043d\u0430 \u0438\u0437 \u043d\u0438\u0445 \u2014 \u0443\u0441\u043b\u043e\u0436\u043d\u0435\u043d\u0438\u0435 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0438. \u0415\u0441\u043b\u0438 \u0432 \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u0435 \u0432\u0441\u044e \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u0443\u044e \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0443 \u043c\u043e\u0436\u043d\u043e \u0441\u0432\u0435\u0441\u0442\u0438 \u043a SQL \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c \u043a \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0440\u0435\u043f\u043b\u0438\u043a\u0435, [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":79468,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-79467","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.3 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430, \u043a\u0430\u043a \u0438 \u0432\u0441\u0435 \u0432 \u044d\u0442\u043e\u043c \u043c\u0438\u0440\u0435, \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0438 \u043f\u043b\u044e\u0441\u044b \u0438 \u0441\u0432\u043e\u0438 \u043c\u0438\u043d\u0443\u0441\u044b. \u041e\u0434\u043d\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b \u0441 \u043d\u0435\u0439 \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u043f\u0440\u043e\u0449\u0435, \u0434\u0440\u0443\u0433\u0438\u0435 \u2014 \u0441\u043b\u043e\u0436\u043d\u0435\u0435.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/operativnaya-analitika-v-mikroservisnoj-arhitekture-p%cc%b6o%cc%b6n%cc%b6ya%cc%b6t%cc%b6%cc%b6-%cc%b6i%cc%b6-%cc%b6p%cc%b6r%cc%b6o%cc%b6s%cc%b6t%cc%b6i%cc%b6t%cc%b6%cc%b6-pomoch-i-podskazat-postgres\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"pt_PT\" \/>\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\/pt\/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\udd47An\u00e1lise operacional em arquitetura de microsservi\u00e7os: entender e simplificar ajuda e orienta Postgres FDW | ProHoster","description":"A arquitetura de microsservi\u00e7os, como tudo neste mundo, tem seus pr\u00f3s e contras. Alguns processos se tornam mais simples, outros \u2014 mais complexos.","canonical_url":"https:\/\/prohoster.info\/pt\/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":"pt_PT","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\/pt\/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\/pt\/wp-json\/wp\/v2\/posts\/79467","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/comments?post=79467"}],"version-history":[{"count":2,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts\/79467\/revisions"}],"predecessor-version":[{"id":159871,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts\/79467\/revisions\/159871"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media\/79468"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media?parent=79467"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/categories?post=79467"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/tags?post=79467"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}