Todos os produtos
Search
Central de documentação

ApsaraDB for MongoDB:Melhores práticas para índices TTL no ApsaraDB for MongoDB

Última atualização: Sep 17, 2026

Um índice TTL (Time-To-Live) é um tipo especial de índice de campo único que o MongoDB utiliza para excluir documentos automaticamente após a expiração. Este tópico descreve o funcionamento dos índices TTL, como criá-los e gerenciá-los, suas limitações, problemas comuns com soluções e as melhores práticas para uso no ApsaraDB for MongoDB.

Visão geral

O índice TTL (Time-To-Live) é um índice especial de campo único usado pelo MongoDB para remover documentos automaticamente quando atingem um tempo de expiração definido. Esse recurso é ideal para gerenciar dados com ciclo de vida bem determinado, como registros de log, informações de sessão, caches temporários e códigos de verificação. O uso adequado de índices TTL permite controlar eficazmente o volume de dados de uma coleção e evitar o crescimento descontrolado do armazenamento.

No entanto, a utilização incorreta desses índices em ambientes de produção pode causar diversos problemas, incluindo picos periódicos de CPU, atraso na exclusão de dados expirados e aumento contínuo do espaço em disco. Este tópico explica o funcionamento dos índices TTL, seu modo de uso, questões frequentes e melhores práticas para auxiliar você a utilizá-los corretamente no ApsaraDB for MongoDB.

Funcionamento dos índices TTL

Mecanismo básico

Ao iniciar um processo mongod, o sistema cria uma thread em segundo plano chamada TTLMonitor. Por padrão, essa thread inicia um ciclo de limpeza TTL a cada 60 segundos. Cada ciclo executa as seguintes operações:

  1. Coleta todos os índices TTL no banco de dados atual.

  2. Gera um plano de execução para cada índice TTL sequencialmente e limpa os dados.

  3. Exclui os documentos cujo valor do campo indexado somado a expireAfterSeconds seja anterior à hora atual.

O cálculo do limiar de expiração ocorre da seguinte forma: o valor de data do campo indexado mais o número de segundos especificado por expireAfterSeconds. Se o resultado for anterior à hora atual, o documento é considerado expirado.

Comportamento em replica sets

Em um replica set, a thread em segundo plano do TTL executa operações de exclusão apenas no nó Primary. As threads TTL nos nós Secondary permanecem ociosas e sincronizam as exclusões replicando o oplog do nó Primary. Isso significa que as exclusões TTL geram entradas adicionais no oplog e podem afetar o atraso de replicação do replica set.

Diferenças entre versões: otimização de exclusão em lote (MongoDB 7.0+)

A partir do MongoDB 7.0 (recurso introduzido originalmente na versão de desenvolvimento 6.1), a exclusão TTL utiliza um mecanismo de "exclusão justa" que aloca tempo de exclusão para cada índice TTL em fatias de tempo. Essa abordagem evita que dados expirados em certas coleções fiquem sem limpeza. As principais melhorias incluem:

  • ttlMonitorBatchDeletes: Ativa o modo de exclusão em lote. Habilitado por padrão. Quando ativo, distribui as exclusões TTL de maneira mais equilibrada entre as coleções.

  • ttlIndexDeleteTargetTimeMS: Limite máximo de tempo por rodada de exclusão para cada índice TTL. Valor padrão: 1000 ms.

  • ttlIndexDeleteTargetDocs: Limite máximo de documentos excluídos por rodada para cada índice TTL. Valor padrão: 50000.

  • ttlMonitorSubPassTargetSecs: Limite máximo de tempo para uma subpassagem que itera sobre os índices TTL. Valor padrão: 60 segundos.

Esses parâmetros aparecem como o estágio BATCHED_DELETE no plano de execução e são visíveis através do comando explain.

Criação e gerenciamento de índices TTL

Criar um índice TTL

Utilize o método createIndex para criar um índice TTL em um campo do tipo Date.

Exemplo 1: Crie um índice TTL para que os documentos expirem 3600 segundos após o valor do campo lastModifiedDate.

db.eventlog.createIndex(
  { "lastModifiedDate": 1 },
  { expireAfterSeconds: 3600 }
)

Exemplo 2: Expiração em um momento específico. Defina expireAfterSeconds como 0 para que apenas o valor do campo determine o tempo de expiração.

db.sessions.createIndex(
  { "expireAt": 1 },
  { expireAfterSeconds: 0 }
)

Modificar o tempo de expiração de um índice TTL

Use o comando collMod para alterar o valor de expireAfterSeconds de um índice TTL existente sem precisar recriar o índice.

db.runCommand({
  "collMod": "log_events",
  "index": {
    "keyPattern": { "createdAt": 1 },
    "expireAfterSeconds": 600
  }
})

Converter um índice comum em índice TTL (MongoDB 6.0+)

Desde o MongoDB 6.0, é possível usar o comando collMod para converter um índice comum de campo único existente em um índice TTL, sem necessidade de excluí-lo e recriá-lo previamente.

db.runCommand({
  "collMod": "tickets",
  "index": {
    "keyPattern": { "lastModifiedDate": 1 },
    "expireAfterSeconds": 100
  }
})

Monitorar o status do TTL

Monitore as operações TTL utilizando os comandos abaixo.

// View the total number of documents deleted by TTL
db.serverStatus().metrics.ttl.deletedDocuments

// View the number of TTL thread passes
db.serverStatus().metrics.ttl.passes

// View the TTL scan interval (default: 60 seconds)
db.runCommand({ getParameter: 1, ttlMonitorSleepSecs: 1 })

// View the TTL delete operations that are currently running
db.currentOp()

Limitações dos índices TTL

Antes de utilizar um índice TTL, considere as seguintes limitações importantes:

  • Índices TTL suportam apenas índices de campo único. Índices compostos não aceitam o recurso TTL. Mesmo que você defina expireAfterSeconds, o parâmetro será ignorado.

  • O campo _id não aceita índices TTL.

  • O campo indexado deve ser do tipo BSON Date. Se o valor do campo não for do tipo Date (por exemplo, um inteiro de timestamp UNIX ou uma string), os documentos não serão excluídos automaticamente.

  • Documentos sem o campo indexado não expiram.

  • Se o campo for um array, o valor de data mais antigo no array será usado para calcular o tempo de expiração.

  • **Não é possível modificar um índice TTL existente usando createIndex**; utilize o comando collMod.

  • **expireAfterSeconds deve estar no intervalo de 0 a 2.147.483.647**, e não pode ser definido como NaN. Caso contrário, podem ocorrer comportamentos inesperados e perda de dados.

Problemas comuns e soluções

Problema 1: Picos periódicos de CPU causados por exclusões TTL

Sintoma

O uso da CPU da instância apresenta picos periódicos evidentes em intervalos fixos. Ao executar db.currentOp(), observa-se que a thread TTL está realizando um grande volume de operações de exclusão.

Causa

Quando a aplicação insere uma grande quantidade de dados no mesmo momento e os valores do campo TTL são idênticos ou muito próximos, esses documentos expiram na mesma janela de tempo. A thread TTL precisa excluir muitos documentos em uma única varredura, o que gera pressão significativa sobre a CPU e o I/O.

Solução

  • Distribua os tempos de expiração: Ao inserir dados, adicione um deslocamento aleatório ao campo TTL para espalhar as expirações ao longo de uma janela de tempo e evitar exclusões em massa. Por exemplo, para dados que expiram em 24 horas, some ou subtraia um deslocamento aleatório de alguns minutos ao tempo de expiração.

  • Atualize para o MongoDB 7.0 ou superior: Utilize os mecanismos de exclusão em lote e exclusão justa para suavizar a pressão das exclusões.

  • Escolha uma especificação de instância adequada: Garanta que a instância tenha CPU e memória suficientes para lidar com a carga adicional das exclusões TTL.

Exemplo: Adicione um deslocamento aleatório de expiração aos dados inseridos.

// Add a random offset of 0 to 600 seconds on top of 24 hours
var randomOffset = Math.floor(Math.random() * 600);
var expireTime = new Date(Date.now() + (86400 + randomOffset) * 1000);
db.logs.insertOne({
  data: "log content",
  createdAt: expireTime
})

Problema 2: Dados não são excluídos após a expiração

Sintoma

Os documentos ultrapassaram o tempo de expiração esperado, mas ainda existem na coleção.

Etapas de solução de problemas

  1. Verifique o tipo do campo: Confirme se o valor do campo indexado pelo TTL é do tipo BSON Date. Um erro comum é usar um inteiro de timestamp UNIX em vez de um objeto Date.

    // Check the field type
    db.collection.findOne({}, { createdAt: 1 })
    // Correct: ISODate("2024-01-01T00:00:00Z")
    // Wrong: 1704067200 (integer timestamp)
  2. Confirme a existência do campo: Verifique se os documentos realmente contêm o campo indexado pelo TTL. Documentos sem esse campo não são excluídos automaticamente.

  3. Valide a definição do índice: Certifique-se de que o índice inclui a propriedade expireAfterSeconds.

    db.collection.getIndexes()
  4. Verifique a direção do índice: Garanta que o índice TTL esteja em ordem ascendente (valor 1). Um índice descendente pode fazer o TTL falhar. Se a direção estiver incorreta, exclua e recrie o índice.

  5. Verifique se o TTL Monitor está ativado: Confirme se o parâmetro ttlMonitorEnabled está definido como true.

    db.adminCommand({ getParameter: 1, ttlMonitorEnabled: 1 })

Problema 3: A exclusão TTL não acompanha a taxa de inserção de dados

Sintoma

O volume de dados na coleção continua crescendo e o uso do disco aumenta constantemente, mesmo com um índice TTL configurado.

Causa

A thread TTL é single-threaded e executa a cada 60 segundos. Quando a taxa de inserção de dados supera em muito a taxa de limpeza do TTL, os dados expirados se acumulam. Além disso, se houver múltiplos índices TTL em uma instância, eles são processados serialmente, reduzindo ainda mais a eficiência da limpeza.

Solução

  • Ajuste a frequência de varredura: Reduza o intervalo de varredura definindo o parâmetro ttlMonitorSleepSecs. Note que uma frequência maior aumenta a carga do sistema.

    // Set the scan interval to 10 seconds
    db.adminCommand({ setParameter: 1, ttlMonitorSleepSecs: 10 })
  • Realize a limpeza no lado da aplicação: Para cenários com volumes de escrita particularmente altos, implemente uma exclusão em lote agendada na sua aplicação em vez de depender exclusivamente de índices TTL.

  • Considere coleções particionadas por tempo: Em cenários de escrita extremamente alta, particione os dados em coleções por tempo e exclua (drop) coleções inteiras expiradas. Essa abordagem é muito mais eficiente do que excluir documentos individualmente com um índice TTL.

Problema 4: Espaço em disco não é liberado após a exclusão

Sintoma

O TTL excluiu um grande número de documentos, mas o uso do disco não diminuiu significativamente.

Solução

O MongoDB utiliza o mecanismo de armazenamento WiredTiger. Quando documentos são excluídos, o espaço é marcado como reutilizável, mas não é devolvido imediatamente ao sistema operacional. Para recuperar espaço em disco imediatamente, execute o comando compact ou recrie os arquivos de dados por meio de uma sincronização inicial. Recomendamos executar o compact fora dos horários de pico.

Melhores práticas

1. Garanta tipos de dados corretos

Índices TTL funcionam apenas em campos do tipo BSON Date. Recomendamos impor o tipo de data correto para campos TTL no lado da aplicação ou utilizando o recurso de Validação de Schema do MongoDB.

db.createCollection("sessions", {
  validator: {
    $jsonSchema: {
      properties: {
        expireAt: { bsonType: "date", description: "The TTL field must be of the Date type" }
      },
      required: ["expireAt"]
    }
  }
})

2. Distribua os tempos de expiração para evitar exclusões em massa

Esta é a maneira mais eficaz de prevenir picos de CPU causados por exclusões TTL. Ao inserir dados, adicione um deslocamento aleatório ao tempo de expiração para que um lote de dados expire ao longo de um intervalo de tempo. Assim, a thread TTL exclui apenas uma pequena quantidade de documentos por varredura, reduzindo significativamente o impacto no desempenho do sistema.

Nota

Para dados com longo período de retenção (como 24 horas ou mais), recomendamos adicionar um deslocamento aleatório de 0 a 10 minutos ao tempo de expiração.

3. Ajuste expireAfterSeconds com cautela

Reduzir o valor de expireAfterSeconds de um índice TTL existente faz com que muitos documentos atuais expirem imediatamente, podendo desencadear operações de exclusão em larga escala e afetar seriamente o desempenho da instância. Recomendamos o seguinte:

  1. Estime quantos documentos expirarão imediatamente após o ajuste.

  2. Faça a alteração fora dos horários de pico.

  3. Se o número de documentos expirados for grande, primeiro exclua parte dos dados em lotes usando um script e depois modifique expireAfterSeconds.

4. Considerações ao criar um novo índice TTL

Criar um índice TTL em uma coleção que já contém muitos documentos atendendo à condição de expiração pode acionar exclusões em larga escala logo após a construção do índice. Siga estas recomendações:

  • Crie o índice TTL fora dos horários de pico.

  • Limpe dados históricos expirados antes de criar o índice TTL.

  • Construa o índice em segundo plano para não afetar as operações normais do negócio.

5. Não desative o TTL Monitor por longos períodos

Embora seja possível desativar temporariamente o recurso TTL definindo o parâmetro ttlMonitorEnabled, não recomendamos mantê-lo desativado por muito tempo em ambiente de produção. O grande volume de documentos expirados acumulados durante o período de inatividade será excluído em massa quando o recurso for reativado, o que pode causar graves problemas de desempenho.

Aviso

Após desativar temporariamente o TTL Monitor, reative-o prontamente para evitar o acúmulo de dados expirados.

6. Avalie o impacto do TTL no oplog

Cada documento excluído pelo TTL gera uma entrada no oplog. Quando o volume de exclusões é alto, a escrita no oplog aumenta significativamente, podendo afetar o atraso de replicação do replica set. Recomendamos avaliar o impacto das seguintes formas:

  • Monitore metrics.ttl.deletedDocuments para acompanhar o volume de exclusões TTL.

  • Monitore o atraso de replicação do replica set para garantir que os nós Secondary consigam lidar com o oplog adicional gerado pelo TTL.

  • Aumente o tamanho do oplog se necessário para evitar overflow causado pelas exclusões TTL.

7. Alternativas para cenários de alta escrita

Índices TTL são adequados para cenários com volumes moderados de escrita. Para cenários com volumes extremamente altos, considere as seguintes alternativas:

  1. Coleções particionadas por tempo: Particione a coleção por uma dimensão temporal (como dia ou semana) e exclua (drop) a coleção inteira quando expirar. Esta é a forma mais eficiente de expirar dados.

  2. Coleções de séries temporais: O MongoDB 5.0+ suporta coleções de séries temporais, que incluem expiração de dados nativa e excluem dados em bloco por bucket. Isso é muito mais eficiente do que excluir documentos individualmente em uma coleção comum.

  3. Limpeza agendada via aplicação: Use tarefas agendadas para realizar exclusões em lote fora dos horários de pico, oferecendo controle mais preciso sobre a taxa e o momento das exclusões.

Recursos TTL por versão

Versão

Recursos

6.0+

Suporta a conversão de um índice comum de campo único para um índice TTL usando collMod, sem necessidade de excluir e recriar o índice anteriormente.

7.0+

Introduz o mecanismo de exclusão em lote (BATCHED_DELETE), melhorando a eficiência da exclusão; implementa exclusão justa para evitar que certas coleções fiquem sem limpeza; suporta índices TTL parciais para coleções de séries temporais e uma partialFilterExpression mais flexível.

Referência de parâmetros TTL

Parâmetro

Descrição

Valor padrão

ttlMonitorSleepSecs

Intervalo de varredura da thread TTL.

60 segundos

ttlMonitorEnabled

Chave para ativar/desativar o recurso TTL.

true

ttlMonitorBatchDeletes

Modo de exclusão em lote (7.0+).

true

ttlIndexDeleteTargetTimeMS

Limite máximo de tempo por rodada de exclusão (7.0+).

1000 ms

ttlIndexDeleteTargetDocs

Limite máximo de documentos excluídos por rodada (7.0+).

50000

ttlMonitorSubPassTargetSecs

Limite máximo de tempo para uma subpassagem (7.0+).

60 segundos

Resumo

Os índices TTL são um mecanismo poderoso e prático de expiração automática de dados no MongoDB, gerenciando eficazmente dados com ciclo de vida definido. Em ambientes de produção, configure-os de acordo com seu cenário de negócios para evitar problemas de desempenho. Os pontos principais são:

  1. Garanta que o campo TTL seja do tipo BSON Date. Este é o pré-requisito para o funcionamento correto dos índices TTL.

  2. Distribuir os tempos de expiração é a forma mais eficaz de evitar picos de CPU.

  3. Monitore continuamente o status do TTL (volume de exclusões, passagens de varredura, atraso do replica set).

  4. Para cenários de alta escrita, considere alternativas como coleções particionadas por tempo ou coleções de séries temporais.

  5. Atualizar para uma versão mais recente (como 7.0+) proporciona melhor desempenho e justiça nas exclusões TTL.