Há um recurso que eu gostaria que existisse no RDBMS, que é o suporte interno para definir um valor de tempo de vida para os registros de dados. Nos bancos de dados NoSQL, o suporte de TTL é muito comum. Os bancos de dados NoSQL foram projetados para lidar com determinados tipos de dados que geralmente não são encontrados nos casos de uso tradicionais de RDBMS. Isso inclui o gerenciamento de logs e eventos, em que, não apenas devido à natureza não estruturada dos dados, mas também ao seu grande volume, o gerenciamento em RDBMS pode ser difícil e caro. É esse tipo de dados que faz com que o Time-to-Live (TTL), um recurso popular nos bancos de dados NoSQL.
Mas uma rápida pesquisa no Google sobre TTL com RDBMS tradicional retorna mais de 1 milhão de resultados, o que indica que há vários casos de uso em que os desenvolvedores gostariam de ter esse tipo de suporte em RDBMS. Estes são alguns dos casos de uso que eu vi:
- Aplicativos que geram um grande volume de dados temporários para fins de cálculo. Por exemplo, um sistema de remuneração de incentivo que permite ao administrador do plano projetar e executar análises hipotéticas para verificar a eficácia do plano. Então, quando os planos forem implementados, os dados temporários para cálculos também precisarão ser mantidos para fins de validação/consulta do usuário.
- Os sistemas de informações gerenciais geralmente precisam pré-gerar dados agregados de fontes multigeográficas, o que geralmente envolve regras complexas de conversão de moeda. O requisito para esses dados agregados geralmente é necessário apenas para o período de relatório contábil atual.
- Sistemas que incluem um processo de arquivamento automático para remover dados antigos depois que os dados forem movidos para uma mídia de armazenamento diferente.
Todos os casos de uso mencionados acima também incluiriam as etapas adicionais da exclusão real dos dados. Mas, em muitos casos, o sistema desejaria desacoplar o processo para evitar o processo potencialmente demorado de exclusão de dados em um RDBMS baseado em transações.
Aqui, o recurso Time-to-Live (TTL) permitiria que o aplicativo simplesmente definisse os registros de dados com o tempo de expiração e adiasse o DELETE real para um processo de banco de dados diferente.
Para o Couchbase, o suporte ao TTL sempre esteve disponível com Operações de valor-chave do Couchbase. Mas de Couchbase 6.5.1Agora, esse recurso está disponível com DMLs N1QL, o que permite que os usuários consultem e definam o valor de expiração diretamente nas instruções N1QL.
N1QL TTL com OPTIONS
Para dar suporte ao TTL, a sintaxe do N1QL foi ampliada com um parâmetro opcional OPTIONS.
1 2 |
INSERIR PARA padrão (CHAVE, VALOR [, OPÇÕES]) VALORES (kval, docval [, {"expiração":avaliação}]); |
Observe que o parâmetro OPTIONS é opcional para garantir a compatibilidade com versões anteriores.
INSERT/UPSERT e defina o documento para expirar em 10 minutos.
1 2 |
INSERIR PARA padrão (CHAVE, VALOR) VALORES ("k01", {"id":"k01"}, {"expiração":10*60}); UPSERT PARA padrão (CHAVE, VALOR) VALORES ("k01", {"id":"k01"}, {"expiração":10*60}); |
INSERT/UPSERT em SELECT e defina o tempo de expiração do documento como 1 hora
1 2 3 4 |
INSERIR PARA padrão (CHAVE chave, VALOR doc, OPÇÕES {"expiração": 60*60}) SELECIONAR META(t).id AS chave, t AS doc DE `viagens-amostra` AS t; UPSERT PARA padrão (CHAVE chave, VALOR doc, OPÇÕES {"expiração": 60*60}) SELECIONAR META(t).id AS chave, t AS doc DE `viagens-amostra` AS t; |
Para preservar o TTL durante a atualização/upsert
Antes do Couchbase 6.5.1, a instrução de atualização N1QL não preservará o valor existente no documento. Esse comportamento permanecerá inalterado e, se os usuários quiserem preservar o TTL, a instrução de atualização do N1QL deverá definir explicitamente a expiração com o mesmo valor.
1 |
ATUALIZAÇÃO padrão AS d CONJUNTO d.comentário = "xyz" , META(d).expiração = META(d).expiração; |
INSERIR/UPSERT no SELECT e manter o tempo de expiração do documento
1 2 3 4 |
INSERIR PARA padrão (CHAVE chave, VALOR doc, OPÇÕES {"expiração": tempo de expiração}) SELECIONAR META(t).id AS chave, t AS doc, META(t).expiração AS tempo de expiração DE `viagens-amostra` AS t; UPSERT PARA padrão (CHAVE chave, VALOR doc, OPÇÕES {"expiração": tempo de expiração}) SELECIONAR META(t).id AS chave, t AS doc, META(t).expiração AS tempo de expiração DE `viagens-amostra` AS t; |
MERGE documentos e preserva o tempo de expiração.
1 2 3 4 5 6 7 8 9 10 11 |
MERGE PARA `viagens-amostra` AS rota USO `viagens-amostra` AS aeroporto ON rota.aeroporto de origem = aeroporto.faa QUANDO COMBINADO ENTÃO ATUALIZAÇÃO CONJUNTO rota.equipamento_antigo = rota.equipamentos, rota.equipamentos = ""797"", rota.atualizado = verdadeiro, META(rota).expiração = META(rota).expiração ONDE aeroporto.país = ""França"" E rota.companhia aérea = ""BA"" E CONTÉM(rota.equipamentos, ""319"");" |
Campo META().expiration
O campo META().expiration sempre esteve disponível com o N1QL. Mas com o N1QL TTL, os usuários podem alterar diretamente o valor do campo.
Para selecionar e usar a expiração em um predicado
1 |
SELECIONAR META(d).id, META(d).expiração DE padrão d ONDE META(d).expiração > 0; |
Para atualizar todos os documentos e definir o tempo de comentário e expiração para 10 minutos.
1 |
ATUALIZAÇÃO padrão AS d CONJUNTO d.comentário = "xyz" , META(d).expiração = 10*60; |
Para limpar o tempo de expiração, para que o documento não seja excluído.
1 |
ATUALIZAÇÃO padrão AS d CONJUNTO META(d).expiração = 0; |
Para excluir todos os documentos que expirarão em mais de um dia
1 |
DELETE padrão d ONDE META(d).expiração > <extensão estilo="font-weight: 400">(NOW_MILLIS()/1000)+ (60*60*24);</extensão> |
Observe que o valor relativo é usado somente para INSERT/UPDATE/UPSERT. O valor de expiração absoluto deve ser usado em todos os outros casos.
Valor do tempo de expiração
O tempo de expiração que é inferior a 30 dias no futuro pode ser definido como o número de segundos. O valor de 60*60*24*14 marcará o documento para exclusão em 14 dias. Para 30 dias ou mais no futuro, deve ser usada a hora Unix. Para obter mais informações sobre o tempo de expiração do Couchbase, consulte a seção Documentação do Couchbase.
Criar um índice no campo de expiração
A capacidade de consultar e indexar o META().expiration sempre foi possível no Couchbase.
1 2 3 |
CRIAR ÍNDICE idx_expir ON `viagens-amostra` ( META().expiração ); SELECIONAR META().id, META().expiração DE `viagens-amostra` ONDE META().expiração = 0 ORDEM BY META().id LIMITE 2; |
Observe que pode haver um atraso entre o momento em que o documento é excluído e quando a exclusão se propaga para o serviço de índice. Por esse motivo, as consultas que são totalmente cobertas pelo índice com a expiração podem retornar dados obsoletos. Mas esse comportamento é apenas temporário.
Consideração de desempenho
N1QL acessa as informações de TTL usando o API SUBDOC Essa API retornará o documento completo e também tem alguma sobrecarga no tamanho do pacote de solicitação. A sobrecarga adicional pode incorrer em latência de consulta adicional. No entanto, a API SUBDOC só será usada se o campo META().expiration for referenciado na consulta.
Recursos adicionais
- Suporte do Couchbase para TTL: https://docs.couchbase.com/server/current/learn/buckets-memory-and-storage/expiration.html
- Como definir o tempo de expiração: https://docs.couchbase.com/server/current/learn/buckets-memory-and-storage/expiration.html
- API SUBDOC do Couchbase: https://docs.couchbase.com/server/5.0/developer-guide/sub-doc-api.html
- Indexação do campo Expiração: https://docs.couchbase.com/server/current/n1ql/n1ql-language-reference/indexing-meta-info.html