<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Arquivo de Design Patterns - Data Universe</title>
	<atom:link href="https://datauniverse.com.br/category/design-patterns/feed/" rel="self" type="application/rss+xml" />
	<link>https://datauniverse.com.br/category/design-patterns/</link>
	<description>Conteúdos sobre as áreas de Data Science, Data Analytics, Estatística e Probabilidade, Inteligência Artificial e Machine Learning.</description>
	<lastBuildDate>Tue, 31 Mar 2026 23:23:30 +0000</lastBuildDate>
	<language>pt-BR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://datauniverse.com.br/wp-content/uploads/2026/01/cropped-data-universe-logo-icon-32x32.png</url>
	<title>Arquivo de Design Patterns - Data Universe</title>
	<link>https://datauniverse.com.br/category/design-patterns/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Arquitetura Medallion (Bronze, Silver, Gold) x Modelo SOR, SOT e SPEC</title>
		<link>https://datauniverse.com.br/arquitetura-medallion-bronze-silver-gold-x-modelo-sor-sot-e-spec/</link>
					<comments>https://datauniverse.com.br/arquitetura-medallion-bronze-silver-gold-x-modelo-sor-sot-e-spec/#respond</comments>
		
		<dc:creator><![CDATA[Alexandre Polselli]]></dc:creator>
		<pubDate>Tue, 31 Mar 2026 23:21:02 +0000</pubDate>
				<category><![CDATA[Design Patterns]]></category>
		<category><![CDATA[Curso Fundamentos da Engenharia de Dados]]></category>
		<guid isPermaLink="false">https://datauniverse.com.br/?p=3036</guid>

					<description><![CDATA[<p>Na engenharia de dados, extrair informações de diversas fontes e jogá-las em um repositório sem organização é a receita perfeita para criar um &#8220;Pântano de Dados&#8221; (Data Swamp). Para que os dados sejam úteis, eles precisam passar por estágios de refinamento. É exatamente para estruturar esse fluxo que existem frameworks arquiteturais como o Medallion (Bronze, [&#8230;]</p>
<p>O post <a href="https://datauniverse.com.br/arquitetura-medallion-bronze-silver-gold-x-modelo-sor-sot-e-spec/">Arquitetura Medallion (Bronze, Silver, Gold) x Modelo SOR, SOT e SPEC</a> apareceu primeiro em <a href="https://datauniverse.com.br">Data Universe</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Na engenharia de dados, extrair informações de diversas fontes e jogá-las em um repositório sem organização é a receita perfeita para criar um &#8220;Pântano de Dados&#8221; (Data Swamp). Para que os dados sejam úteis, eles precisam passar por estágios de refinamento.</p>



<p>É exatamente para estruturar esse fluxo que existem frameworks arquiteturais como o <strong>Medallion (Bronze, Silver, Gold)</strong> e o modelo <strong>SOR, SOT, SPEC</strong>. <mark style="background-color:#fcb900" class="has-inline-color">Na prática, ambos descrevem a mesma jornada de amadurecimento do dado, mas com origens e focos ligeiramente diferentes.</mark></p>



<h3 class="wp-block-heading">A Arquitetura Medallion (Bronze, Silver, Gold)</h3>



<p>O conceito foi introduzido pela equipe da Databricks (liderada por nomes como <strong>Ali Ghodsi</strong>, CEO e cofundador) por volta de <strong>2020</strong> junto com o conceito de <em><a href="https://datauniverse.com.br/data-lakehouse/">Data Lakehouse</a></em>, a arquitetura Medallion foca no <strong>estado de qualidade e refinamento</strong> dos arquivos e tabelas dentro de um pipeline de <a href="https://datauniverse.com.br/big-data/">Big Data</a>.</p>



<figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="960" height="540" src="https://datauniverse.com.br/wp-content/uploads/2026/03/image-16.png" alt="" class="wp-image-3038" srcset="https://datauniverse.com.br/wp-content/uploads/2026/03/image-16.png 960w, https://datauniverse.com.br/wp-content/uploads/2026/03/image-16-300x169.png 300w, https://datauniverse.com.br/wp-content/uploads/2026/03/image-16-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /><figcaption class="wp-element-caption">https://learn.microsoft.com/pt-br/azure/databricks/lakehouse/medallion</figcaption></figure>



<p>A analogia é simples: o dado entra bruto e vai sendo &#8220;lapidado&#8221; até virar ouro.</p>



<p><strong>Camada Bronze (Raw / Bruta):</strong> É a zona de aterrissagem. Os dados chegam aqui exatamente no mesmo formato dos sistemas de origem (APIs, ERPs, CRMs, <a href="https://datauniverse.com.br/logs-logging/">logs</a>), sem nenhuma alteração.</p>



<p><em>Objetivo:</em> Manter o histórico imutável. Se houver um erro no processamento futuro, você sempre pode voltar à camada Bronze e reprocessar o dado original.</p>



<p><strong>Camada Silver (Cleansed / Conformed):</strong> É onde a faxina acontece. Os dados da Bronze são lidos, filtrados, padronizados (ex: transformar todas as datas para o formato YYYY-MM-DD), desduplicados e têm seus tipos de dados corrigidos.</p>



<p><em>Objetivo:</em> Criar uma base de dados limpa, integrada e confiável que representa a operação da empresa, pronta para exploração por analistas e cientistas de dados.</p>



<p><strong>Camada Gold (Curated / Aggregated):</strong> É a camada de negócio. Aqui, os dados da Silver são agregados, somados e cruzados para responder a perguntas específicas (ex: &#8220;Total de vendas por região por mês&#8221;).</p>



<p><em>Objetivo:</em> Entregar dados altamente otimizados e prontos para consumo por ferramentas de BI (Tableau, Power BI, Metabase) ou modelos de Machine Learning.</p>



<h3 class="wp-block-heading">O Modelo SOR, SOT e SPEC</h3>



<p>Enquanto o Medallion nasceu no mundo do Big Data e processamento em nuvem, a nomenclatura <strong>SOR, SOT e SPEC</strong> tem raízes mais profundas na Governança de Dados clássica e em arquiteturas de Data Warehousing (como as de Ralph Kimball e Bill Inmon). O termo ganhou força com <strong>Bill Inmon</strong> (conhecido como o &#8220;Pai do Data Warehouse. <mark style="background-color:#fcb900" class="has-inline-color">O foco aqui é a <strong>confiabilidade e o propósito</strong> do dado.</mark></p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="270" src="https://datauniverse.com.br/wp-content/uploads/2026/03/image-17-1024x270.png" alt="sor, sot e spec" class="wp-image-3039" srcset="https://datauniverse.com.br/wp-content/uploads/2026/03/image-17-1024x270.png 1024w, https://datauniverse.com.br/wp-content/uploads/2026/03/image-17-300x79.png 300w, https://datauniverse.com.br/wp-content/uploads/2026/03/image-17-768x203.png 768w, https://datauniverse.com.br/wp-content/uploads/2026/03/image-17.png 1095w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="509" height="564" src="https://datauniverse.com.br/wp-content/uploads/2026/03/image-18.png" alt="sor, sot e spec" class="wp-image-3040" srcset="https://datauniverse.com.br/wp-content/uploads/2026/03/image-18.png 509w, https://datauniverse.com.br/wp-content/uploads/2026/03/image-18-271x300.png 271w" sizes="(max-width: 509px) 100vw, 509px" /></figure>



<p><strong>SOR (System of Record &#8211; Sistema de Registro):</strong> É a origem do dado. Em arquitetura de dados, representa a camada onde a informação é armazenada de forma bruta e fidedigna ao sistema transacional que a gerou.</p>



<p><mark style="background-color:#ff6900" class="has-inline-color has-palette-color-1-color"><em>Equivalência:</em> É a representação lógica da camada <strong>Bronze</strong>.</mark></p>



<p><strong>SOT (Source of Truth / Single Source of Truth &#8211; Fonte Única da Verdade):</strong> É o coração da governança. É a camada onde as discrepâncias entre diferentes sistemas foram resolvidas. Se o sistema de Vendas diz que o cliente é &#8220;João S.&#8221; e o sistema de Entregas diz &#8220;João Silva&#8221;, a SOT resolve esse conflito e consolida o dado oficial da empresa.</p>



<p><mark style="background-color:#abb8c3" class="has-inline-color"><em>Equivalência:</em> É a representação lógica da camada <strong>Silver</strong>.</mark></p>



<p><strong>SPEC (Specific / System of Engagement &#8211; Específico):</strong> São as visões de dados criadas para propósitos específicos de um departamento ou caso de uso. O RH não quer ver a base inteira da empresa; ele quer um conjunto de dados focado em métricas de contratação e turnover (um Data Mart).</p>



<p><mark style="background-color:#fcb900" class="has-inline-color"><em>Equivalência:</em> É a representação lógica da camada <strong>Gold</strong>.</mark></p>



<h3 class="wp-block-heading">Qual a diferença real entre eles?</h3>



<p><mark style="background-color:#fcb900" class="has-inline-color">A diferença não está na tecnologia ou no fluxo (ambos usam pipelines de extração, limpeza e agregação), mas sim na <strong>filosofia e no vocabulário adotado pela equipe</strong>.</mark></p>



<figure class="wp-block-image size-large zoooom"><img loading="lazy" decoding="async" width="1024" height="351" src="https://datauniverse.com.br/wp-content/uploads/2026/03/image-15-1024x351.png" alt="sor, sot e spec" class="wp-image-3037" srcset="https://datauniverse.com.br/wp-content/uploads/2026/03/image-15-1024x351.png 1024w, https://datauniverse.com.br/wp-content/uploads/2026/03/image-15-300x103.png 300w, https://datauniverse.com.br/wp-content/uploads/2026/03/image-15-768x263.png 768w, https://datauniverse.com.br/wp-content/uploads/2026/03/image-15-1536x527.png 1536w, https://datauniverse.com.br/wp-content/uploads/2026/03/image-15-2048x703.png 2048w, https://datauniverse.com.br/wp-content/uploads/2026/03/image-15-scaled.png 1920w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-table"><table><thead><tr><td><strong>Característica</strong></td><td><strong>Arquitetura Medallion (Databricks)</strong></td><td><strong>Arquitetura SOR / SOT / SPEC</strong></td></tr></thead><tbody><tr><td><strong>Origem do Conceito</strong></td><td>Engenharia de Dados Moderna (Data Lakehouse, Spark).</td><td>Governança de Dados e Data Warehousing tradicional.</td></tr><tr><td><strong>Foco Principal</strong></td><td>Estágio de processamento e qualidade do dado (Bruto $\rightarrow$ Limpo $\rightarrow$ Agregado).</td><td>Autoridade, governança e consumo do dado (Registro $\rightarrow$ Verdade $\rightarrow$ Aplicação).</td></tr><tr><td><strong>Camada 1 (Bruto)</strong></td><td><strong>Bronze:</strong> Pouso do dado bruto e retenção de histórico.</td><td><strong>SOR:</strong> O espelho exato do sistema de origem.</td></tr><tr><td><strong>Camada 2 (Limpo)</strong></td><td><strong>Silver:</strong> Dados padronizados, desduplicados e modelados.</td><td><strong>SOT:</strong> A &#8220;Fonte Única da Verdade&#8221; validada para toda a empresa.</td></tr><tr><td><strong>Camada 3 (Negócio)</strong></td><td><strong>Gold:</strong> Dados agregados e otimizados para dashboards de BI.</td><td><strong>SPEC:</strong> Visões departamentais específicas (Data Marts) e produtos de dados.</td></tr></tbody></table></figure>



<p>Na prática das empresas modernas, esses termos frequentemente se misturam. Um Arquiteto de Dados pode perfeitamente desenhar um pipeline dizendo: <em>&#8220;Vamos usar a camada <strong>Silver</strong> do nosso Data Lake como a nossa <strong>Source of Truth (SOT)</strong> corporativa&#8221;</em>.</p>



<p>Se você abrir o banco de dados de uma empresa madura, a tabela que o engenheiro chama de &#8220;Silver&#8221; é a exata mesma tabela que o time de governança chama de &#8220;SOT&#8221; (Source of Truth).</p>



<p>A diferença não está na tecnologia ou no fluxo dos dados. A diferença está <strong>na perspectiva de quem está olhando</strong> e <strong>no vocabulário usado para resolver problemas diferentes</strong>.</p>



<p>Pense nisso como duas &#8220;lentes&#8221; para olhar o mesmo funil de dados: a lente da Engenharia e a lente do Negócio/Governança.</p>



<h3 class="wp-block-heading">Lente 1: Medallion (A Visão da Engenharia)</h3>



<p>O Medallion (Bronze, Silver, Gold) foca no <strong>estado de processamento e qualidade do dado</strong>. É o vocabulário de quem &#8220;põe a mão na massa&#8221; (Engenheiros de Dados, Arquitetos Cloud).</p>



<ul class="wp-block-list">
<li><strong>A pergunta que ele responde:</strong> &#8220;O quanto de código, limpeza e transformação nós já rodamos nesse dado?&#8221;</li>



<li><strong>Na prática:</strong> Você usa esses termos em reuniões técnicas.
<ul class="wp-block-list">
<li><em>Exemplo:</em> &#8220;A pipeline deu erro porque o arquivo JSON que chegou na <strong>Bronze</strong> veio corrompido, então o script do Spark não conseguiu limpar e jogar para a <strong>Silver</strong>.&#8221;</li>
</ul>
</li>
</ul>



<h3 class="wp-block-heading">Lente 2: SOR, SOT, SPEC (A Visão do Negócio e Governança)</h3>



<p>O SOR/SOT/SPEC foca na <strong>confiabilidade, auditoria e autoridade do dado</strong>. É o vocabulário de quem consome o dado e toma decisões de negócio (Diretores, Analistas de Negócio, Auditores, Data Stewards).</p>



<ul class="wp-block-list">
<li><strong>A pergunta que ele responde:</strong> &#8220;Eu posso confiar nesse número para apresentar para o conselho diretivo? Quem é o dono dessa informação?&#8221;</li>



<li><strong>Na prática:</strong> Você usa esses termos em reuniões de alinhamento estratégico ou resolução de conflitos.
<ul class="wp-block-list">
<li><em>Exemplo:</em> &#8220;O dashboard de Vendas e o de Finanças estão mostrando faturamentos diferentes. Precisamos definir que a tabela X do Data Warehouse será a nossa <strong>SOT (Fonte Única da Verdade)</strong> para o faturamento global da empresa.&#8221;</li>
</ul>
</li>
</ul>



<h3 class="wp-block-heading">Quando usar um vocabulário no lugar do outro?</h3>



<p>Aqui está a regra de ouro para o seu dia a dia profissional: <strong>Você não escolhe um modelo em detrimento do outro, você os usa simultaneamente dependendo com quem está falando.</strong></p>



<p>Veja como os dois mundos se mapeiam perfeitamente na mesma infraestrutura:</p>



<figure class="wp-block-table"><table><thead><tr><td><strong>A Tabela Física no Banco</strong></td><td><strong>Como o Engenheiro chama (Medallion)</strong></td><td><strong>Como o Negócio chama (Governança)</strong></td><td><strong>O que acontece ali na prática?</strong></td></tr></thead><tbody><tr><td><strong>Pasta <code>raw_vendas</code></strong> no Data Lake</td><td><strong>Bronze</strong> (Porque o dado está cru, recém-chegado da API).</td><td><strong>SOR</strong> (System of Record &#8211; O espelho exato do sistema que originou a venda).</td><td>É o backup intocável. Se der problema, todo mundo volta aqui para auditar o que aconteceu originalmente.</td></tr><tr><td><strong>Tabela <code>clientes_limpos</code></strong> no BigQuery</td><td><strong>Silver</strong> (Porque o código já removeu duplicatas e arrumou os CPFs).</td><td><strong>SOT</strong> (Source of Truth &#8211; Porque o negócio decidiu que essa tabela é a verdade corporativa sobre quem é cliente).</td><td>É a base central da empresa. Todos os departamentos devem ler daqui para não haver divergência de números.</td></tr><tr><td><strong>Tabela <code>vendas_agregadas_rh</code></strong></td><td><strong>Gold</strong> (Porque cruzou vendas com a tabela de funcionários para calcular comissões).</td><td><strong>SPEC</strong> (System of Engagement/Specific &#8211; Porque foi feita <em>especificamente</em> para o RH calcular a folha de pagamento).</td><td>É o dado final, resumido e otimizado apenas para quem vai consumir aquele painel ou relatório.</td></tr></tbody></table></figure>



<h3 class="wp-block-heading">Resumo:</h3>



<ul class="wp-block-list">
<li>Você fala <strong>Bronze, Silver e Gold</strong> quando está discutindo com outro desenvolvedor sobre <em>como o código vai transformar o arquivo</em>.</li>



<li>Você fala <strong>SOR, SOT e SPEC</strong> quando o Diretor pergunta: <em>&#8220;De onde veio esse número e por que eu deveria confiar nele?&#8221;</em>.</li>
</ul>
<p>O post <a href="https://datauniverse.com.br/arquitetura-medallion-bronze-silver-gold-x-modelo-sor-sot-e-spec/">Arquitetura Medallion (Bronze, Silver, Gold) x Modelo SOR, SOT e SPEC</a> apareceu primeiro em <a href="https://datauniverse.com.br">Data Universe</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://datauniverse.com.br/arquitetura-medallion-bronze-silver-gold-x-modelo-sor-sot-e-spec/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Concorrência e Paralelismo</title>
		<link>https://datauniverse.com.br/concorrencia-e-paralelismo/</link>
					<comments>https://datauniverse.com.br/concorrencia-e-paralelismo/#respond</comments>
		
		<dc:creator><![CDATA[Alexandre Polselli]]></dc:creator>
		<pubDate>Tue, 27 Jan 2026 21:13:45 +0000</pubDate>
				<category><![CDATA[Design Patterns]]></category>
		<category><![CDATA[Curso Fundamentos da Engenharia de Dados]]></category>
		<guid isPermaLink="false">https://datauniverse.com.br/?p=2792</guid>

					<description><![CDATA[<p>Compreenda a distinção fundamental: Concorrência e Paralelismo sob diferentes óticas Sob a Ótica da Engenharia de Software Na programação de aplicações, a Concorrência resolve problemas de latência e responsividade. Ocorre quando duas ou mais tarefas podem iniciar, rodar e completar em períodos de tempo sobrepostos. O sistema operacional utiliza o Context Switching (troca de contexto) [&#8230;]</p>
<p>O post <a href="https://datauniverse.com.br/concorrencia-e-paralelismo/">Concorrência e Paralelismo</a> apareceu primeiro em <a href="https://datauniverse.com.br">Data Universe</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Compreenda a distinção fundamental: </p>



<ul class="wp-block-list">
<li><strong>Concorrência</strong> é sobre a <strong>composição</strong> de processos independentes (lidar com múltiplas coisas ao mesmo tempo). </li>



<li><strong>Paralelismo</strong> é sobre a <strong>execução</strong> simultânea (fazer múltiplas coisas ao mesmo tempo). Um sistema pode ser concorrente sem ser paralelo (ex: um único núcleo de CPU alternando tarefas), mas o paralelismo real exige hardware capaz de multitarefa simultânea.</li>
</ul>



<h2 class="wp-block-heading">Concorrência e Paralelismo sob diferentes óticas</h2>



<h3 class="wp-block-heading">Sob a Ótica da Engenharia de Software</h3>



<p>Na programação de aplicações, a <strong>Concorrência</strong> resolve problemas de latência e responsividade. Ocorre quando duas ou mais tarefas podem iniciar, rodar e completar em períodos de tempo sobrepostos. </p>



<p>O sistema operacional utiliza o <strong>Context Switching</strong> (troca de contexto) para alternar o uso da CPU entre tarefas, criando a ilusão de simultaneidade.</p>



<p>O <strong>Paralelismo</strong> ocorre quando tarefas são literalmente executadas no mesmo instante físico, exigindo arquiteturas <strong>Multi-Core</strong>.</p>



<h3 class="wp-block-heading">Sob a Ótica da Engenharia de Dados</h3>



<p>Na Engenharia de Dados, a escala muda de uma única máquina para clusters distribuídos.</p>



<ul class="wp-block-list">
<li><strong>Concorrência em Dados:</strong> <mark style="background-color:#fcb900" class="has-inline-color">Refere-se à capacidade de um orquestrador (como o Airflow) gerenciar centenas de DAGs (Directed Acyclic Graphs) ativos.</mark> O <em>scheduler</em> decide qual <em>task</em> deve ser enviada para a fila, lidando com dependências e prioridades, mesmo que não haja <em>slots</em> suficientes para rodar tudo instantaneamente.</li>



<li><strong>Paralelismo em Dados:</strong> <mark style="background-color:#fcb900" class="has-inline-color">Refere-se ao processamento distribuído (ex: Apache Spark ou Databricks). Um arquivo de 1TB é dividido em 1000 partições.</mark> 1000 núcleos de CPU (espalhados por vários nós) processam essas partições exatamente ao mesmo tempo. É a base do paradigma <strong>MPP (Massively Parallel Processing)</strong>.</li>
</ul>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="932" height="458" src="https://datauniverse.com.br/wp-content/uploads/2026/01/image-2.png" alt="" class="wp-image-2803" srcset="https://datauniverse.com.br/wp-content/uploads/2026/01/image-2.png 932w, https://datauniverse.com.br/wp-content/uploads/2026/01/image-2-300x147.png 300w, https://datauniverse.com.br/wp-content/uploads/2026/01/image-2-768x377.png 768w" sizes="(max-width: 932px) 100vw, 932px" /></figure>



<h2 class="wp-block-heading">Qual a sua importância?</h2>



<p>A aplicação correta destes conceitos não é apenas uma questão de velocidade, mas de robustez sistêmica e eficiência econômica.</p>



<h3 class="wp-block-heading">Tolerância a Falhas e Isolamento</h3>



<p>Sistemas concorrentes bem projetados isolam falhas. <mark style="background-color:#fcb900" class="has-inline-color">Se você processa 1 milhão de registros em um único loop sequencial e o registro 999.000 falha, todo o processo para.</mark></p>



<p>Ao utilizar concorrência, cada &#8220;worker&#8221; opera de forma independente. Se um falha, apenas aquela unidade de trabalho é perdida ou reprocessada (retry), sem derrubar todo o pipeline.</p>



<h3 class="wp-block-heading">Consistência de Dados</h3>



<p>Em ambientes concorrentes, múltiplos processos podem tentar ler ou escrever o mesmo dado (Race Condition). Mecanismos de controle de concorrência (como <strong>Locks</strong>, semáforos ou controle via <strong>MVCC &#8211; Multiversion Concurrency Control</strong> em bancos de dados) garantem que transações financeiras ou atualizações de estoque mantenham as propriedades <strong>ACID</strong>, impedindo corrupção de dados.</p>



<h3 class="wp-block-heading">Redução de Custos Operacionais</h3>



<ul class="wp-block-list">
<li><strong>Recursos Ociosos:</strong> Processos sequenciais frequentemente deixam CPU ociosa enquanto esperam I/O (leitura de disco/rede). A concorrência preenche esses vazios com outras tarefas, maximizando o uso do hardware alugado na nuvem.</li>



<li><strong>Tempo de Cluster:</strong> O paralelismo reduz o tempo total de execução (<em>wall-clock time</em>). Em nuvem, onde você paga por &#8220;segundo de cluster ligado&#8221;, reduzir um job de 10 horas para 1 hora (usando 10x mais máquinas) custa teoricamente o mesmo, mas entrega valor ao negócio muito mais rápido.</li>
</ul>



<h2 class="wp-block-heading">Exemplo Prático Real (Engenharia de Dados)</h2>



<p><strong>Cenário:</strong> Uma empresa de logística recebe telemetria de 50.000 caminhões a cada 30 segundos. O objetivo é ingerir, limpar e armazenar esses dados no Data Lake.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Abordagem Sem Concorrência/Paralelismo (O Erro)</th><th>Abordagem Ideal (A Solução)</th></tr></thead><tbody><tr><td>Um script Python simples lê a fila de mensagens (Kafka), processa um JSON por vez e salva no S3.<br><br><strong>Resultado:</strong> O script processa 50 mensagens/segundo. A entrada é de 1.600 mensagens/segundo.<br><br><strong>Consequência:</strong> Latência acumulada. Dados chegam com horas de atraso (<em>Backlog</em>). Se o script quebrar, o processamento para totalmente. Custo alto de oportunidade.</td><td>Implementação de um job Spark Streaming (Paralelismo) com leitura de múltiplos tópicos (Concorrência).<br><br><strong>Paralelismo de Dados:</strong> O Kafka é particionado em 50 partições. O Spark sobe 50 executores, cada um lendo uma partição simultaneamente.<br><br><strong>Concorrência de I/O:</strong> Enquanto os dados são escritos no S3 (operação lenta de rede), a CPU já está desserializando o próximo lote de JSONs.<br><br><strong>Resultado:</strong> Processamento de 10.000 mensagens/segundo.<br><br><strong>Consequência:</strong> Ingestão <em>Near Real-Time</em>. Se um nó do cluster cair, o Spark reage (concorrência de tarefas) e realoca a partição para outro nó.</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Principais Métodos de Implementação</h2>



<p>Analise a tabela abaixo para compreender as diferenças de implementação técnica:</p>



<table> <thead> <tr> <th>Método</th> <th>Tipo Principal</th> <th>Uso Ideal na Eng. de Dados</th> <th>Limitação Crítica</th> </tr> </thead> <tbody> <tr> <td><strong>Multithreading</strong></td> <td>Concorrência (I/O Bound)</td> <td>Chamadas de API, Leitura/Escrita de arquivos, requisições HTTP.</td> <td>GIL (Global Interpreter Lock) no Python impede uso real de múltiplos núcleos para CPU.</td> </tr> <tr> <td><strong>Multiprocessing</strong></td> <td>Paralelismo (CPU Bound)</td> <td>Transformações pesadas locais (Pandas), regex complexo em máquina única.</td> <td>Alto overhead de memória (cada processo tem seu próprio espaço de memória).</td> </tr> <tr> <td><strong>Processamento Distribuído</strong></td> <td>Paralelismo de Cluster</td> <td>Processamento de <a href="https://datauniverse.com.br/big-data/">Big Data</a> (Spark, Dask, Trino).</td> <td>Latência de rede (Network Shuffle) e complexidade de gestão de cluster.</td> </tr> <tr> <td><strong>Async I/O</strong></td> <td>Concorrência (Event Loop)</td> <td>Microsserviços de alta vazão, scrapers de dados massivos.</td> <td>Complexidade de código (&#8220;Callback hell&#8221;) e difícil depuração.</td> </tr> </tbody> </table>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="835" src="https://datauniverse.com.br/wp-content/uploads/2026/01/image-4-1024x835.png" alt="" class="wp-image-2808" srcset="https://datauniverse.com.br/wp-content/uploads/2026/01/image-4-1024x835.png 1024w, https://datauniverse.com.br/wp-content/uploads/2026/01/image-4-300x245.png 300w, https://datauniverse.com.br/wp-content/uploads/2026/01/image-4-768x627.png 768w, https://datauniverse.com.br/wp-content/uploads/2026/01/image-4.png 1043w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<h3 class="wp-block-heading">Exemplo de Código: Threading vs Multiprocessing (Python)</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>import time
import threading
import multiprocessing

# Simulação de tarefa I/O Bound (Ex: Request API)
def task_io():
    time.sleep(1)

# Simulação de tarefa CPU Bound (Ex: Cálculo Hash)
def task_cpu():
    sum(&#91;i**2 for i in range(10**6)&#93;)

# Implemente Threading para I/O (Concorrência)
# Útil para quando o gargalo é esperar resposta externa
t1 = threading.Thread(target=task_io)
t2 = threading.Thread(target=task_io)
t1.start(); t2.start() # Iniciam "juntas"

# Implemente Multiprocessing para CPU (Paralelismo Real)
# Útil para cálculos pesados que travam a CPU
p1 = multiprocessing.Process(target=task_cpu)
p2 = multiprocessing.Process(target=task_cpu)
p1.start(); p2.start() # Rodam em núcleos diferentes
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">import</span><span style="color: #F6F6F4"> time</span></span>
<span class="line"><span style="color: #F286C4">import</span><span style="color: #F6F6F4"> threading</span></span>
<span class="line"><span style="color: #F286C4">import</span><span style="color: #F6F6F4"> multiprocessing</span></span>
<span class="line"></span>
<span class="line"><span style="color: #7B7F8B"># Simulação de tarefa I/O Bound (Ex: Request API)</span></span>
<span class="line"><span style="color: #F286C4">def</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">task_io</span><span style="color: #F6F6F4">():</span></span>
<span class="line"><span style="color: #F6F6F4">    time.sleep(</span><span style="color: #BF9EEE">1</span><span style="color: #F6F6F4">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #7B7F8B"># Simulação de tarefa CPU Bound (Ex: Cálculo Hash)</span></span>
<span class="line"><span style="color: #F286C4">def</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">task_cpu</span><span style="color: #F6F6F4">():</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #97E1F1">sum</span><span style="color: #F6F6F4">(&#91;i</span><span style="color: #F286C4">**</span><span style="color: #BF9EEE">2</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">for</span><span style="color: #F6F6F4"> i </span><span style="color: #F286C4">in</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">range</span><span style="color: #F6F6F4">(</span><span style="color: #BF9EEE">10</span><span style="color: #F286C4">**</span><span style="color: #BF9EEE">6</span><span style="color: #F6F6F4">)&#93;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #7B7F8B"># Implemente Threading para I/O (Concorrência)</span></span>
<span class="line"><span style="color: #7B7F8B"># Útil para quando o gargalo é esperar resposta externa</span></span>
<span class="line"><span style="color: #F6F6F4">t1 </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> threading.Thread(</span><span style="color: #FFB86C; font-style: italic">target</span><span style="color: #F286C4">=</span><span style="color: #F6F6F4">task_io)</span></span>
<span class="line"><span style="color: #F6F6F4">t2 </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> threading.Thread(</span><span style="color: #FFB86C; font-style: italic">target</span><span style="color: #F286C4">=</span><span style="color: #F6F6F4">task_io)</span></span>
<span class="line"><span style="color: #F6F6F4">t1.start(); t2.start() </span><span style="color: #7B7F8B"># Iniciam &quot;juntas&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #7B7F8B"># Implemente Multiprocessing para CPU (Paralelismo Real)</span></span>
<span class="line"><span style="color: #7B7F8B"># Útil para cálculos pesados que travam a CPU</span></span>
<span class="line"><span style="color: #F6F6F4">p1 </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> multiprocessing.Process(</span><span style="color: #FFB86C; font-style: italic">target</span><span style="color: #F286C4">=</span><span style="color: #F6F6F4">task_cpu)</span></span>
<span class="line"><span style="color: #F6F6F4">p2 </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> multiprocessing.Process(</span><span style="color: #FFB86C; font-style: italic">target</span><span style="color: #F286C4">=</span><span style="color: #F6F6F4">task_cpu)</span></span>
<span class="line"><span style="color: #F6F6F4">p1.start(); p2.start() </span><span style="color: #7B7F8B"># Rodam em núcleos diferentes</span></span>
<span class="line"></span></code></pre></div>



<h2 class="wp-block-heading">Desafios e Considerações</h2>



<ol start="1" class="wp-block-list">
<li><strong>Race Conditions (Condições de Corrida):</strong> Ocorrem quando a saída depende da sequência ou tempo de outros eventos incontroláveis. Em ETLs, isso gera dados duplicados ou inconsistentes.</li>



<li><strong>Deadlocks:</strong> O Processo A espera o recurso do Processo B, e o Processo B espera o recurso do Processo A. O sistema trava indefinidamente.</li>



<li><strong>Complexidade de Debug:</strong> Erros em sistemas paralelos são frequentemente <strong>não-determinísticos</strong>. Um bug pode aparecer apenas 1 vez a cada 100 execuções (&#8220;Heisenbugs&#8221;), dificultando a reprodução.</li>
</ol>



<h2 class="wp-block-heading">Melhores Práticas</h2>



<p>Siga estas 5 diretrizes para mitigar riscos ao implementar concorrência e paralelismo:</p>



<ol start="1" class="wp-block-list">
<li><strong>Arquitetura &#8220;Shared Nothing&#8221; (Nada Compartilhado):</strong> Projete tarefas que não compartilhem estado (memória ou variáveis globais). Cada <em>worker</em> deve receber seus dados, processar e salvar o resultado sem precisar &#8220;conversar&#8221; com outros <em>workers</em>. Isso elimina <em>Locks</em> complexos.</li>



<li><strong>Idempotência é Obrigatória:</strong> Garanta que, se uma tarefa paralela falhar e for reexecutada (concorrência), o resultado final seja o mesmo. Use chaves primárias ou <em>upserts</em> ao invés de <em>append</em> cego.</li>



<li><strong>Prefira Imutabilidade:</strong> Dados imutáveis não sofrem de <em>Race Conditions</em> porque não são alterados, apenas lidos. Crie novas tabelas/arquivos ao invés de atualizar os existentes (<em>Write-Once-Read-Many</em>).</li>



<li><strong>Use Ferramentas de Alto Nível:</strong> Evite gerenciar <em>threads</em> e <em>locks</em> manualmente em Python se possível. Utilize frameworks que abstraem essa complexidade, como <strong>Apache Spark</strong> ou <strong>Dask</strong>, que gerenciam a distribuição e tolerância a falhas nativamente.</li>



<li><strong>Particionamento Inteligente:</strong> O paralelismo só funciona se os dados puderem ser divididos uniformemente (evite <em>Data Skew</em>). Garanta que suas chaves de partição distribuam o volume de dados de forma equilibrada entre os nós.</li>
</ol>
<p>O post <a href="https://datauniverse.com.br/concorrencia-e-paralelismo/">Concorrência e Paralelismo</a> apareceu primeiro em <a href="https://datauniverse.com.br">Data Universe</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://datauniverse.com.br/concorrencia-e-paralelismo/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Idempotência</title>
		<link>https://datauniverse.com.br/idempotencia/</link>
					<comments>https://datauniverse.com.br/idempotencia/#respond</comments>
		
		<dc:creator><![CDATA[Alexandre Polselli]]></dc:creator>
		<pubDate>Tue, 27 Jan 2026 17:58:15 +0000</pubDate>
				<category><![CDATA[Design Patterns]]></category>
		<category><![CDATA[Curso Fundamentos da Engenharia de Dados]]></category>
		<guid isPermaLink="false">https://datauniverse.com.br/?p=2782</guid>

					<description><![CDATA[<p>Aqui, a pergunta não é &#8220;se&#8221; algo vai falhar, mas &#8220;quando&#8221;. E quando falhar, o seu sistema precisa ser inteligente o suficiente para se curar sem corromper os dados. Imagine que você está em um elevador e aperta o botão do 5º andar. Se você apertar esse mesmo botão dez vezes seguidas, o elevador ainda [&#8230;]</p>
<p>O post <a href="https://datauniverse.com.br/idempotencia/">Idempotência</a> apareceu primeiro em <a href="https://datauniverse.com.br">Data Universe</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Aqui, a pergunta não é &#8220;se&#8221; algo vai falhar, mas &#8220;quando&#8221;. E quando falhar, o seu sistema precisa ser inteligente o suficiente para se curar sem corromper os dados.</p>



<p>Imagine que você está em um elevador e aperta o botão do 5º andar. Se você apertar esse mesmo botão dez vezes seguidas, o elevador ainda te levará para o 5º andar, certo? Ele não vai somar os cliques e te levar para o 50º andar.</p>



<p>Isso é <strong>idempotência</strong>. No mundo da Engenharia de Dados, esse conceito é um dos pilares para construir sistemas confiáveis e à prova de falhas.</p>



<h2 class="wp-block-heading">O que é Idempotência? (Definição e Óticas)</h2>



<p><strong>Em resumo</strong>: Idempotência é a propriedade de poder realizar a mesma ação várias vezes e obter o mesmo resultado que se tivesse realizado apenas uma vez.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="792" height="856" src="https://datauniverse.com.br/wp-content/uploads/2026/01/image-8.png" alt="" class="wp-image-2832" srcset="https://datauniverse.com.br/wp-content/uploads/2026/01/image-8.png 792w, https://datauniverse.com.br/wp-content/uploads/2026/01/image-8-278x300.png 278w, https://datauniverse.com.br/wp-content/uploads/2026/01/image-8-768x830.png 768w" sizes="(max-width: 792px) 100vw, 792px" /></figure>



<h3 class="wp-block-heading">A. Ótica da Engenharia de Software (APIs)</h3>



<p>Imagine um botão de &#8220;Chamar Elevador&#8221;. Você pode apertá-lo uma vez ou vinte vezes seguidas impacientemente. O sistema entende: &#8220;O elevador foi chamado&#8221;. Ele não manda 20 elevadores para o seu andar.</p>



<p>Em APIs REST:</p>



<ul class="wp-block-list">
<li><strong>POST</strong> geralmente não é idempotente (cria um novo recurso a cada chamada).</li>



<li><strong>PUT</strong> e <strong>DELETE</strong> devem ser idempotentes (se eu deletar o usuário ID 10 duas vezes, na segunda vez o resultado final é o mesmo: o usuário não existe).</li>
</ul>



<h3 class="wp-block-heading">B. Ótica da Engenharia de Dados</h3>



<p>Aqui é onde o jogo muda. Idempotência em pipelines de dados significa que você pode <strong>reprocessar um arquivo, uma mensagem ou um lote de dados inteiro</strong> sem gerar duplicidade no destino final.</p>



<p>Se o seu script Python falhar na metade e você rodá-lo de novo:</p>



<ul class="wp-block-list">
<li><strong>Pipeline Não-Idempotente:</strong> Você terá metade dos dados duplicados no banco.</li>



<li><strong>Pipeline Idempotente:</strong> O sistema detecta o que já foi processado, atualiza o que mudou ou simplesmente sobrescreve o destino de forma segura, garantindo integridade.</li>
</ul>



<h2 class="wp-block-heading">Qual a sua importância?</h2>



<p>Por que devemos exigir idempotência idealmente em todos os projetos de dados?</p>



<ol start="1" class="wp-block-list">
<li><strong>Tolerância a Falhas (Fault Tolerance):</strong> Redes caem. Servidores reiniciam. Em um sistema distribuído, a estratégia padrão de recuperação é o Retry (tentar novamente). Se o seu processo não for idempotente, você não pode usar <em>retries</em> automáticos sem corromper o banco.</li>



<li><strong>Consistência de Dados:</strong> Garante a semântica de <em>Exactly-Once</em> (Exatamente uma vez). O analista de BI ou o Cientista de Dados na ponta final confiará que o número de vendas é real, e não inflado por reprocessamentos.</li>



<li><strong>Redução de Custos Operacionais:</strong> Imagine o custo de horas de engenharia para escrever scripts de &#8220;limpeza&#8221; (Deduplication) toda vez que um job falhar. Com a idempotência, a recuperação é apenas &#8220;rodar o job de novo&#8221;.</li>
</ol>



<h2 class="wp-block-heading">Exemplo Prático Real (Engenharia de Dados)</h2>



<p><strong>Cenário: O E-commerce &#8220;TechVendas&#8221;</strong></p>



<p>Você é responsável por ingerir as vendas do dia anterior no Data Warehouse para o relatório financeiro.</p>



<ul class="wp-block-list">
<li><strong>Input:</strong> Arquivo <code>vendas_2023-10-27.csv</code> com 1 milhão de linhas.</li>



<li><strong>O Evento:</strong> O job começa a rodar às 03:00 AM. Ele insere 500.000 linhas no banco de dados. Às 03:15 AM, a conexão cai e o script quebra.</li>
</ul>



<figure class="wp-block-table is-style-regular"><table class="has-fixed-layout"><thead><tr><th><strong>Sem Idempotência (O Caos)</strong></th><th><strong>Com Idempotência (O Ideal)</strong></th></tr></thead><tbody><tr><td>O orquestrador (airflow, por exemplo) tenta rodar o job novamente.<br><br>O script lê o arquivo do zero.<br><br>Ele insere as 500.000 linhas (que já foram inseridas antes da falha).<br><br>Ele continua e insere as outras 500.000 linhas restantes.<br><br><strong>Resultado:</strong> O banco tem 1.5 milhões de registros. A receita do dia aparece 50% maior. O CEO toma decisões erradas baseadas em lucro inexistente.</td><td>O orquestrador roda o job novamente.<br><br>O script usa uma estratégia de <strong>Upsert</strong> ou <strong>Overwrite Partition</strong>.<br><br>Ao encontrar as 500.000 linhas que já existem (baseado no ID da venda), ele apenas confirma que estão iguais ou as atualiza.<br><br>Ele insere as novas 500.000 linhas.<br><br><strong>Resultado:</strong> O banco tem exatamente 1 milhão de registros. Dados consistentes. Você continua dormindo tranquilamente.</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Principais Métodos de Implementação</h2>



<p>Como você escreve isso no código? Aqui estão as três abordagens clássicas:</p>



<h3 class="wp-block-heading">1. DELETE-WRITE (Sobrescrita de Partição)</h3>



<p>É a abordagem mais simples e robusta para processamento em lote (Batch).</p>



<p><strong>Lógica:</strong> Antes de escrever, apague tudo que existe para aquele período/partição específica.</p>



<p><strong>Exemplo SQL:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>-- Passo 1: Limpa a "mesa" para o dia específico
DELETE FROM tabela_vendas WHERE data_venda = '2023-10-27';

-- Passo 2: Escreve os dados novos limpos
INSERT INTO tabela_vendas SELECT * FROM arquivo_staging;</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #7B7F8B">-- Passo 1: Limpa a &quot;mesa&quot; para o dia específico</span></span>
<span class="line"><span style="color: #F286C4">DELETE</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">FROM</span><span style="color: #F6F6F4"> tabela_vendas </span><span style="color: #F286C4">WHERE</span><span style="color: #F6F6F4"> data_venda </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">2023-10-27</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #7B7F8B">-- Passo 2: Escreve os dados novos limpos</span></span>
<span class="line"><span style="color: #F286C4">INSERT INTO</span><span style="color: #F6F6F4"> tabela_vendas </span><span style="color: #F286C4">SELECT</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">*</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">FROM</span><span style="color: #F6F6F4"> arquivo_staging;</span></span></code></pre></div>



<h3 class="wp-block-heading">2. UPSERT (Merge)</h3>



<p>Ideal quando você não pode apagar dados (ex: atualizações de status de pedidos). O banco verifica linha a linha.</p>



<p><strong>Lógica:</strong> Se a chave (ID) existe -&gt; Atualiza (Update). Se não existe -&gt; Insere (Insert).</p>



<p><strong>Exemplo (Conceitual Python/Pandas):</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly># Não faça append cego!
# Lógica de Merge pseudo-código
for row in dataframe:
    if database.exists(row.id):
        database.update(row)
    else:
        database.insert(row)</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #7B7F8B"># Não faça append cego!</span></span>
<span class="line"><span style="color: #7B7F8B"># Lógica de Merge pseudo-código</span></span>
<span class="line"><span style="color: #F286C4">for</span><span style="color: #F6F6F4"> row </span><span style="color: #F286C4">in</span><span style="color: #F6F6F4"> dataframe:</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">if</span><span style="color: #F6F6F4"> database.exists(row.id):</span></span>
<span class="line"><span style="color: #F6F6F4">        database.update(row)</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">else</span><span style="color: #F6F6F4">:</span></span>
<span class="line"><span style="color: #F6F6F4">        database.insert(row)</span></span></code></pre></div>



<h3 class="wp-block-heading">3. Tabela de Controle (Watermarking)</h3>



<p>Você mantém uma tabela auxiliar que registra quais arquivos já foram processados.</p>



<ul class="wp-block-list">
<li><strong>Lógica:</strong> O script verifica: &#8220;O arquivo X já foi processado com sucesso?&#8221;. Se sim, pula. Se não, processa e marca como concluído no final.</li>
</ul>



<h2 class="wp-block-heading">Desafios e Considerações</h2>



<p>Nem tudo são flores. Implementar idempotência tem um custo:</p>



<p><strong>Performance (Overhead):</strong></p>



<ul class="wp-block-list">
<li>Fazer um <code>INSERT</code> direto (append) é extremamente rápido.</li>



<li>Fazer um <code>UPSERT</code> exige que o banco leia o índice para ver se o ID existe antes de escrever. Isso é mais lento e consome mais CPU.</li>
</ul>



<p><strong>Complexidade de Design:</strong></p>



<p>Você precisa definir muito bem suas <strong>Chaves Primárias (Primary Keys)</strong>. Se seus dados não tiverem um ID único confiável, a idempotência fica quase impossível.</p>



<p><strong>Janelas de Tempo (Late Arriving Data):</strong></p>



<p>No método <em>Delete-Write</em>, se chegar um dado atrasado de 3 dias atrás, você precisa reprocessar a partição daquele dia antigo, não a de hoje.</p>



<h2 class="wp-block-heading">Melhores Práticas (Diretrizes de Ouro)</h2>



<ul class="wp-block-list">
<li><strong>Defina uma Chave Única (Natural Key):</strong> Nunca confie apenas em IDs gerados automaticamente pelo banco (auto-increment). Tente usar algo do negócio (ex: <code>NumeroPedido</code> ou uma combinação <code>Data + ID_Cliente + SKU</code>).</li>
</ul>



<ul class="wp-block-list">
<li><strong>Particionamento é Vida:</strong> Sempre que possível, trabalhe com partições (por data é o mais comum). É muito mais barato apagar e reescrever uma partição de um dia (<code>DELETE WHERE date = X</code>) do que fazer <em>Upsert</em> na tabela inteira.</li>
</ul>



<ul class="wp-block-list">
<li><strong>Imutabilidade na Origem:</strong> Nunca modifique o arquivo bruto (Raw Data). Se precisar reprocessar, a fonte original deve estar intocada.</li>
</ul>



<ul class="wp-block-list">
<li><strong>Use Transações (Atomocidade):</strong> Em bancos relacionais, envolva suas operações de limpeza e escrita em uma transação. Se a escrita falhar, o <code>DELETE</code> inicial é desfeito (rollback), evitando que você perca dados se o script quebrar no meio.</li>
</ul>



<ul class="wp-block-list">
<li><strong>Teste a Falha:</strong> Não teste apenas o &#8220;Caminho Feliz&#8221;. Force o erro no meio do script e rode de novo. Se duplicar dados no ambiente de desenvolvimento, seu design falhou.</li>
</ul>
<p>O post <a href="https://datauniverse.com.br/idempotencia/">Idempotência</a> apareceu primeiro em <a href="https://datauniverse.com.br">Data Universe</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://datauniverse.com.br/idempotencia/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
