Control Interval — a unidade de I/O

O Control Interval (CI) é a unidade mínima de transferência entre disco e memória no VSAM. Toda vez que o VSAM precisa ler ou gravar dados, ele movimenta um CI inteiro — mesmo que o programa precise de um único registro.

🦕 Analogia: Pense numa biblioteca onde os livros são guardados em caixas. Quando você pede um livro, o bibliotecário busca a caixa inteira (CI), tira o livro que você quer, e devolve a caixa. Mesmo que você queira apenas uma página, a caixa toda sai da prateleira. O tamanho da caixa é o CISZ — Control Interval Size.

Um CI contém:

┌─────────────────────────────────────────────────────────┐
│  CI = CISZ bytes (ex: 4096 bytes)                        │
│                                                          │
│  ┌──────────┬──────────┬──────────┬───────┬────┬────┐   │
│  │ Registro │ Registro │ Registro │       │RDF │CIDF│   │
│  │    1     │    2     │    3     │ Free  │    │    │   │
│  │ (120 B)  │ (120 B)  │ (120 B)  │ space │ 3B │ 4B│   │
│  └──────────┴──────────┴──────────┴───────┴────┴────┘   │
│                                                          │
│  Dados → crescem da esquerda para a direita              │
│  RDF+CIDF → ficam sempre no final (direita)              │
└─────────────────────────────────────────────────────────┘

O tamanho do CI é definido no parâmetro CONTROLINTERVALSIZE (ou CISZ) do IDCAMS. Se não especificado, o VSAM escolhe automaticamente com base no tamanho do registro e do track do disco.

CIDF e RDF — os campos de controle

Ao final de cada CI existem campos de controle que o VSAM usa internamente — nunca acessíveis pelo programa de aplicação:

CIDF — Control Interval Definition Field (4 bytes)

Um por CI. Descreve o espaço livre disponível no CI:

Campo no CIDFConteúdo
Offset do freespaceByte onde começa o espaço livre dentro do CI
Tamanho do freespaceQuantos bytes livres existem no CI

RDF — Record Definition Field (3 bytes cada)

Um ou mais RDFs por CI, um para cada registro (em registros de comprimento fixo há apenas dois RDFs). Cada RDF descreve um registro:

Campo no RDFConteúdo
Comprimento do registroTamanho em bytes do registro descrito
Contador de repetiçõesQuantos registros consecutivos têm esse mesmo tamanho (otimização para registros fixos)
Por que isso importa na prática: o espaço ocupado por CIDF e RDFs reduz o espaço útil do CI para dados. Em registros de comprimento variável, há um RDF por registro — quanto mais registros por CI, mais espaço os RDFs consomem. Isso influencia o cálculo do CISZ ideal.

Control Area — agrupando CIs

Uma Control Area (CA) é um conjunto de CIs contíguos no disco. O VSAM aloca espaço em CAs — não em CIs individuais. Quando o dataset precisa de mais espaço (secondary allocation), o VSAM aloca uma nova CA completa.

  Dataset VSAM
  ├── CA 1 (ex: 1 cylinder)
  │   ├── CI 1  [reg A, reg B, reg C | freespace | RDF RDF RDF | CIDF]
  │   ├── CI 2  [reg D, reg E        | freespace | RDF RDF     | CIDF]
  │   ├── CI 3  [freespace completo  |            |             | CIDF] ← CA freespace
  │   └── ...
  ├── CA 2
  │   ├── CI 1  [reg F, reg G, reg H | freespace | RDF RDF RDF | CIDF]
  │   └── ...
  └── ...

O tamanho da CA é determinado pela geometria do disco — geralmente um cilindro. No VSAM moderno com discos virtuais (VDISK/EAV), o conceito de cilindro é abstraído, mas a CA ainda existe como unidade de alocação secundária.

Estrutura do KSDS — dados e índice

Um dataset KSDS tem dois componentes físicos separados no disco:

ComponenteConteúdoNome no IDCAMS
Data ComponentOs registros em si, ordenados pela chave primária, armazenados em CIs e CAssufixo .DATA
Index ComponentEstrutura B-tree com os valores de chave e ponteiros para os CIs correspondentes no Data Componentsufixo .INDEX

Para localizar um registro por chave, o VSAM faz:

  1. Lê o índice (sequence set) → encontra o CI que contém a chave
  2. Lê o CI do data component → varre os registros até achar a chave
  3. Retorna o registro para o programa

  Mínimo: 2 I/Os (1 index + 1 data)
  Na prática: índice costuma estar em buffer → 1 I/O (só o data CI)
💗 Index component não tem freespace. O índice do KSDS é mantido pelo próprio VSAM e não aceita parâmetros de freespace. Somente o Data Component tem CI% e CA% configuráveis.

Freespace — CI% e CA%

O freespace é espaço intencionalmente deixado vazio dentro dos CIs e das CAs no momento da carga inicial do dataset. Esse espaço existe para acomodar inserções futuras sem precisar reorganizar os dados imediatamente.

É definido no IDCAMS com o parâmetro FREESPACE(ci% ca%):

  FREESPACE(20 10)
  │            │
  │            └── 10% de cada CA é reservada como CIs completamente vazios
  └────────────── 20% de cada CI é reservado como bytes livres dentro do CI

CI% — freespace dentro do CI

Determina quantos bytes de cada CI ficam livres após a carga inicial. Com FREESPACE(20 0) e CISZ de 4096 bytes:

  Bytes disponíveis para dados: 4096 × (1 - 0,20) = 3277 bytes
  Bytes reservados como freespace: 4096 × 0,20 = 819 bytes

Quando um novo registro é inserido numa posição já existente, o VSAM usa esse espaço livre para encaixá-lo sem mover dados para outro CI.

CA% — freespace dentro da CA

Determina quantos CIs de cada CA ficam completamente vazios após a carga inicial. Com FREESPACE(0 10) e uma CA com 20 CIs:

  CIs com dados: 20 × (1 - 0,10) = 18 CIs
  CIs completamente vazios: 20 × 0,10 = 2 CIs

Esses CIs vazios são usados quando um CI fica completamente cheio e não cabe mais nenhum registro — o que desencadeia um CI Split.

Escolhendo CI% e CA% na prática

Perfil de usoCI%CA%Justificativa
Somente leitura (tabela de referência)00Sem inserções — maximiza densidade e reduz I/Os
Poucas inserções distribuídas10–155Absorve inserções sem splits frequentes
Muitas inserções aleatórias20–3010–15Dataset transacional com INSERT intenso
Cargas em ordem crescente de chave00Inserções no final nunca causam splits no meio

CI Split — quando o CI fica cheio

Um CI Split ocorre quando o VSAM precisa inserir um registro em um CI que não tem freespace suficiente para acomodá-lo. O VSAM então:

  Antes do CI Split:
  ┌─────────────────────────────────────┐
  │ reg A │ reg B │ reg C │ reg D │ sem │
  │ (10)  │ (10)  │ (10)  │ (10)  │ esp │
  └─────────────────────────────────────┘
         ↑ inserir reg B2 aqui — não há espaço!

  Depois do CI Split:
  ┌──────────────────────────┐   ┌──────────────────────────┐
  │ reg A │ reg B │ reg B2  │   │ reg C │ reg D │  free    │
  └──────────────────────────┘   └──────────────────────────┘
  CI original (metade dos dados)   CI novo (metade restante)
                                   ↑ veio do CA freespace

O VSAM move aproximadamente metade dos registros do CI original para um CI vazio da CA (do CA freespace). Depois encaixa o novo registro na posição correta.

⚠️ CI Splits têm custo alto. Cada CI Split envolve múltiplos I/Os (ler o CI original, gravar o CI original modificado, gravar o novo CI, atualizar o índice). Em períodos de alto volume de inserções, um dataset sem freespace adequado pode sofrer dezenas de splits por minuto, degradando a performance.

CA Split — quando a CA fica cheia

Um CA Split ocorre quando um CI Split não pode ser completado porque a CA não tem mais nenhum CI vazio (CA freespace esgotado). O VSAM então:

  1. Aloca uma nova CA (secondary extent)
  2. Move aproximadamente metade dos CIs da CA cheia para a nova CA
  3. Executa o CI Split normalmente no espaço liberado
  4. Atualiza o índice para refletir a nova organização
⚠️ CA Splits são muito mais custosos que CI Splits. Envolvem movimentação de grandes blocos de dados no disco e alocação de extents secundários. Um dataset com muitos CA Splits fica fragmentado em múltiplos extents não contíguos — leituras sequenciais se tornam lentas porque o cabeçote do disco precisa se deslocar entre extents. É o principal indicador de que o dataset precisa ser reorganizado.
🦕 Analogia: CI Split é como reorganizar uma gaveta que ficou cheia — você pega metade das coisas e coloca em outra gaveta vazia. CA Split é quando não há gaveta vazia disponível — você precisa comprar um armário novo (nova CA) e reorganizar tudo.

Escolhendo o tamanho do CI

O CONTROLINTERVALSIZE (CISZ) influencia diretamente a performance de leitura e escrita. Valores válidos são múltiplos de 512, de 512 até 32768 bytes (para o data component). O index component tem CISZ menor, geralmente 512 ou 1024.

CI maiorCI menor
Mais registros por I/O → melhor para leitura sequencialMenos registros por I/O → melhor para acesso aleatório
CI Split move mais dados → mais custosoCI Split move menos dados → mais barato
Mais dados em buffer → mais registros em cacheMenos overhead de buffer
Indicado para relatórios, cargas batchIndicado para transações CICS de acesso direto

Cálculo orientativo do CISZ

  Fórmula básica para KSDS:
  CISZ = (registros por CI desejados × tamanho do registro)
         + (registros por CI × 3 bytes de RDF)
         + 4 bytes de CIDF
         + freespace CI%

  Exemplo: registro de 200 bytes, 15 registros por CI, 20% freespace
  CISZ mínimo = (15 × 200) + (15 × 3) + 4 = 3049 bytes
  Com 20% freespace: 3049 / 0,80 = 3812 bytes
  → arredondar para o próximo múltiplo de 512: CISZ = 4096
Na prática: CISZs de 4096 (4KB) a 8192 (8KB) são os mais comuns em arquivos transacionais. Arquivos de carga batch ou relatórios usam 16384 (16KB) ou 32768 (32KB). Se não especificado, o VSAM calcula automaticamente — o valor automático é aceitável para a maioria dos casos.

Monitorando com LISTCAT

O comando LISTCAT do IDCAMS exibe as estatísticas de uso de um dataset VSAM. É a principal ferramenta para identificar fragmentação e necessidade de reorganização.

//* JCL para LISTCAT com estatísticas detalhadas
//LISTCAT  EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN    DD *
  LISTCAT ENTRIES(BANCO.PROD.CNTFILE) -
          ALL
/*

Os campos mais importantes na saída do LISTCAT para monitorar saúde do dataset:

Campo no LISTCATSignificadoSinal de alerta
CI-SPLITSTotal de CI Splits desde a última reorganizaçãoCrescimento rápido indica freespace insuficiente
CA-SPLITSTotal de CA Splits desde a última reorganizaçãoQualquer valor > 0 merece atenção; > 10 indica necessidade urgente de REORG
EXTENTSNúmero de extents alocados> 5 extents indica fragmentação física severa
REC-TOTALTotal de registros no datasetComparar com REC-DELETED para ver densidade real
REC-DELETEDRegistros marcados como deletados (slots vazios)Alto REC-DELETED com baixo REC-TOTAL = desperdício de espaço
FREESPACE-%CIPercentual atual de freespace nos CIsMuito baixo = risco de splits iminentes
FREESPACE-%CAPercentual atual de freespace nas CAsZero = próximo CA Split causará alocação de extent
* trecho típico de saída do LISTCAT ALL
DATA ---BANCO.PROD.CNTFILE.DATA
  STATISTICS
    REC-TOTAL-----------1250000
    REC-DELETED-----------12500
    CI-SPLITS--------------3821   ← alto! freespace CI% muito baixo
    CA-SPLITS----------------47   ← crítico! reorganizar urgente
  ALLOCATION
    SPACE-TYPE----------CYLINDER
    SPACE-PRI----------------100
    SPACE-SEC-----------------20
    EXTENTS-------------------14  ← muito fragmentado

Quando reorganizar

Reorganizar um dataset VSAM significa exportar todos os registros em ordem de chave e reimportá-los para um dataset novo (ou para o mesmo após deletar e recriar). Isso elimina fragmentação, restaura o freespace definido e consolida os extents.

IndicadorAção recomendada
CA-SPLITS > 10Reorganização urgente
EXTENTS > 5Reorganização em breve
Degradação visível de tempo de resposta em transações CICSInvestigar CI/CA-SPLITS e EXTENTS; reorganizar se confirmado
REC-DELETED > 20% de REC-TOTALMuitos slots vazios desperdiçando espaço; reorganizar
Dataset com carga batch noturna e zero inserções durante o diaReconstruir do zero toda noite com REPRO — mais eficiente que freespace

A reorganização em si é feita com o IDCAMS — seja com REPRO (cópia) ou com o par DELETE + DEFINE + REPRO. O artigo seguinte cobre esses comandos em detalhe.

🟣 Avançado — IMBED e REPLICATE (legado): Versões antigas do VSAM tinham parâmetros IMBED (guardar o sequence set do índice no primeiro track de cada CA) e REPLICATE (duplicar o sequence set em cada track da CA) para reduzir I/Os de índice. Esses parâmetros são obsoletos em DFSMS moderno — o gerenciador de buffers resolve o mesmo problema de forma mais eficiente. Se você os encontrar em JCLs antigos, ignore-os com segurança.