Produto Cartesiano - Matemática – Conjuntos. Produto Cartesiano – Matemática
Matemática – Conjuntos. Produto Cartesiano – Matemática

Como funciona na prática

O produto cartesiano é, basicamente, a operação que gera todas as combinações possíveis entre os elementos de dois ou mais conjuntos. Não tem segredo maior que isso. A definição matemática fala em pares ordenados, mas o que você realmente encontra no dia a dia é um resultado que cresce de forma exponencial com o tamanho dos conjuntos de entrada. Se você tem um conjunto A com 5 elementos e um conjunto B com 8 elementos, o produto cartesiano A × B vai gerar exatamente 40 pares ordenados. Se adicionar um terceiro conjunto C com 12 elementos, o resultado pula para 480 combinações. Isso é importante porque a maioria das pessoas subestima esse crescimento na hora de planejar queries ou scripts.

O que é produto cartesiano e onde ele aparece

No SQL, o produto cartesiano aparece quando você faz um CROSS JOIN entre duas tabelas, ou quando esquece a cláusula WHERE em um JOIN e o banco simplesmente cruza todas as linhas de uma tabela com todas as linhas da outra. No Python, você usa o método product() do módulo itertools. Em linguagens funcionais como Haskell ou Scala, a notação de compreensão de listas ou for-compreensões frequentemente resultam em produtos cartesianos sob o capô. O problema real começa quando você tenta aplicar isso sem medir o tamanho dos dados. Eu trabalhei em um projeto onde precisávamos cruzar uma tabela de produtos com uma tabela de variações de cor e tamanho para gerar um catálogo completo. A tabela de produtos tinha cerca de 3.200 itens e a de variações tinha aproximadamente 850 combinações. O produto cartesiano gerou 2.720.000 linhas. O script levou 47 minutos para rodar e consumiu 12 GB de memória RAM só pra montar o dataframe antes de qualquer filtragem.

👉 Clique no botão abaixo para saber mais sobre o assunto!

A solução foi segmentar o cruzamento. Em vez de processar tudo de uma vez, separei os produtos por categoria e processei cada grupo individualmente, salvando os resultados intermediários em disco. Isso reduziu o tempo para cerca de 6 minutos e o uso de memória para menos de 800 MB. O ganho não veio de otimizar o algoritmo em si, mas de evitar que o produto cartesiano completo fosse materializado na memória de uma vez só. Outra coisa que as pessoas geralmente não consideram é a ordem dos operandos. Matematicamente, A × B é diferente de B × A porque os pares ordenados têm posição significativa. No SQL isso se traduz em colunas que aparecem em ordens diferentes, o que pode quebrar códigos que dependem de posições fixas para mapear resultados. Já vi queries que passaram por review porque alguém inverteu a ordem das tabelas no FROM e o time que consumia a API esperava as colunas na sequência original.

Também vale mencionar que produto cartesiano não é sinônimo de junção útil. Muitas vezes ele é o resultado de um erro acidental, especialmente em bancos de dados relacionais onde a ausência de uma condição de correlação entre tabelas gera esse cruzamento completo. O explain plan de uma query com produto cartesiano acidental mostra um Nested Loop Join sem predicado de ligação, e o custo estima rapidamente porque o número de linhas atravessadas é o produto dos tamanhos das duas tabelas envolvidas. Se o seu cenário envolve conjuntos grandes e você precisa das combinações para testes ou geração de dados, considere usar geradores em vez de listas completas. Em Python, itertools.product retorna um iterador, então você processa cada combinação sob demanda sem guardar tudo na memória. A diferença entre carregar 500 mil tuplas de uma vez e consumi-las uma a uma é entre um script que termina em segundos e um que é morto pelo garbage collector após estourar a memória disponível.