☕ Um Café no Bellacosa Mainframe
Gostou do conteúdo? Ajude a manter o café quente, o COBOL compilando e o mainframe acordado. 😄
☕ Pague um café ao Bellacosa

Translate

Mostrar mensagens com a etiqueta modelagem de dados. Mostrar todas as mensagens
Mostrar mensagens com a etiqueta modelagem de dados. Mostrar todas as mensagens

domingo, 10 de setembro de 2023

Viagem ao Fundo dos Dados — O Dia em que o Programador COBOL Entrou no Db2 e Descobriu um IMS Morando no Porão

Bellacosa Mainframe e a modelagem de dados para o db2

☕ Um Café no Bellacosa Mainframe

Viagem ao Fundo dos Dados — O Dia em que o Programador COBOL Entrou no Db2 e Descobriu um IMS Morando no Porão

Ou: por que trocar segmentos por tabelas não elimina a hierarquia, como diferenciar QSAM, VSAM, IMS e banco relacional, e o que Edgar Codd diria ao encontrar uma chave de 47 bytes carregando toda a árvore genealógica do cliente


Prólogo — A entrada para o mundo subterrâneo

O professor Otto Lidenbrock encontrou um manuscrito misterioso escondido dentro de um livro antigo. O documento indicava uma passagem para o centro da Terra através da cratera de um vulcão islandês. Um programador COBOL iniciante, por sua vez, encontrou algo igualmente inquietante: uma tabela Db2 com uma chave composta por empresa, filial, departamento, cliente, contrato, produto, parcela e sequência.

Não havia runas. Havia um copybook de 1989.

Na primeira página, alguém escrevera:

01  CHAVE-MESTRA.
    05 CD-EMPRESA       PIC 9(03).
    05 CD-FILIAL        PIC 9(04).
    05 NR-CLIENTE       PIC 9(09).
    05 NR-CONTRATO      PIC 9(12).
    05 NR-PARCELA       PIC 9(03).

O sistema utilizava uma versão moderna do Db2, possuía SQL, índices, tablespaces, packages e planos. Mesmo assim, para chegar a uma parcela, o programa precisava conhecer empresa, filial, cliente e contrato. Qualquer consulta começava pela raiz e descia pelos mesmos túneis. As tabelas pareciam segmentos. Os cursores pareciam GN. Algumas rotinas faziam tantos SELECT encadeados que quase se podia ouvir um distante GNP ecoando nas cavernas.

Foi então que surgiu a pergunta que leva muitos veteranos do mainframe a desconfiar do chão sob seus pés:

Se estou usando Db2, por que ainda sinto que os dados são IMS/DL/I?

A resposta curta é: porque tecnologia relacional e pensamento relacional não são a mesma coisa. É possível colocar dados num SGBD relacional e continuar projetando, navegando e mantendo tudo como se fosse uma velha hierarquia. A placa na entrada diz Db2, mas a planta dos túneis continua sendo IMS.

Vamos descer.



1. Hierarquia não é pecado; prisão de caminho é outra história

A realidade está cheia de hierarquias legítimas:

  • uma empresa contém departamentos;

  • um pedido contém itens;

  • uma conta recebe lançamentos;

  • um funcionário pode responder a um gerente;

  • um produto pode ser formado por componentes;

  • um país possui estados, que possuem municípios.

Portanto, encontrar relações pai-filho dentro de um Db2 não prova que a modelagem esteja errada. O modelo relacional representa hierarquias perfeitamente bem. A questão decisiva é saber se a hierarquia descreve o negócio ou aprisiona o acesso ao dado.

No banco hierárquico, o caminho é parte essencial da estrutura. Imagine:

CLIENTE
  └── CONTA
       └── LANÇAMENTO

Para alcançar determinado lançamento, a navegação tradicional começa no cliente, localiza a conta e finalmente desce ao lançamento. O programador não faz apenas uma pergunta sobre os dados; ele informa ou conhece o caminho para encontrá-los.

No modelo relacional, o lançamento pode ser encontrado diretamente por sua identidade:

SELECT *
  FROM LANCAMENTO
 WHERE ID_LANCAMENTO = 987654;

Também pode ser encontrado pela conta:

SELECT *
  FROM LANCAMENTO
 WHERE ID_CONTA = 12345;

Ou relacionado ao cliente:

SELECT L.*
  FROM CLIENTE C
  JOIN CONTA A
    ON A.ID_CLIENTE = C.ID_CLIENTE
  JOIN LANCAMENTO L
    ON L.ID_CONTA = A.ID_CONTA
 WHERE C.ID_CLIENTE = 100;

O dado não deixa de ter parentes. Ele apenas deixa de possuir um único roteiro obrigatório de visitação.

Essa é uma das diferenças mais importantes entre os dois mundos: no modelo hierárquico, pensamos em percorrer caminhos; no relacional, pensamos em combinar conjuntos de fatos.



2. IMS — a caverna desenhada antes da expedição

O IMS organiza dados em segmentos. Existe um segmento raiz e, abaixo dele, segmentos dependentes. Um desenho simplificado poderia ser:

CLIENTE
├── ENDEREÇO
├── TELEFONE
└── CONTA
    └── LANÇAMENTO

Cada ocorrência de CONTA vive sob determinado CLIENTE; cada LANÇAMENTO vive sob determinada CONTA. A aplicação percorre essa estrutura usando chamadas DL/I como:

  • GU — Get Unique;

  • GN — Get Next;

  • GNP — Get Next Within Parent;

  • ISRT — Insert;

  • REPL — Replace;

  • DLET — Delete.

É uma lógica navegacional. Ela se parece com a expedição de Júlio Verne: entre pela cratera correta, atravesse a galeria indicada, contorne o lago subterrâneo e procure a passagem depois da rocha marcada. Se você quiser chegar ao mesmo ponto por outro lado, talvez precise de outro índice, outro caminho lógico ou uma nova solução estrutural.

Isso não torna o IMS primitivo. Muito pelo contrário. O IMS continua sendo uma tecnologia poderosa, madura e extremamente eficiente em cargas com caminhos previsíveis. Possui índices secundários, logical relationships e diversos recursos que tornam o modelo muito mais sofisticado do que uma árvore escolar desenhada no quadro.

Suas qualidades aparecem quando:

  • o relacionamento pai-filho é estável;

  • os caminhos de acesso são conhecidos;

  • o volume transacional é elevado;

  • a previsibilidade é valiosa;

  • a estrutura combina naturalmente com o negócio.

As dificuldades aparecem quando consultas novas exigem atravessar a árvore de maneiras não previstas, quando muitos-para-muitos se multiplicam ou quando alterar a estrutura obriga muitos programas a reaprender o mapa subterrâneo.

3. Db2 — a pergunta lógica e o caminho escolhido pelo otimizador

No modelo relacional, uma tabela representa uma relação: um conjunto de fatos do mesmo tipo. Cada linha deveria afirmar algo claro sobre o mundo.

Uma tabela CLIENTE pode declarar:

Existe um cliente identificado por este código, com este nome e esta data de nascimento.

Uma tabela CONTA pode declarar:

Existe uma conta identificada por este código e relacionada a determinado cliente.

O relacionamento não deveria morar apenas na memória do analista ou numa condição dentro do COBOL. Ele pode ser declarado ao SGBD:

ALTER TABLE CONTA
  ADD CONSTRAINT FK_CONTA_CLIENTE
  FOREIGN KEY (ID_CLIENTE)
  REFERENCES CLIENTE (ID_CLIENTE);

Quando a regra existe somente no programa, temos uma convenção. Quando é declarada como constraint, temos uma regra protegida pelo banco para todos os programas autorizados a alterar aqueles dados.

No Db2, escrevemos o que desejamos obter. O otimizador decide como alcançar o resultado, considerando estatísticas, índices, cardinalidades, custos e alternativas de acesso. Pode escolher a ordem dos joins e diferentes estratégias físicas sem exigir que a regra de negócio seja reescrita.

É como pedir:

Quero todos os fósseis encontrados por expedições islandesas entre duas datas.

Em vez de ordenar:

Entre pelo túnel A, caminhe 300 metros, vire à esquerda, abra a terceira caixa e leia registro por registro.

Essa separação entre intenção lógica e acesso físico é uma das grandes conquistas do modelo relacional.

4. Quando o Db2 usa gravata, mas pensa em DL/I

Existem sintomas clássicos de que o sistema migrou de tecnologia sem migrar de pensamento.

4.1 Chaves que contêm todo o caminho dos ancestrais

Imagine estas chaves:

CLIENTE
  CD_EMPRESA + CD_FILIAL + NR_CLIENTE

CONTA
  CD_EMPRESA + CD_FILIAL + NR_CLIENTE + NR_CONTA

LANÇAMENTO
  CD_EMPRESA + CD_FILIAL + NR_CLIENTE + NR_CONTA + DT_MOVIMENTO + SEQUENCIA

Uma chave composta não é automaticamente ruim. Em muitos casos, a composição representa a verdadeira identidade do negócio. O problema começa quando o filho transporta toda a ancestralidade apenas porque antigamente o caminho físico precisava estar embutido na chave.

Uma possibilidade mais independente seria:

CLIENTE
  ID_CLIENTE PK

CONTA
  ID_CONTA PK
  ID_CLIENTE FK

LANCAMENTO
  ID_LANCAMENTO PK
  ID_CONTA FK

Agora, cada entidade tem identidade própria. O relacionamento continua existindo, mas não se confunde com a identidade completa do registro.

Não existe mandamento dizendo “usarás sempre chave artificial”. O bom projetista pergunta: a chave é estável? É curta? Tem significado duradouro? Pode mudar por correção cadastral ou legislação? Expõe informação sensível? Realmente identifica a entidade ou simplesmente reproduz a trilha de acesso?

4.2 O programa que faz uma excursão linha a linha

Outro sinal é o programa que seleciona clientes e, para cada cliente, abre uma consulta de contas; para cada conta, consulta lançamentos; para cada lançamento, busca informações complementares.

Em espírito:

SELECT CLIENTE
  SELECT CONTA
    SELECT LANCAMENTO
      SELECT TIPO_LANCAMENTO

É uma navegação hierárquica reconstruída com SQL. Também pode produzir o conhecido problema de muitas consultas repetitivas.

Uma abordagem relacional tenta formular o conjunto desejado:

SELECT C.ID_CLIENTE,
       A.ID_CONTA,
       SUM(L.VALOR) AS TOTAL
  FROM CLIENTE C
  JOIN CONTA A
    ON A.ID_CLIENTE = C.ID_CLIENTE
  JOIN LANCAMENTO L
    ON L.ID_CONTA = A.ID_CONTA
 GROUP BY C.ID_CLIENTE,
          A.ID_CONTA;

Não significa transformar qualquer processamento COBOL em um SQL gigantesco e impossível de manter. Significa reconhecer quando o SGBD pode trabalhar eficientemente com conjuntos, evitando que o programa imite um explorador abrindo cada caixote individualmente.

4.3 Relações protegidas apenas pelo COBOL

Alguns programas verificam se o pai existe antes de inserir o filho:

EXEC SQL
   SELECT COUNT(*)
     INTO :WS-COUNT
     FROM CLIENTE
    WHERE ID_CLIENTE = :WS-ID-CLIENTE
END-EXEC

Depois, se WS-COUNT for maior que zero, inserem a conta. Além de duplicar a regra em diferentes programas, essa estratégia pode sofrer com concorrência: a realidade pode mudar entre a verificação e a inserção.

Uma foreign key expressa diretamente a regra. O COBOL continua tratando o retorno SQL e produzindo a mensagem apropriada, mas o Db2 assume a proteção central da integridade.

4.4 A ordem “natural” da tabela

Uma tabela relacional não possui ordem lógica garantida. Este comando:

SELECT * FROM CLIENTE;

não promete retornar clientes por código, nome, horário de inclusão nem posição física. Se a ordem importa, ela deve ser declarada:

SELECT *
  FROM CLIENTE
 ORDER BY NOME, ID_CLIENTE;

Programa que depende da ordem observada sem ORDER BY está tratando a tabela como arquivo sequencial. Pode funcionar por anos e mudar depois de uma reorganização, alteração de índice ou novo access path. O monstro não nasceu naquele dia; naquele dia alguém apenas acendeu a lanterna.

5. QSAM — a longa estrada em linha reta

QSAM é associado ao acesso sequencial a registros bloqueados e aparece diariamente em processamento batch. É natural encontrá-lo em entradas, saídas, relatórios, interfaces, cargas, descargas e arquivos de erros.

No COBOL:

READ ARQ-CLIENTES
   AT END
      SET FIM-ARQUIVO TO TRUE
END-READ

O layout pode estar num copybook:

01  REG-CLIENTE.
    05 REG-ID       PIC 9(09).
    05 REG-NOME     PIC X(40).
    05 REG-STATUS   PIC X(01).

Para o mecanismo de acesso, existem registros e bytes. O significado “as posições 10 a 49 representam o nome” está no layout conhecido pela aplicação.

QSAM é como uma ferrovia subterrânea: excelente quando se deseja seguir do primeiro ao último vagão. Para processar quarenta milhões de registros numa passada, uma leitura sequencial pode ser exatamente a solução correta.

Entretanto, QSAM não oferece por si só joins, foreign keys ou integridade referencial entre diferentes datasets. Se um arquivo de contas contém o código do cliente, cabe aos programas garantir que esse cliente exista no arquivo correspondente.

Eis uma curiosidade importante para o iniciante: dataset é um termo amplo no z/OS. QSAM não é “um tipo de banco”; é um método de acesso normalmente empregado com datasets sequenciais. Confundir dataset, organização e método de acesso é como chamar toda criatura subterrânea de dinossauro. Algumas nem sequer viveram no mesmo período.

6. VSAM — as galerias com placas e atalhos

VSAM é uma família de organizações e serviços de acesso. O mais famoso no universo COBOL é o KSDS, que permite acesso por chave e também processamento sequencial.

READ ARQ-CLIENTE
   KEY IS WS-ID-CLIENTE
   INVALID KEY
      CONTINUE
END-READ

As organizações mais conhecidas incluem:

  • KSDS — registros acessíveis por chave e em sequência de chave;

  • ESDS — registros mantidos conforme a ordem de entrada, com acesso por endereço relativo;

  • RRDS — registros associados a números relativos;

  • LDS — espaço linear, utilizado em cenários específicos e por componentes que gerenciam sua própria estrutura.

Um KSDS possui entradas indexadas e pode encontrar rapidamente um registro. Ainda assim, o fato de dois clusters terem campos com o mesmo código não cria automaticamente um relacionamento protegido entre eles.

Se o arquivo CONTA contém ID-CLIENTE, um programa pode excluir o cliente e deixar contas órfãs, a menos que as aplicações e os processos impeçam isso. O VSAM não interpreta espontaneamente aquela igualdade como uma foreign key.

VSAM também não é “inferior” ao Db2. Há problemas para os quais sua simplicidade, previsibilidade e acesso direto são excelentes. A pergunta madura não é “qual tecnologia é mais moderna?”, mas “qual semântica, integridade, concorrência e padrão de acesso este problema exige?”.

7. O mapa comparativo da expedição

TecnologiaVisão predominanteRelacionamentosAcesso típicoQuem conhece grande parte da semântica?
QSAMsequência de registrosmantidos pela aplicaçãoleitura/gravação sequencialcopybook e programa
VSAM KSDSregistros indexados por chavemantidos principalmente pela aplicaçãochave ou sequênciadefinição do cluster, copybook e programa
IMSsegmentos numa hierarquiapai-filho estruturado pelo banconavegação DL/IDBD, PSB/PCB e aplicação
Db2conjuntos de fatos relacionadosPK, FK, constraints e valoresSQL declarativocatálogo, modelo e aplicação

O ponto não é dizer que apenas o Db2 conhece regras. Todos esses ambientes podem formar sistemas sólidos. A diferença está em onde a estrutura e a integridade são declaradas e quanto o programa precisa conhecer sobre o percurso físico ou lógico.

8. O que caracteriza uma boa modelagem relacional

Uma boa modelagem começa quando conseguimos terminar esta frase sem hesitar:

Cada linha desta tabela representa...

“Um cliente” é claro. “Uma conta” também. “A participação de um cliente numa conta durante certo período” pode justificar uma tabela associativa. Já “cliente, contrato, endereço atual, última cobrança e alguns campos reservados” revela vários conceitos presos no mesmo fóssil.

8.1 Identidade clara

Cada linha deve ser distinguível. Uma tabela pode usar uma chave técnica e, ao mesmo tempo, proteger a chave natural:

CREATE TABLE CLIENTE (
    ID_CLIENTE BIGINT       NOT NULL,
    NOME       VARCHAR(100) NOT NULL,
    CPF        CHAR(11),
    CONSTRAINT PK_CLIENTE
       PRIMARY KEY (ID_CLIENTE),
    CONSTRAINT UK_CLIENTE_CPF
       UNIQUE (CPF)
);

ID_CLIENTE fornece identidade técnica estável; CPF expressa uma possível regra de unicidade do negócio. O modelo real ainda precisa decidir como tratar estrangeiros, dados provisórios, correções e valores ausentes.

8.2 Relacionamentos declarados

Uma conta pode exigir um cliente existente:

CREATE TABLE CONTA (
    ID_CONTA     BIGINT NOT NULL,
    ID_CLIENTE   BIGINT NOT NULL,
    DATA_ABERTURA DATE  NOT NULL,
    SITUACAO     CHAR(1) NOT NULL,
    CONSTRAINT PK_CONTA
       PRIMARY KEY (ID_CONTA),
    CONSTRAINT FK_CONTA_CLIENTE
       FOREIGN KEY (ID_CLIENTE)
       REFERENCES CLIENTE (ID_CLIENTE),
    CONSTRAINT CK_CONTA_SITUACAO
       CHECK (SITUACAO IN ('A', 'B', 'E'))
);

O DDL passa a documentar e proteger identidade, obrigatoriedade, relacionamento e domínio.

8.3 Um fato em seu devido lugar

Se o limite de crédito pertence à conta, não deveria estar em CLIENTE apenas porque hoje cada cliente possui uma única conta. Se o preço depende do produto e da data de vigência, talvez não pertença simplesmente a PRODUTO.

A pergunta de ouro é:

Este atributo depende de quê?

Se depende da chave, da chave inteira e de nada além da chave, provavelmente está no lugar correto. Eis, em linguagem prática, a alma da normalização.

8.4 Muitos-para-muitos sem colunas numeradas

Um cliente pode participar de várias contas e uma conta pode ter vários titulares. Criar ID_CLIENTE_1, ID_CLIENTE_2 e ID_CLIENTE_3 estabelece um limite artificial e espalha lógica condicional.

O modelo apropriado pode usar:

CLIENTE
  ID_CLIENTE

CONTA
  ID_CONTA

CONTA_TITULAR
  ID_CONTA
  ID_CLIENTE
  TIPO_TITULARIDADE
  DATA_INICIO
  DATA_FIM

CONTA_TITULAR não é apenas uma ponte técnica. Ela representa um fato do negócio: determinada pessoa participa de determinada conta, com certo papel e durante certo intervalo.

8.5 Repetições viram linhas, não colunas numeradas

Uma tabela com TELEFONE_1, TELEFONE_2 e TELEFONE_3 carrega uma pergunta inevitável: o que acontecerá com o quarto telefone?

Uma tabela CLIENTE_TELEFONE permite zero, um ou muitos números, cada um com tipo, preferência, validade e outras regras necessárias.

8.6 NULL não é um saco de mistérios

NULL não deveria significar simultaneamente “não informado”, “não existe”, “não se aplica”, “será calculado”, “ocorreu erro” e “veio em branco no arquivo de 1997”. Esses estados podem exigir tratamentos diferentes.

O modelo precisa definir o significado da ausência. Caso contrário, cada programa inventará sua própria interpretação e o banco ganhará pequenas cavernas particulares.

8.7 O tempo precisa ser modelado

Pergunte sempre:

  • a data é de ocorrência, processamento ou vigência?

  • o dado atual substitui o anterior ou deve existir histórico?

  • períodos podem se sobrepor?

  • DATA_FIM IS NULL significa registro vigente?

  • alterações retroativas são permitidas?

  • precisamos saber quem alterou e quando?

Muitos modelos parecem ótimos até alguém perguntar: “Como essa conta estava no fechamento do mês passado?”. Nesse instante, descobre-se que atualizar uma linha apagou a história.

9. Normalização sem transformar o Db2 num labirinto

Normalizar significa reduzir redundâncias e anomalias, não dividir o universo em centenas de tabelas minúsculas por devoção religiosa.

Na primeira forma normal, evitamos guardar listas escondidas numa coluna:

TELEFONES = "11999999999;11888888888;11777777777"

Esse campo dificulta validação, pesquisa, indexação e alteração individual.

Na segunda forma normal, quando existe chave composta, cada atributo não-chave deve depender da chave inteira. Se ITEM_PEDIDO tem chave ID_PEDIDO + ID_PRODUTO, o nome do cliente não depende dessa combinação; a descrição geral do produto tampouco.

Na terceira forma normal, evitamos dependências indiretas. Se CLIENTE contém ID_CIDADE, NOME_CIDADE e UF, mas nome e UF dependem de ID_CIDADE, talvez esses atributos pertençam a CIDADE.

Entretanto, snapshots, trilhas históricas, integrações e estruturas analíticas podem duplicar dados intencionalmente. A distinção importante é esta:

  • redundância acidental cria várias verdades concorrentes;

  • redundância projetada identifica a fonte oficial, o momento da cópia e o mecanismo de reconciliação.

Desnormalizar por desempenho antes de medir é como abrir uma passagem com dinamite porque talvez exista um atalho atrás da parede. Pode existir. Também pode haver um oceano subterrâneo esperando para entrar.

10. Passo a passo para construir um bom modelo

Passo 1 — Escreva as regras em português

Antes do primeiro CREATE TABLE, registre frases como:

  • um cliente pode participar de várias contas;

  • uma conta pode ter vários titulares;

  • um lançamento pertence a exatamente uma conta;

  • uma conta pode existir sem lançamento;

  • a titularidade possui início, fim e tipo;

  • um lançamento cancelado não desaparece: ganha estado e referência de estorno.

Essas frases revelam entidades, cardinalidades, opcionalidade e tempo.

Passo 2 — Separe entidades, eventos e classificações

Entidades são coisas reconhecíveis, como cliente, conta e produto. Eventos registram algo ocorrido, como pagamento, transferência ou lançamento. Classificações descrevem categorias e estados.

Misturar tudo em TB_CADASTRO_GERAL pode parecer econômico no início, mas logo cria colunas sem sentido para metade das linhas e códigos mágicos decidindo qual formato cada registro possui.

Passo 3 — Defina as cardinalidades

Para cada relacionamento, pergunte:

  • a ocorrência relacionada é obrigatória?

  • pode existir uma ou várias?

  • o relacionamento muda com o tempo?

  • há exceções reais?

Não escolha 1:N porque o arquivo antigo parecia possuir um cabeçalho e vários detalhes. Escolha porque essa é a regra do negócio.

Passo 4 — Escolha chaves com consciência

Examine estabilidade, tamanho, privacidade e significado. Uma chave natural ótima hoje pode mudar amanhã. Uma chave artificial facilita identidade, mas não elimina a necessidade de proteger unicidades do negócio.

Passo 5 — Declare constraints

Use PRIMARY KEY, FOREIGN KEY, UNIQUE, NOT NULL e CHECK quando representam regras verdadeiras. Criar tudo como nullable para “facilitar a carga” apenas transfere a dificuldade para milhares de consultas futuras.

Passo 6 — Teste o ciclo de vida, não apenas o cadastro

Simule:

  • criação;

  • correção;

  • cancelamento;

  • reativação;

  • troca de titular;

  • evento retroativo;

  • auditoria;

  • anonimização;

  • consulta histórica;

  • exclusão permitida e exclusão proibida.

Um modelo que funciona somente no primeiro INSERT ainda não atravessou a primeira galeria.

Passo 7 — Valide com consultas reais

Escreva as perguntas principais que o negócio fará. Se para responder a algo básico for necessário interpretar cinco códigos obscuros e reconstruir manualmente uma sequência implícita, talvez o modelo não represente o negócio com clareza.

Passo 8 — Planeje o físico depois do lógico

Somente então avalie índices, particionamento, clustering, compressão, tablespaces, estatísticas, padrões batch, concorrência, recuperação e retenção.

Índice não corrige semântica. Ele encontra depressa aquilo que talvez tenha sido armazenado errado.

11. A fronteira que nunca parece clara nos projetos reais

Na prática, as fronteiras ficam nebulosas porque sistemas empresariais acumulam décadas de decisões:

  • tabelas nasceram de layouts VSAM;

  • segmentos IMS foram convertidos quase mecanicamente;

  • interfaces batch exigiram registros autocontidos;

  • projetos evitaram foreign keys por medo de desempenho ou dificuldade de carga;

  • regras ficaram duplicadas em COBOL, Java, stored procedures e ETLs;

  • aquisições juntaram conceitos diferentes sob nomes iguais;

  • cada equipe modelou apenas a parte que conhecia;

  • urgências transformaram exceções temporárias em arquitetura permanente.

Por isso, sua sensação não é nostalgia técnica nem impressão equivocada. Muitas instalações Db2 contêm estratos arqueológicos. Na superfície há SQL moderno; alguns metros abaixo aparecem tabelas tratadas como KSDS; mais fundo, chaves carregam caminhos de segmentos; no último nível, um programa ainda acredita que branco, zero e ausência são a mesma criatura.

Uma boa modernização começa reconhecendo esses estratos. Não é necessário demolir tudo. Pode-se:

  1. documentar o significado real das tabelas;

  2. identificar fontes oficiais e redundâncias;

  3. localizar relações sem constraints;

  4. medir órfãos e inconsistências antes de criar FKs;

  5. encapsular legados por views e serviços;

  6. corrigir novas extensões segundo um modelo melhor;

  7. migrar por domínios, com reconciliação e rollback;

  8. manter desempenho e operação envolvidos desde o desenho.

Colocar uma foreign key numa base histórica sem verificar dados existentes pode revelar milhões de órfãos. A constraint não criou o problema; ela apenas encontrou os esqueletos.

12. Checklist do explorador relacional

Ao examinar uma tabela, pergunte:

  1. Cada linha representa exatamente o quê?

  2. Qual regra torna uma linha única?

  3. A chave representa identidade ou caminho de navegação?

  4. Quais foreign keys deveriam existir?

  5. Há registros órfãos?

  6. Existem listas dentro de colunas?

  7. Há colunas numeradas como ENDERECO_1, ENDERECO_2 e ENDERECO_3?

  8. O mesmo fato aparece em várias tabelas?

  9. Qual delas é a fonte oficial?

  10. O programa depende da ordem sem ORDER BY?

  11. Existem sequências de SELECT que imitam pai-filho-neto?

  12. As regras vivem no banco ou espalhadas por programas?

  13. É possível reconstruir o passado?

  14. Branco, zero e NULL possuem significados definidos?

  15. Alterar um relacionamento exige alterar a identidade do registro?

Se muitas respostas causarem desconforto, provavelmente existe um IMS, um VSAM ou um QSAM conceitual vivendo por baixo das tabelas. Isso não condena o sistema, mas indica onde começar a investigação.

Epílogo — O centro da Terra não era o fim da viagem

Depois de atravessar galerias de QSAM, atalhos de VSAM, árvores de IMS e salões relacionais do Db2, nosso programador COBOL finalmente entendeu que nenhuma dessas tecnologias é vilã.

QSAM pode ser perfeito para uma grande varredura batch. VSAM pode oferecer o acesso direto e previsível de que determinada aplicação necessita. IMS pode processar hierarquias estáveis com eficiência extraordinária. Db2 pode representar conjuntos relacionados, proteger integridade e permitir múltiplos caminhos lógicos de consulta.

O erro não está em conservar tecnologia antiga quando ela resolve bem o problema. O erro está em usar uma tecnologia sem compreender seu modelo — ou esperar que a simples migração física transforme automaticamente a maneira de pensar.

Uma boa modelagem relacional apresenta:

  • conceitos com fronteiras compreensíveis;

  • linhas com identidade clara;

  • fatos colocados onde realmente pertencem;

  • relacionamentos declarados e protegidos;

  • cardinalidades fiéis ao negócio;

  • ausência e tempo com significado definido;

  • redundância consciente, quando necessária;

  • independência entre a pergunta lógica e o caminho físico;

  • capacidade de evoluir sem obrigar cada programa a memorizar a árvore inteira.

No final de Viagem ao Centro da Terra, os exploradores não retornam pelo mesmo caminho: são expelidos por outro vulcão, muito longe do ponto de entrada. É um belo easter egg relacional. Num mundo governado por caminhos hierárquicos, a saída deveria repetir a rota conhecida. Num mundo relacional, diferentes caminhos podem alcançar o mesmo conjunto de fatos.

E se Edgar F. Codd estivesse sentado numa poltrona do Bellacosa Mainframe, tomando café enquanto examinava aquela chave de 47 bytes, talvez dissesse com toda a elegância britânica:

Meu caro, isto não é uma relação. É uma árvore genealógica tentando passar pela catraca do Db2.

O programador olharia novamente para o copybook, respiraria fundo e abriria o catálogo.

A expedição verdadeira estaria apenas começando.

sexta-feira, 7 de julho de 2023

Kojak Entra no CPD — O Caso do Db2 que Tinha um IMS Escondido no Porão

 


☕ Um Café no Bellacosa Mainframe

Kojak Entra no CPD — O Caso do Db2 que Tinha um IMS Escondido no Porão

Ou: como uma chave composta de 47 bytes entregou a árvore genealógica do sistema, por que uma tabela pode agir como arquivo e o que QSAM, VSAM, DL/I e Edgar Codd estavam fazendo na mesma cena do crime



Prólogo — Quem ama você, banco de dados?

Era uma tarde comum no CPD, o que significa que nada estava realmente comum.

O processamento batch havia terminado com RC=00, os operadores respiravam aliviados e um programador COBOL iniciante recebera uma manutenção considerada pequena: incluir uma nova forma de consultar lançamentos de conta. O pedido parecia inocente. Bastava localizar os lançamentos por documento, sem informar empresa, filial, cliente e contrato.

Ele abriu a tabela no Db2 e encontrou a primeira pista: uma chave composta tão longa que parecia a ficha criminal de metade de Nova York.

CD-EMPRESA
CD-FILIAL
NR-CLIENTE
NR-CONTRATO
TP-PRODUTO
NR-PARCELA
NR-SEQUENCIA

Para alcançar o lançamento, todos os programas percorriam a mesma rota. Primeiro encontravam o cliente. Depois a conta. Depois o contrato. Finalmente chegavam ao movimento. Havia SQL por toda parte, mas o cheiro era de DL/I.

Foi quando a porta do CPD se abriu. Entrou o detetive Kojak, sobretudo impecável, olhar desconfiado e pirulito no lugar onde outros investigadores carregariam um cachimbo.

Ele observou o diagrama de tabelas e fez a pergunta que ninguém queria ouvir:

“Se isto é relacional, por que todo mundo precisa entrar pela mesma porta?”

Silêncio.

O Db2 era moderno. O COBOL compilava. O catálogo estava disponível. Mas alguma coisa antiga vivia no porão. Não era exatamente um defeito de software. Era uma maneira de pensar.

O caso estava aberto.



1. A primeira testemunha: hierarquia não é crime

Kojak começou eliminando uma suspeita comum: a hierarquia.

Hierarquias existem naturalmente no mundo real:

  • uma empresa possui departamentos;

  • um departamento possui funcionários;

  • um pedido possui itens;

  • uma conta recebe lançamentos;

  • um país possui estados e municípios;

  • um produto pode conter componentes;

  • um gerente pode supervisionar outros funcionários.

Portanto, encontrar uma estrutura pai-filho dentro de um banco relacional não significa encontrar o culpado. O modelo relacional representa hierarquias sem dificuldade. Uma tabela pode referenciar a si mesma, como ocorre numa estrutura de funcionários e gerentes:

CREATE TABLE FUNCIONARIO (
    ID_FUNCIONARIO BIGINT NOT NULL,
    ID_GERENTE     BIGINT,
    NOME           VARCHAR(100) NOT NULL,
    PRIMARY KEY (ID_FUNCIONARIO),
    FOREIGN KEY (ID_GERENTE)
       REFERENCES FUNCIONARIO (ID_FUNCIONARIO)
);

O problema não é existir pai e filho. O problema é o filho somente poder ser encontrado depois que o programa percorre toda a linhagem familiar.

Num modelo hierárquico, a navegação faz parte essencial da estrutura. Imagine:

CLIENTE
  └── CONTA
       └── LANÇAMENTO

Para localizar determinado lançamento, tradicionalmente se encontra o cliente, dentro dele a conta e, dentro dela, o lançamento. É como um detetive que só pode chegar ao apartamento 32 entrando primeiro na delegacia, passando pelo arquivo central e pedindo autorização ao síndico.

No modelo relacional, o lançamento pode possuir identidade própria:

SELECT *
  FROM LANCAMENTO
 WHERE ID_LANCAMENTO = 987654;

Também pode ser encontrado pela conta:

SELECT *
  FROM LANCAMENTO
 WHERE ID_CONTA = 12345;

Ou associado ao cliente:

SELECT L.*
  FROM CLIENTE C
  JOIN CONTA A
    ON A.ID_CLIENTE = C.ID_CLIENTE
  JOIN LANCAMENTO L
    ON L.ID_CONTA = A.ID_CONTA
 WHERE C.ID_CLIENTE = 100;

A família continua existindo. O que desaparece é a obrigação de visitar o avô antes de perguntar pelo neto.

Kojak anotou no bloco:

Hierarquia: liberada por falta de provas. Prisão de caminho: permanece sob investigação.



2. IMS presta depoimento — a cidade construída com ruas predefinidas

O IMS não tentou esconder sua natureza. Ele trabalha com segmentos organizados hierarquicamente. Existe uma raiz e, abaixo dela, segmentos dependentes.

CLIENTE
├── ENDEREÇO
├── TELEFONE
└── CONTA
    └── LANÇAMENTO

Cada ocorrência de CONTA pertence a determinado CLIENTE. Cada LANÇAMENTO está subordinado a uma CONTA. Para navegar, a aplicação utiliza chamadas DL/I, entre elas:

  • GU — Get Unique;

  • GN — Get Next;

  • GNP — Get Next Within Parent;

  • ISRT — Insert;

  • REPL — Replace;

  • DLET — Delete.

Há uma diferença importante entre perguntar o que se deseja e informar como navegar. No IMS, o programa conhece a estrutura e percorre seus caminhos. O DBD descreve a organização do banco. PSBs e PCBs ajudam a definir as visões e os acessos permitidos às aplicações.

Isso não faz do IMS um criminoso antiquado. Seria uma conclusão preguiçosa. IMS é uma tecnologia madura, sofisticada e extremamente eficiente para grandes volumes transacionais e caminhos previsíveis. Índices secundários e logical relationships ampliam as possibilidades de acesso. Seu desempenho, estabilidade e integração com o ambiente transacional ajudaram a sustentar sistemas críticos durante décadas.

O detetive experiente não confunde idade com culpa.

O IMS funciona muito bem quando:

  • as relações pai-filho são naturais e estáveis;

  • os caminhos de navegação são conhecidos;

  • o volume transacional exige comportamento previsível;

  • a hierarquia representa fielmente o domínio;

  • as aplicações foram desenhadas para esse modelo.

As dificuldades aparecem quando surgem muitas relações muitos-para-muitos, quando consultas inesperadas precisam atravessar a árvore em novas direções ou quando uma mudança estrutural afeta muitos programas.

O IMS declarou:

“Eu nunca prometi ser relacional. Se encontraram minha árvore escondida dentro do Db2, interroguem quem fez a migração.”

Kojak concordou. O depoimento era consistente.



3. Db2 entra na sala — tabela não é apenas arquivo com gravata

No modelo relacional, a unidade lógica é a relação, normalmente representada como tabela. Cada tabela deveria expressar um tipo claro de fato.

Por exemplo:

CLIENTE
ID_CLIENTE | NOME | DATA_NASCIMENTO

Cada linha afirma:

Existe um cliente identificado por este código, com este nome e esta data de nascimento.

Outra tabela:

CONTA
ID_CONTA | ID_CLIENTE | DATA_ABERTURA | SITUACAO

Cada linha afirma:

Existe uma conta identificada por este código, relacionada a determinado cliente.

A relação não deveria depender apenas de um programa COBOL saber que CONTA.ID_CLIENTE combina com CLIENTE.ID_CLIENTE. Ela pode e, quando apropriado, deve ser declarada:

ALTER TABLE CONTA
  ADD CONSTRAINT FK_CONTA_CLIENTE
  FOREIGN KEY (ID_CLIENTE)
  REFERENCES CLIENTE (ID_CLIENTE);

Quando a regra existe apenas no programa, temos uma convenção. Quando está declarada como constraint, temos uma regra central protegida pelo SGBD.

Outra característica fundamental: o SQL é declarativo. Em geral, o programador informa o resultado desejado; o otimizador analisa estatísticas, índices, cardinalidades, custos e alternativas para escolher um caminho físico.

SELECT C.NOME,
       A.ID_CONTA,
       SUM(L.VALOR) AS TOTAL
  FROM CLIENTE C
  JOIN CONTA A
    ON A.ID_CLIENTE = C.ID_CLIENTE
  JOIN LANCAMENTO L
    ON L.ID_CONTA = A.ID_CONTA
 WHERE L.DATA_MOVIMENTO >= :WS-DATA-INICIAL
 GROUP BY C.NOME, A.ID_CONTA;

O programa formula a pergunta. O Db2 decide se utilizará determinado índice, qual tabela acessará primeiro e qual estratégia de join será mais adequada.

Essa separação entre visão lógica e implementação física é uma das grandes ideias do modelo relacional. O programa não deveria precisar memorizar cada corredor do depósito.


4. A impressão digital: a chave de 47 bytes

O primeiro indício concreto apareceu nas chaves.

CLIENTE
  CD_EMPRESA + CD_FILIAL + NR_CLIENTE

CONTA
  CD_EMPRESA + CD_FILIAL + NR_CLIENTE + NR_CONTA

LANCAMENTO
  CD_EMPRESA + CD_FILIAL + NR_CLIENTE + NR_CONTA
  + DATA_MOVIMENTO + SEQUENCIA

Chave composta não é ilegal. Às vezes, a identidade verdadeira de um fato é composta. O item de um pedido pode ser identificado pelo pedido e pelo número do item. Uma ocorrência de tabela associativa pode usar as chaves das duas entidades relacionadas.

A pista suspeita é outra: cada descendente carregar todos os códigos de seus ancestrais apenas para reproduzir o caminho antigo.

Uma alternativa seria:

CLIENTE
  ID_CLIENTE PK

CONTA
  ID_CONTA PK
  ID_CLIENTE FK

LANCAMENTO
  ID_LANCAMENTO PK
  ID_CONTA FK

Cada entidade possui identidade própria e relacionamentos explícitos. Alterar um vínculo não exige necessariamente redefinir a identidade inteira do registro.

Mas Kojak não aceitava soluções automáticas. Substituir todas as chaves naturais por números artificiais também pode esconder regras. A decisão correta exige perguntas:

  • A chave natural é realmente estável?

  • Pode mudar por correção, fusão empresarial ou legislação?

  • É grande demais para se propagar por todas as tabelas?

  • Expõe CPF, conta ou outra informação sensível?

  • Possui significado duradouro?

  • A chave técnica substituta será acompanhada de uma UNIQUE para proteger a regra do negócio?

Uma prática frequente é utilizar uma chave substituta como primary key e proteger a chave natural com unique constraint.

CREATE TABLE CLIENTE (
    ID_CLIENTE BIGINT       NOT NULL,
    CPF        CHAR(11),
    NOME       VARCHAR(100) NOT NULL,
    CONSTRAINT PK_CLIENTE
       PRIMARY KEY (ID_CLIENTE),
    CONSTRAINT UK_CLIENTE_CPF
       UNIQUE (CPF)
);

O número técnico fornece estabilidade. A constraint sobre CPF preserva a regra definida pelo negócio — considerando, naturalmente, estrangeiros, dados incompletos e demais exceções reais.


5. O crime do SELECT em série

Kojak encontrou outro padrão no fonte:

  1. selecionar um cliente;

  2. para esse cliente, selecionar suas contas;

  3. para cada conta, selecionar lançamentos;

  4. para cada lançamento, consultar sua descrição;

  5. repetir milhares de vezes.

Em espírito:

SELECT CLIENTE
  SELECT CONTA
    SELECT LANCAMENTO
      SELECT TIPO_LANCAMENTO

Era DL/I encenando uma peça de SQL.

Esse processamento linha a linha pode gerar enorme quantidade de chamadas e o conhecido problema de consultas repetitivas. O pensamento relacional procura operar sobre conjuntos:

SELECT C.ID_CLIENTE,
       A.ID_CONTA,
       T.DESCRICAO,
       SUM(L.VALOR) AS TOTAL
  FROM CLIENTE C
  JOIN CONTA A
    ON A.ID_CLIENTE = C.ID_CLIENTE
  JOIN LANCAMENTO L
    ON L.ID_CONTA = A.ID_CONTA
  JOIN TIPO_LANCAMENTO T
    ON T.ID_TIPO = L.ID_TIPO
 GROUP BY C.ID_CLIENTE,
          A.ID_CONTA,
          T.DESCRICAO;

Isso não significa escrever um SQL gigantesco, impossível de compreender e tratar. Significa identificar quando o banco pode resolver uma operação de conjunto melhor do que o COBOL percorrendo cada galho individualmente.

O desempenho deve ser medido. Um join bem modelado, com estatísticas e índices adequados, pode ser excelente. Um SQL mal escrito também pode ser desastroso. A teoria relacional não dispensa análise do access path, EXPLAIN, cardinalidade, distribuição e custo.

Como diria Kojak, gostar de SQL não fornece álibi para um SELECT * sem critério numa tabela de bilhões de linhas.


6. O cúmplice invisível: integridade mantida apenas pelo COBOL

Em vários sistemas, o programa verifica manualmente se o cliente existe antes de inserir a conta:

EXEC SQL
   SELECT COUNT(*)
     INTO :WS-COUNT
     FROM CLIENTE
    WHERE ID_CLIENTE = :WS-ID-CLIENTE
END-EXEC

IF WS-COUNT > 0
   EXEC SQL
      INSERT INTO CONTA (...)
      VALUES (...)
   END-EXEC
END-IF

O código parece cuidadoso, mas a regra pode estar duplicada em dezenas de programas. Além disso, existe uma janela de concorrência entre verificar e inserir.

A foreign key permite ao banco proteger a relação:

FOREIGN KEY (ID_CLIENTE)
REFERENCES CLIENTE (ID_CLIENTE)

O COBOL continua responsável por tratar SQLCODE, produzir mensagens adequadas e controlar a unidade de trabalho. O COMMIT continua sendo parte da história. A diferença é que a integridade não depende de todos os programas se lembrarem da mesma regra para sempre.

Naturalmente, há ambientes que evitam constraints por razões históricas, cargas em grande volume, replicação, desenho distribuído ou receio de custo. Algumas razões podem ser legítimas; outras apenas repetem crenças não medidas desde 1994.

A pergunta saudável é:

Se o banco não protege esta relação, quem protege, como protege e como provamos que funciona em todos os caminhos de atualização?

Se ninguém consegue responder, temos um suspeito sem vigilância.


7. QSAM — a testemunha que só anda para a frente

QSAM aparece diariamente no processamento batch do z/OS. É usado com datasets sequenciais para entradas, saídas, relatórios, arquivos de erro, cargas e intercâmbios.

READ ARQ-CLIENTES
   AT END
      SET FIM-ARQUIVO TO TRUE
END-READ

O significado dos bytes costuma estar num copybook:

01  REG-CLIENTE.
    05 REG-ID       PIC 9(09).
    05 REG-NOME     PIC X(40).
    05 REG-STATUS   PIC X(01).

QSAM é excelente para uma grande varredura sequencial. Se o objetivo é ler quarenta milhões de registros do começo ao fim, aplicar uma transformação e produzir uma saída, a simplicidade sequencial pode ser uma virtude.

Porém, QSAM não fornece por si só join, foreign key ou integridade referencial entre datasets. O sistema operacional não deduz que os bytes de determinada posição representam uma relação com outro arquivo. Essa semântica vive no copybook, nos programas e nos procedimentos.

Uma curiosidade importante: dataset é um conceito amplo no z/OS. QSAM é um método de acesso, não um banco de dados. Dizer “dataset versus QSAM” seria misturar o recipiente com uma das formas de acessá-lo.

Kojak interrogou o arquivo sequencial. Ele respondeu:

“Eu só leio do começo ao fim. Não fui eu quem prometeu relacionamento.”

Álibi aceito.


8. VSAM — a testemunha com índice e acesso direto

VSAM oferece diferentes organizações. Entre as mais conhecidas:

  • KSDS — registros organizados por chave, com acesso direto e sequencial;

  • ESDS — registros preservados em ordem de entrada, acessíveis também por endereço relativo;

  • RRDS — registros associados a números relativos;

  • LDS — espaço linear utilizado por componentes e casos específicos.

No COBOL, um KSDS pode ser acessado pela chave:

READ ARQ-CLIENTE
   KEY IS WS-ID-CLIENTE
   INVALID KEY
      CONTINUE
END-READ

O KSDS encontra registros rapidamente e pode suportar aplicações muito eficientes. Contudo, dois clusters com campos semelhantes não ganham automaticamente integridade referencial.

Se CONTA contém ID-CLIENTE, é a aplicação que normalmente impede uma conta órfã. Excluir o registro do cliente não dispara por natureza uma verificação relacional em todos os outros arquivos.

VSAM não é um Db2 incompleto. É outra ferramenta, com outro modelo operacional. Pode ser exatamente o que determinada solução necessita. O erro está em copiar um KSDS para uma tabela e acreditar que a presença de SQL realizou toda a modelagem.

Uma tabela usada somente por chave, sem constraints, com ordem física presumida e todas as regras no COBOL pode ser, conceitualmente, um KSDS mais caro usando crachá de banco relacional.


9. A comparação no mural da delegacia

TecnologiaEstrutura predominanteAcesso típicoRelacionamentosOnde vive a semântica
QSAMsequência de registrosleitura e gravação sequencialmantidos pela aplicaçãocopybook e programas
VSAM KSDSregistros indexados por chavechave e sequência de chavemantidos principalmente pela aplicaçãocluster, copybook e programas
IMSsegmentos hierárquicosnavegação DL/Ipai-filho estruturadoDBD, PSB/PCB e aplicação
Db2conjuntos de fatos relacionadosSQL declarativoPK, FK, valores e constraintscatálogo, modelo e aplicação

Nenhuma linha desta tabela declara um vencedor absoluto. O bom arquiteto escolhe conforme:

  • natureza dos dados;

  • padrão de acesso;

  • volume;

  • concorrência;

  • integridade necessária;

  • recuperação;

  • capacidade de mudança;

  • necessidade de consultas novas;

  • conhecimento e operação disponíveis.

Tecnologia não é concurso de beleza. É adequação ao caso.


10. Boa modelagem: a vítima precisa ser identificada

Kojak colocou uma tabela sob a luz e perguntou:

“Cada linha representa exatamente o quê?”

Essa é uma das melhores perguntas de modelagem.

Respostas claras:

  • um cliente;

  • uma conta;

  • um lançamento;

  • a participação de um aluno numa turma;

  • a titularidade de um cliente numa conta durante determinado período.

Resposta suspeita:

“É cliente, contrato, endereço atual, última cobrança e alguns campos reservados que dependem do tipo do registro.”

Provavelmente há vários conceitos misturados.

Uma boa tabela tem identidade clara, atributos coerentes e regras compreensíveis. Os nomes ajudam, mas não bastam. É preciso conhecer o significado, a granularidade e o ciclo de vida do fato.

O teste da dependência

Pergunte sobre cada atributo:

Este valor depende de quê?

Se o limite de crédito pertence à conta, não deve morar em CLIENTE apenas porque hoje existe uma conta por cliente. Se a taxa depende do produto e da vigência, talvez exija uma estrutura histórica própria.

Esse raciocínio conduz à normalização.


11. Normalização — separando suspeitos que estavam na mesma cela

Normalizar não significa fragmentar o banco até que uma consulta precise de 83 joins. Significa reduzir redundâncias e evitar anomalias.

Primeira forma normal

Evite listas escondidas em uma coluna:

TELEFONES = "11999999999;11888888888;11777777777"

Essa estrutura dificulta pesquisa, validação, indexação e alteração individual.

Também desconfie de:

TELEFONE_1
TELEFONE_2
TELEFONE_3

O quarto telefone já está a caminho da delegacia.

Uma tabela CLIENTE_TELEFONE permite representar zero, um ou muitos números, com tipo, preferência e validade.

Segunda forma normal

Se uma tabela possui chave composta, os atributos não-chave devem depender da chave inteira.

Em ITEM_PEDIDO, identificado por ID_PEDIDO + NR_ITEM, o nome do cliente depende do pedido, não do item completo. A descrição permanente do produto depende do produto, não da combinação pedido-item.

Terceira forma normal

Os atributos não-chave não deveriam depender de outros atributos não-chave.

Se CLIENTE contém ID_CIDADE, NOME_CIDADE e UF, e os dois últimos dependem de ID_CIDADE, talvez pertençam a uma tabela CIDADE.

Desnormalização consciente

Há casos legítimos de repetição: snapshots, relatórios históricos, data warehouses, integrações e otimizações comprovadas.

A diferença é simples:

  • redundância acidental cria várias versões da verdade;

  • redundância deliberada possui fonte oficial, momento de cópia e mecanismo de reconciliação.

Desnormalizar antes de medir é apresentar uma confissão antes mesmo de conhecer o crime.


12. Muitos-para-muitos: quando havia mais de dois suspeitos

Um cliente pode participar de várias contas. Uma conta pode ter vários titulares.

Um modelo frágil cria:

ID_CLIENTE_1
ID_CLIENTE_2
ID_CLIENTE_3

Além do limite arbitrário, cada consulta precisa tratar colunas diferentes.

O modelo relacional representa o relacionamento por meio de uma tabela associativa:

CLIENTE
  ID_CLIENTE

CONTA
  ID_CONTA

CONTA_TITULAR
  ID_CONTA
  ID_CLIENTE
  TIPO_TITULARIDADE
  DATA_INICIO
  DATA_FIM

CONTA_TITULAR não é uma gambiarra técnica. Ela representa um fato real:

Este cliente participa desta conta, neste papel e durante este período.

Se o relacionamento possui atributos próprios, ele merece ser tratado como conceito do negócio.


13. NULL, branco e zero: três suspeitos com rostos diferentes

Nos sistemas antigos, é comum encontrar campos nos quais branco, zero, noves e datas impossíveis representam estados especiais.

No banco relacional, NULL representa ausência de valor, mas a ausência precisa ter significado controlado. Ela não deveria significar ao mesmo tempo:

  • não informado;

  • não existe;

  • não se aplica;

  • ainda será calculado;

  • ocorreu erro;

  • veio vazio no arquivo legado.

Esses estados podem exigir uma coluna de situação ou motivo.

Também é perigoso criar defaults apenas para evitar NULL. Uma data 1900-01-01 pode parecer conveniente, mas obriga todas as consultas a conhecer o código secreto. O default deve representar um valor verdadeiro, não uma cortina para esconder desconhecimento.


14. O álibi temporal: como o dado estava ontem?

Muitos modelos funcionam bem até alguém perguntar:

“Qual era a situação da conta no fechamento do mês passado?”

Se cada atualização substitui a linha anterior, a história desaparece.

Para cada data, pergunte:

  • é data de ocorrência?

  • é data de processamento?

  • é início ou fim de vigência?

  • períodos podem se sobrepor?

  • alterações retroativas são permitidas?

  • quem alterou o dado e quando?

  • precisamos reconstruir o estado de uma data passada?

Tempo de negócio e tempo de sistema são conceitos diferentes. Um pagamento pode ocorrer numa sexta-feira, ser recebido no sábado e processado na segunda. Misturar essas datas produz investigações contábeis dignas de uma temporada inteira.


15. Passo a passo da investigação de um modelo

Passo 1 — Escreva as regras em português

Antes do CREATE TABLE, registre frases:

  • um cliente pode participar de várias contas;

  • uma conta pode possuir vários titulares;

  • uma conta pode existir sem lançamentos;

  • cada lançamento pertence a exatamente uma conta;

  • o cancelamento não apaga o lançamento original;

  • a titularidade possui início, fim e tipo.

Essas frases revelam entidades, cardinalidades, opcionalidade e tempo.

Passo 2 — Identifique entidades, eventos e classificações

  • entidades: cliente, conta, produto;

  • eventos: pagamento, transferência, lançamento;

  • classificações: tipo de conta, moeda, situação.

Evite uma tabela genérica que represente tudo por meio de um código de tipo e centenas de colunas opcionais.

Passo 3 — Defina cardinalidades

Pergunte se o relacionamento é obrigatório, opcional, único, múltiplo e temporal. Não deduza a cardinalidade apenas do layout antigo.

Passo 4 — Escolha as chaves

Analise estabilidade, tamanho, significado, privacidade e possibilidade de mudança. Diferencie identidade técnica de unicidade do negócio.

Passo 5 — Declare constraints

Use PRIMARY KEY, FOREIGN KEY, UNIQUE, NOT NULL e CHECK quando correspondem a regras verdadeiras.

Passo 6 — Teste o ciclo de vida

Simule cadastro, correção, cancelamento, reativação, transferência, evento retroativo, auditoria, anonimização e consulta histórica.

Passo 7 — Escreva consultas reais

Valide se o modelo responde às perguntas essenciais do negócio sem depender de códigos secretos e sequências implícitas.

Passo 8 — Projete o físico

Depois do modelo lógico, trate índices, particionamento, clustering, compressão, tablespaces, estatísticas, concorrência, recuperação, retenção e padrões batch.

Um índice encontra rapidamente o dado. Não consegue decidir se o dado deveria estar ali.


16. Cuidado ao prender o culpado: constraints numa base histórica

Ao modernizar um sistema, alguém pode decidir criar todas as foreign keys numa sexta-feira à tarde. Péssimo horário para heroísmo.

Antes de ativar constraints, investigue:

  1. quantos registros órfãos existem;

  2. quais programas atualizam cada tabela;

  3. quais cargas dependem de ordem especial;

  4. como funcionam deleções e cancelamentos;

  5. quais dados chegam atrasados;

  6. como será feita a correção;

  7. qual é o plano de rollback;

  8. qual impacto existe em disponibilidade e desempenho.

Se a foreign key encontrar milhões de órfãos, ela não criou o crime. Apenas acendeu a luz da sala de evidências.

Uma modernização segura pode usar views, serviços, reconciliações, constraints inicialmente informativas quando disponíveis e adequadas, correção gradual dos dados e migração por domínios.


17. Checklist de Kojak para descobrir um IMS usando SQL

Pegue uma tabela e responda:

  1. Cada linha representa exatamente o quê?

  2. Qual regra torna a linha única?

  3. A chave representa identidade ou o caminho até a raiz?

  4. Quais foreign keys existem e quais deveriam existir?

  5. Há registros órfãos?

  6. Existem listas dentro de colunas?

  7. Existem campos numerados como TELEFONE_1, TELEFONE_2 e TELEFONE_3?

  8. O mesmo fato aparece em várias tabelas?

  9. Qual tabela é a fonte oficial?

  10. Algum programa depende de ordem sem ORDER BY?

  11. Existem SELECTs aninhados que imitam pai-filho-neto?

  12. As regras estão no banco ou espalhadas por COBOL, Java, ETL e planilhas?

  13. É possível reconstruir o passado?

  14. Branco, zero, noves e NULL têm significados documentados?

  15. Alterar um relacionamento muda a identidade do registro?

  16. Uma nova consulta exige começar sempre pela mesma tabela raiz?

  17. O desenho nasceu do negócio ou foi copiado de um arquivo?

Quanto mais respostas desconfortáveis, maior a chance de existir um modelo navegacional escondido sob a camada SQL.


Epílogo — Caso encerrado, pirulito devolvido

Kojak reuniu todos no CPD.

QSAM não era culpado. Fazia muito bem seu trabalho sequencial e nunca prometera relacionamentos.

VSAM também possuía um álibi. Sabia localizar registros por chave, mas não alegava conhecer automaticamente as relações de negócio entre clusters.

IMS admitia sua hierarquia desde o primeiro interrogatório. Seus caminhos eram parte do projeto e podiam oferecer enorme desempenho quando combinavam com o problema.

Db2, por sua vez, oferecia tabelas, constraints, SQL declarativo, otimização e operações de conjunto. Mas nenhuma versão moderna do produto poderia impedir uma equipe de reproduzir dentro dele a mentalidade de arquivos e segmentos.

O culpado não era uma tecnologia. Era a migração sem remodelagem, acompanhada pela crença de que mudar READ para SELECT transformaria automaticamente registros em relações.

Uma boa modelagem relacional apresenta:

  • conceitos com fronteiras claras;

  • linhas com identidade inequívoca;

  • atributos dependentes do fato correto;

  • relacionamentos declarados;

  • cardinalidades fiéis ao negócio;

  • regras protegidas perto dos dados;

  • tempo e ausência com significado;

  • redundância consciente, quando necessária;

  • liberdade para consultar por diferentes perspectivas;

  • separação entre a pergunta lógica e o caminho físico.

O programador COBOL olhou novamente para a chave de 47 bytes. Pela primeira vez, não viu apenas campos concatenados. Viu uma árvore genealógica, uma rota de navegação e décadas de decisões arquitetônicas preservadas como impressões digitais.

Kojak colocou o pirulito na boca, caminhou em direção à saída e deixou sua última observação:

“Uma tabela pode morar no Db2 e ainda pensar como arquivo. Quem ama você, banco de dados? Porque seus programas claramente amam o caminho mais longo.”

Naquela noite, ninguém reescreveu o sistema inteiro. Em vez disso, a equipe documentou as regras, mediu os órfãos, identificou as fontes oficiais e começou a melhorar o próximo domínio.

Era menos cinematográfico do que uma prisão.

Mas, em arquitetura de dados, evitar o próximo crime costuma valer mais do que posar ao lado do culpado.



quarta-feira, 4 de maio de 2022

Engenharia de Dados para um Programador COBOL Padawan

 

Bellacosa Mainframe e a engenharia de dados

☕ Um Café no Bellacosa Mainframe

Engenharia de Dados para um Programador COBOL Padawan

Você Não Está Mudando de Profissão. Está Descobrindo que Sempre Trabalhou com Dados.

"Toda geração acredita que inventou a Engenharia de Dados. Quem passou décadas desenvolvendo em COBOL sabe que mover, transformar, validar e proteger dados sempre foi o coração do Mainframe."


Se existe uma palavra que domina o mercado de tecnologia atualmente, ela é Dados.

Data Engineer.

Data Lake.

Data Warehouse.

Data Mesh.

Data Fabric.

Big Data.

Analytics.

Machine Learning.

Inteligência Artificial.

Para quem acompanha as vagas do LinkedIn, parece que surgiu uma profissão completamente nova.

Mas será que surgiu mesmo?

Se você é um Programador COBOL Padawan, talvez esteja olhando para esse universo pensando:

"Isso não é para mim."

Ou talvez pior.

"Vou precisar esquecer tudo o que aprendi nos últimos anos."

Nada poderia estar mais distante da realidade.

Na verdade, existe uma notícia excelente.

Boa parte da Engenharia de Dados nasceu exatamente nos ambientes onde o COBOL reina há mais de sessenta anos.

Hoje vamos tomar um café e descobrir por que um programador COBOL possui muito mais vantagens para aprender Engenharia de Dados do que imagina.


O maior equívoco sobre Engenharia de Dados

Quando alguém fala "Data Engineer", muitas pessoas imaginam imediatamente alguém escrevendo Python.

Outros imaginam Spark.

Outros imaginam nuvem.

Outros imaginam Inteligência Artificial.

Tudo isso faz parte da profissão.

Mas nada disso explica sua essência.

A verdadeira Engenharia de Dados pode ser resumida em uma única pergunta:

Como garantir que a informação certa chegue ao lugar certo, no momento certo, com qualidade e segurança?

Perceba.

Não estamos falando de linguagem.

Não estamos falando de banco de dados.

Não estamos falando de cloud.

Estamos falando de engenharia.

E engenharia sempre existiu.


O COBOL sempre foi uma linguagem de dados

Vamos imaginar um programa extremamente simples.

READ CLIENTE

IF STATUS = "A"

   COMPUTE LIMITE = SALARIO * 3

   WRITE CLIENTE-APROVADO

END-IF

O que esse programa faz?

Não desenha telas.

Não cria animações.

Não faz gráficos.

Ele faz algo muito mais importante.

Transforma dados.

Exatamente o trabalho de um pipeline moderno.

Hoje essa transformação poderia estar escrita em:

Python.

Spark.

SQL.

Scala.

Mas o conceito permanece exatamente o mesmo.

Entrada.

Transformação.

Saída.


Um pipeline moderno não é muito diferente de um Job Batch

Vamos comparar.

No Mainframe

Arquivo VSAM

↓

Programa COBOL

↓

SORT

↓

IDCAMS

↓

DB2

↓

Relatório

Agora veja um ambiente moderno.

API

↓

Python

↓

Spark

↓

Data Lake

↓

Data Warehouse

↓

Dashboard

Mudaram as ferramentas.

O fluxo continua praticamente idêntico.

Receber.

Transformar.

Validar.

Persistir.

Consumir.

É por isso que muitos profissionais de Mainframe aprendem Engenharia de Dados com enorme facilidade.

Eles já entendem o processo.

Só precisam aprender novos nomes.


Nível 1 — SQL e Linux

Toda jornada começa aqui.

Algumas pessoas desprezam SQL.

Grave isto.

Quem domina SQL domina dados.

SQL continua sendo a língua universal da informação.

Não importa se você usa:

Oracle

SQL Server

PostgreSQL

MySQL

Db2

Snowflake

BigQuery

Databricks

Spark SQL

Todos conversam através de SQL.


No Linux acontece algo parecido.

Quem trabalha com z/OS talvez ache curioso.

Mas muitos comandos Linux lembram bastante utilitários clássicos do Mainframe.

Por exemplo.

Localizar informações.

Linux

grep CPF clientes.txt

Mainframe

SORT INCLUDE

Contar registros.

Linux

wc -l arquivo.txt

Mainframe

ICETOOL COUNT.

Filtrar.

Ordenar.

Mesclar.

Tudo isso já fazia parte do universo Batch décadas antes do Big Data existir.


Nível 2 — Programação

Aqui normalmente aparece Python.

Mas poderia ser Java.

Scala.

Go.

Até mesmo COBOL.

Sim.

COBOL continua sendo usado em pipelines modernos.

Principalmente quando o dado nasce no Mainframe.

O objetivo agora não é consultar dados.

É automatizar processos.

Imagine.

Você precisa:

baixar arquivos

consumir APIs

descompactar

validar

gerar logs

carregar banco

enviar e-mail

Tudo isso exige programação.

Não importa a linguagem.

O importante é pensar em automação.


O primeiro choque: APIs

Muitos programadores COBOL perguntam:

"O que é uma API?"

A resposta mais simples é:

Uma API é um programa conversando com outro programa.

Só isso.

Você já fazia isso.

CICS fazia isso.

MQ fazia isso.

IMS fazia isso.

A diferença é que hoje a conversa normalmente acontece usando:

HTTP

JSON

REST

GraphQL

gRPC

O conceito continua exatamente igual.


Nível 3 — Spark

Aqui começa a diversão.

Imagine que seu programa COBOL processa:

5 milhões de registros.

Funciona muito bem.

Agora imagine:

5 bilhões.

Não existe CPU suficiente.

Surge então o processamento distribuído.

Em vez de uma máquina.

Cem máquinas.

Ou mil.

Cada uma processando uma pequena parte.

Esse é o Spark.

Ele divide o problema.

Depois reúne os resultados.

É como um enorme SORT distribuído.


Spark não substitui SQL

Esse é outro mito.

Na prática.

Boa parte do Spark moderno utiliza SQL.

Ou Spark SQL.

Ou DataFrames.

Ou seja.

O conhecimento adquirido anteriormente continua sendo utilizado.

Nada é perdido.

Tudo evolui.


Nível 4 — Cloud

Aqui muita gente se assusta.

Parece outro universo.

Na verdade, não é.

Cloud é apenas um novo datacenter.

Só que alugado.

Imagine um CPD gigantesco.

Você liga um servidor.

Usa.

Desliga.

Paga apenas pelo tempo utilizado.

É isso.

Claro.

Existem centenas de serviços.

Mas a ideia continua simples.

Infraestrutura sob demanda.


O que muda para o Engenheiro de Dados?

Antes.

Você tinha um servidor.

Agora possui dezenas.

Centenas.

Tudo automatizado.

Surge então uma nova preocupação.

Escalabilidade.

Monitoramento.

Custos.

Segurança.


Nível 5 — Inteligência Artificial

Chegamos ao assunto da moda.

Todo mundo quer trabalhar com IA.

Mas poucos entendem uma verdade simples.

A IA depende completamente da Engenharia de Dados.

Imagine um modelo treinado com:

CPFs inválidos.

Datas erradas.

Valores duplicados.

Clientes repetidos.

O resultado será desastroso.

Existe uma frase muito antiga.

Garbage In.

Garbage Out.

Entrou lixo.

Sai lixo.


Por isso.

Antes da Inteligência Artificial.

Existe um profissional invisível.

O Engenheiro de Dados.

Ele garante que os dados sejam:

limpos

organizados

consistentes

históricos

auditáveis

confiáveis

Sem isso.

Nenhum ChatGPT.

Nenhum Copilot.

Nenhum modelo funciona adequadamente.


Mas existe algo ainda mais importante...

A imagem que inspirou este artigo mostra uma sequência de tecnologias.

Ela está correta.

Mas incompleta.

Porque existem conhecimentos que nunca saem de moda.


Modelagem de Dados

Se existe um superpoder do programador COBOL, é este.

Quem desenvolveu sistemas bancários conhece:

Cliente.

Conta.

Agência.

Contrato.

Movimentação.

Parcela.

Histórico.

Relacionamentos.

Tudo isso é modelagem.

Sem um bom modelo.

Nem Spark salva.

Nem IA resolve.

Nem Cloud ajuda.


Qualidade dos Dados

Imagine um cadastro onde o mesmo cliente aparece quinze vezes.

Ou um saldo negativo impossível.

Ou datas inexistentes.

Quem resolve?

Não é a IA.

É engenharia.

Validação.

Regras.

Auditoria.

Consistência.

Exatamente como fazemos há décadas em sistemas críticos.


Observabilidade

No Mainframe existe SDSF.

SMF.

RMF.

Logs.

Mensagens JES.

Abends.

Tudo isso existe para observar o ambiente.

Hoje fazemos exatamente a mesma coisa.

Só mudaram as ferramentas.

Monitoramos:

pipelines

latência

falhas

volumes

distribuição

anomalias

A filosofia continua igual.

Nunca confiar.

Sempre medir.


Governança

Poucos assuntos cresceram tanto.

Hoje toda empresa pergunta:

Quem alterou esse dado?

Quem acessou?

Quem apagou?

Quando?

Por quê?

No Mainframe isso sempre foi levado muito a sério.

RACF.

Auditoria.

Perfis.

Permissões.

Hoje apenas ampliamos esse conceito.


Versionamento

Você conhece Endevor?

ISPW?

ChangeMan?

Parabéns.

Você já trabalhou com gestão de versões antes mesmo do Git existir.

Hoje usamos GitHub.

GitLab.

Bitbucket.

Mas o princípio permanece.

Nunca alterar produção diretamente.

Sempre controlar mudanças.


DataOps

Assim como surgiu DevOps.

Hoje existe DataOps.

Automatizar testes.

Validar qualidade.

Executar pipelines.

Fazer deploy.

Documentar.

Monitorar.

Tudo automaticamente.

Isso reduz erros humanos.

Aumenta confiabilidade.

E acelera entregas.


O conhecimento mais importante continua sendo o negócio

Imagine dois profissionais.

O primeiro conhece:

Spark.

Kafka.

Snowflake.

Airflow.

Terraform.

Kubernetes.

Python.

Databricks.

O segundo conhece apenas SQL.

Mas entende perfeitamente:

crédito

seguros

contabilidade

tributação

previdência

Qual deles gera mais valor?

Na maioria das empresas.

O segundo.

Porque tecnologia resolve problemas.

Mas somente quem entende o negócio consegue resolver o problema correto.


O programador COBOL já possui metade da jornada concluída

Esse talvez seja o maior segredo da Engenharia de Dados.

Profissionais de Mainframe normalmente já dominam:

✔ Processamento Batch

✔ Integridade transacional

✔ Bancos relacionais

✔ Modelagem

✔ Performance

✔ Grandes volumes

✔ Segurança

✔ Auditoria

✔ Sistemas críticos

✔ Dados corporativos

O que falta aprender?

As ferramentas modernas.

E ferramentas podem ser aprendidas.

Princípios levam anos para serem construídos.


A verdadeira evolução

Muitos imaginam a carreira assim.

COBOL

↓

Python

↓

Spark

↓

Cloud

↓

IA

Na realidade.

Ela é muito mais parecida com isto.

                 Negócio
                     │
      ┌──────────────┼──────────────┐
      │              │              │
 Modelagem     Engenharia      Arquitetura
      │              │              │
      ├──────────────┼──────────────┤
      │              │              │
    SQL         Programação      Segurança
      │              │              │
      ├──────────────┼──────────────┤
      │              │              │
 Spark        Cloud         Observabilidade
      │              │              │
      └──────────────┼──────────────┘
                     │
                 DataOps
                     │
               Inteligência Artificial

Observe que a IA aparece quase no final.

Isso não é coincidência.

Ela depende de tudo o que veio antes.


Um café antes de voltar ao código...

Existe uma frase muito comum nas redes sociais:

"Aprenda IA."

Eu faria uma pequena correção.

Aprenda Engenharia.

Porque tecnologias mudam.

Spark um dia será substituído.

Novos bancos aparecerão.

Novas linguagens surgirão.

Novos frameworks nascerão.

Assim como Clipper deu lugar a outras soluções, e como muitas ferramentas de ETL evoluíram ao longo das décadas, o ecossistema continuará mudando.

Mas alguns princípios permanecem praticamente imutáveis desde os primeiros sistemas corporativos:

  • Dados precisam ser confiáveis.

  • Processos precisam ser previsíveis.

  • Sistemas precisam ser auditáveis.

  • Arquiteturas precisam ser sustentáveis.

  • Segurança nunca é opcional.

  • O negócio deve orientar a tecnologia, e não o contrário.

É exatamente por isso que um Programador COBOL não está começando do zero ao olhar para a Engenharia de Dados. Pelo contrário: ele já carrega uma bagagem construída em ambientes onde disponibilidade, consistência e integridade sempre foram requisitos inegociáveis.

No fim das contas, a maior transformação não é aprender Python, Spark ou Cloud. É perceber que o trabalho sempre foi o mesmo: transformar dados em informação confiável para apoiar decisões.

As ferramentas evoluem.

Os nomes mudam.

As interfaces ficam mais modernas.

Mas a boa engenharia continua sendo reconhecida pelos mesmos atributos de décadas atrás: simplicidade, clareza, desempenho, confiabilidade e foco no problema de negócio.

Então, Padawan, da próxima vez que ouvir alguém dizer que Engenharia de Dados é "uma profissão completamente nova", sorria, tome mais um gole do seu café e lembre-se: os mainframes já movimentavam bilhões de registros por dia quando muitos dos conceitos modernos ainda nem tinham nome.

quarta-feira, 23 de fevereiro de 2022

SQL versus NoSQL: A Guerra que Nunca Existiu (e por que todo Programador COBOL deveria entender os dois)

 

Bellacosa Mainframe numa guerra que nunca existiu sql versus nosql

☕ Um Café no Bellacosa Mainframe

SQL versus NoSQL: A Guerra que Nunca Existiu (e por que todo Programador COBOL deveria entender os dois)

"A tecnologia muda. Os princípios permanecem."

Imagine que você acabou de entrar em uma grande empresa. É seu primeiro emprego como programador COBOL. Você acabou de aprender JCL, já conseguiu fazer seu primeiro programa rodar no z/OS, descobriu o que é um Job, um Dataset e finalmente conseguiu fazer um SELECT sem esquecer o END-EXEC.

Então alguém da equipe comenta durante uma reunião:

"Estamos integrando o Mainframe com MongoDB."

Cinco minutos depois outro colega fala:

"Os dados vão para Redis."

Na sequência o arquiteto comenta:

"O Neo4j será usado para análise de fraude."

Você pensa:

"Mas... eu aprendi SQL... o que aconteceu? Agora existem quatro bancos diferentes?"

Bem-vindo ao desenvolvimento moderno.

Hoje vamos conversar sobre uma das maiores dúvidas de quem está começando:

SQL ou NoSQL?

Spoiler...

A resposta é muito diferente do que a internet costuma vender.

Pegue seu café.

Vamos conversar.


O mito da guerra

Existe uma narrativa que aparece em vídeos, blogs e redes sociais dizendo que:

SQL morreu.

Ou então:

NoSQL veio substituir os bancos relacionais.

Nada poderia estar mais distante da realidade.

Na verdade, SQL nunca esteve tão vivo.

E NoSQL nunca tentou matá-lo.

Os dois nasceram para resolver problemas completamente diferentes.

É como comparar:

  • um caminhão

  • um avião

Qual é melhor?

Depende.

Você quer transportar cimento entre cidades?

Ou cruzar o oceano?

A pergunta está errada.

Da mesma forma:

A pergunta nunca foi SQL versus NoSQL.

A pergunta correta sempre foi:

Qual tecnologia resolve melhor ESTE problema?


Uma pequena viagem no tempo

Imagine que estamos em 1970.

Os computadores ocupavam salas inteiras.

Não existia internet.

Não existia smartphone.

Nem notebook.

Muito menos Cloud.

Os bancos de dados funcionavam quase como arquivos gigantes.

Era preciso conhecer exatamente onde cada informação estava gravada.

Era complicado.

Foi então que um pesquisador da IBM chamado Edgar Frank Codd publicou um artigo que mudaria para sempre a computação:

A Relational Model of Data for Large Shared Data Banks

Esse trabalho apresentou uma ideia brilhante.

Em vez de pensar em ponteiros físicos...

Vamos pensar em relações.

Assim nasceram:

  • tabelas

  • linhas

  • colunas

  • chaves

  • relacionamentos

Nascia o Modelo Relacional.

Poucos anos depois, a própria IBM desenvolveu o System R, um projeto experimental que introduziu a linguagem SQL (Structured Query Language). A ideia mostrou tanto potencial que outras empresas passaram a investir no modelo, surgindo plataformas como Oracle, Informix, SQL Server, PostgreSQL, MySQL e, naturalmente, o Db2, um dos pilares do universo IBM Mainframe.


Por que o SQL fez tanto sucesso?

Porque ele resolveu um problema gigantesco.

Imagine um banco.

Existem milhões de clientes.

Cada cliente possui:

  • conta corrente

  • poupança

  • investimentos

  • cartões

  • empréstimos

Tudo isso precisa estar relacionado.

Se João mudar de endereço...

Não faz sentido atualizar vinte lugares diferentes.

O SQL organiza essas informações em tabelas relacionadas, reduzindo redundâncias e garantindo consistência.

Esse conceito recebe o nome de normalização.

Parece um detalhe.

Na prática...

Economizou bilhões de dólares em armazenamento ao longo da história.


ACID: o superpoder invisível

Existe um conceito que todo programador júnior deveria decorar.

ACID.

Não porque cai em entrevista.

Mas porque explica por que bancos confiam tanto em SQL.

Imagine transferir R$ 500 de uma conta para outra.

São duas operações:

  • retirar da Conta A

  • adicionar na Conta B

E se faltar energia exatamente no meio?

ACID garante que isso não aconteça.

Ou tudo acontece...

Ou nada acontece.

Isso é chamado de Atomicidade.

Depois temos:

Consistência

Os dados permanecem válidos.

Isolamento

Milhares de pessoas podem operar simultaneamente sem "atropelar" umas às outras.

Durabilidade

Depois do COMMIT...

Mesmo que o servidor desligue...

Os dados continuam lá.

É por isso que bancos, seguradoras e bolsas de valores continuam confiando em bancos relacionais.


Onde entra o Mainframe?

Agora vem uma curiosidade que muita gente desconhece.

Grande parte do dinheiro que circula diariamente no mundo passa por Mainframes.

Cartões.

PIX.

TED.

DOC.

Compras internacionais.

Folha de pagamento.

Seguros.

Tudo isso frequentemente passa por sistemas COBOL utilizando Db2 for z/OS.

Quando você escreve:

EXEC SQL

SELECT SALDO

INTO :WS-SALDO

FROM CONTAS

WHERE NUMERO = :WS-CONTA

END-EXEC.

O SQL não está apenas buscando dados.

Existe todo um universo trabalhando por trás:

  • Pré-compilador SQL

  • DBRM

  • Package

  • Bind

  • Plan

  • Otimizador

  • Buffer Pools

  • Logging

  • Locking

  • Recovery

O desenvolvedor enxerga apenas a ponta do iceberg.


Então por que surgiu o NoSQL?

Porque o mundo mudou.

Muito.

Em 1970 ninguém imaginava redes sociais.

Nem streaming.

Nem IoT.

Nem celulares.

Nem milhões de fotos por minuto.

Agora imagine armazenar:

  • vídeos

  • comentários

  • curtidas

  • localização

  • mensagens

  • sensores

  • documentos JSON

Tudo isso em tabelas relacionais.

Funciona?

Sim.

Mas nem sempre é a melhor escolha.

Foi então que surgiu o movimento NoSQL.

Curiosamente...

NoSQL não significa "Sem SQL".

Significa:

Not Only SQL

Ou seja...

Existem outros modelos além do relacional.


Os quatro reinos do NoSQL

Quando alguém diz "NoSQL", na verdade está falando de uma família inteira de bancos.

📄 Documento

Exemplo:

MongoDB.

Os dados ficam parecidos com JSON.

Cada documento pode possuir uma estrutura diferente.

Perfeito para aplicações web.


🔑 Chave-Valor

Exemplo:

Redis.

Imagine um gigantesco dicionário.

Você fornece uma chave.

Recebe um valor.

Extremamente rápido.

Muito utilizado como cache.


📚 Colunar

Exemplos:

Cassandra.

ScyllaDB.

HBase.

Projetados para trabalhar com enormes volumes distribuídos.

Muito utilizados em Big Data.


🌐 Grafos

Exemplo:

Neo4j.

Aqui o importante não são os registros.

São os relacionamentos.

Quem conhece quem?

Quem comprou junto?

Quem transferiu dinheiro para quem?

Ideal para detectar fraudes.


SQL é rígido?

Sim.

E isso é uma vantagem.

Imagine um cadastro de funcionários.

Todos possuem:

  • matrícula

  • nome

  • salário

  • departamento

É ótimo exigir que todos tenham exatamente a mesma estrutura.

Já em uma rede social...

Cada usuário pode possuir informações diferentes.

Uns possuem Instagram.

Outros TikTok.

Outros LinkedIn.

Outros nenhum.

Forçar uma estrutura única pode ser desnecessário.

É aí que bancos orientados a documentos brilham.


Escalabilidade

Existe outra diferença importante.

Tradicionalmente, bancos SQL cresceram na vertical.

Mais CPU.

Mais memória.

Mais discos.

Servidor maior.

Já muitos bancos NoSQL foram desenhados pensando em crescer horizontalmente.

Mais servidores.

Mais nós.

Mais máquinas.

É o modelo utilizado por empresas como Google, Amazon, Netflix e Meta.

Mas atenção: hoje essa divisão não é absoluta. Bancos relacionais modernos também oferecem mecanismos de escalabilidade horizontal, e diversas soluções NoSQL implementam recursos avançados de consistência e transações.


SQL também evoluiu

Existe outro mito.

"O SQL parou no tempo."

Errado.

Hoje temos:

  • JSON dentro do PostgreSQL

  • JSON no Oracle

  • JSON no SQL Server

  • JSON no Db2

  • XML

  • Graph Extensions

  • Machine Learning integrado

  • Consultas analíticas

  • Window Functions

  • Compressão avançada

  • IA auxiliando otimização

Os bancos relacionais modernos absorveram diversas características que antes eram exclusivas do NoSQL.


NoSQL também evoluiu

MongoDB hoje possui:

  • transações

  • índices sofisticados

  • agregações complexas

Redis deixou de ser apenas cache.

Neo4j suporta consultas extremamente sofisticadas.

Cassandra possui consistência configurável.

Ou seja...

Os mundos estão convergindo.


O conceito mais importante: Polyglot Persistence

Se existe uma expressão que todo desenvolvedor moderno deveria conhecer é esta:

Polyglot Persistence.

Ela significa:

usar o banco certo para cada problema.

Imagine um banco digital.

Ele pode utilizar:

Db2 → contas correntes

MongoDB → documentos

Redis → cache

Neo4j → fraude

Elastic → pesquisa

Banco Vetorial → IA

Tudo funcionando junto.

Não existe regra dizendo que um sistema deve possuir apenas um banco.


O papel do COBOL nessa história

Aqui existe um enorme equívoco.

Muitos imaginam que COBOL só conversa com Db2.

Hoje isso está longe da realidade.

Aplicações COBOL podem consumir:

REST APIs.

MQ.

Kafka.

gRPC.

z/OS Connect.

Eventos.

Microsserviços.

E esses serviços podem acessar MongoDB, Redis ou qualquer outro banco moderno.

O COBOL continua sendo o cérebro transacional.

Os demais componentes ampliam suas capacidades.


Dicas para quem está começando

Se eu pudesse aconselhar um programador júnior, seguiria esta ordem:

  1. Aprenda modelagem de dados.

  2. Domine SQL.

  3. Entenda normalização.

  4. Aprenda índices.

  5. Estude planos de acesso.

  6. Descubra como funciona um otimizador.

  7. Aprenda transações.

  8. Depois estude MongoDB.

  9. Conheça Redis.

  10. Descubra Neo4j.

  11. Aprenda APIs REST.

  12. Entenda eventos e mensageria.

A tecnologia muda.

Os fundamentos permanecem.


Curiosidades que pouca gente conhece

☕ O primeiro grande projeto SQL da IBM chamava-se System R.

☕ O Db2 nasceu dentro da IBM justamente para materializar as ideias do modelo relacional em ambientes corporativos.

☕ O comando SELECT * é um dos mais utilizados por iniciantes... e um dos menos recomendados em produção. Buscar apenas as colunas necessárias reduz tráfego de dados e melhora o desempenho.

☕ Muitos sistemas bancários escritos há mais de 30 anos continuam processando milhões de transações diariamente com desempenho impressionante.

☕ Redis consegue responder consultas em microssegundos porque mantém os dados principalmente em memória.

☕ Neo4j foi inspirado na Teoria dos Grafos, um ramo da matemática muito mais antigo do que os computadores.

☕ Diversos bancos NoSQL utilizam conceitos publicados em artigos científicos da Google e da Amazon sobre sistemas distribuídos, como Bigtable, Dynamo e MapReduce.

☕ O termo NoSQL surgiu como um movimento alternativo, mas acabou sendo reinterpretado como Not Only SQL, refletindo melhor a realidade atual.


Easter Eggs Bellacosa Mainframe 🥚

🔍 Easter Egg #1 – O herói invisível

Sempre que você executa um SELECT no Db2, existe um componente trabalhando silenciosamente para decidir o melhor caminho de acesso: o otimizador de consultas. Ele é como o GPS do banco de dados. Você não o vê, mas ele escolhe a rota mais eficiente.


🥚 Easter Egg #2 – O COBOL nunca pergunta "como"

Um programa COBOL com Embedded SQL apenas descreve o que deseja. Quem decide como buscar os dados é o Db2. Essa separação entre intenção e estratégia foi uma das grandes revoluções introduzidas pelo SQL.


🥚 Easter Egg #3 – O Mainframe conversa com o futuro

Um programa COBOL criado na década de 1990 pode, com poucas adaptações, consumir uma API REST hospedada na nuvem que, por sua vez, grava documentos em MongoDB e publica eventos em Kafka. O legado não é um obstáculo: ele pode ser parte da arquitetura moderna.


🥚 Easter Egg #4 – Nem tudo é tabela

Quando você olhar para uma árvore genealógica, uma rede social ou um mapa de rotas aéreas, pense em grafos. Quando observar um catálogo de produtos com atributos diferentes para cada item, pense em documentos. Quando acessar seu extrato bancário, pense em tabelas relacionais. O segredo está em reconhecer o problema antes de escolher a ferramenta.


Conclusão

No fim das contas, SQL e NoSQL não são adversários. São aliados que nasceram em épocas diferentes para enfrentar desafios distintos. O SQL continua sendo o alicerce dos sistemas críticos que exigem consistência, integridade e confiabilidade — exatamente o tipo de ambiente onde o IBM Z e o Db2 brilham há décadas. Já o NoSQL oferece flexibilidade, escalabilidade e modelos especializados que complementam essas capacidades em aplicações modernas, distribuídas e orientadas a dados.

Se você está iniciando sua jornada como programador COBOL ou desenvolvedor Mainframe, não caia na armadilha dos modismos. Aprenda primeiro os fundamentos: modelagem de dados, SQL, índices, transações e otimização de consultas. Esses conhecimentos acompanharão toda a sua carreira. Depois, expanda seus horizontes estudando MongoDB, Redis, Cassandra, Neo4j e outras tecnologias que fazem parte das arquiteturas atuais.

Lembre-se sempre de uma filosofia muito presente no universo Bellacosa Mainframe:

Um excelente desenvolvedor não é aquele que conhece todas as ferramentas, mas aquele que sabe exatamente quando usar cada uma delas.

No mundo do IBM Z, onde convivem sistemas escritos há décadas com APIs, microsserviços, inteligência artificial e computação em nuvem, essa capacidade de escolher a tecnologia certa é o que transforma um programador júnior em um verdadeiro arquiteto de soluções. Afinal, o futuro não pertence ao SQL nem ao NoSQL. Ele pertence aos profissionais que compreendem ambos e conseguem fazê-los trabalhar juntos.


Vagner Renato Bellacosa, IBM Champion e especialista em IBM Mainframe
IBM Z17 SYSTEM ONLINE
Sobre o autor

Vagner Renato Bellacosa

IBM Champion 2026 • Especialista em IBM Mainframe

Vagner Renato Bellacosa trabalha com IBM Mainframe desde 1988 , é IBM Champion e especialista em COBOL, CICS, Db2, z/OS e IBM Z. Compartilha experiências profissionais, conhecimento técnico, história da computação e práticas do universo mainframe para aproximar novas gerações das tecnologias que sustentam empresas, bancos e governos ao redor do mundo.

IBM Champion IBM Z COBOL CICS Db2 z/OS Mainframe desde 1988
GitHub LinkedIn
Inicializando conteúdo...