Minha escolha seria uma variação da abordagem 2. Negrito indica campos na chave primária.
- Você insere todos os artigos em uma tabela
articles_versioned
(código , carimbo de data e hora , nome, texto) - Sua segunda tabela é
articles
(código , carimbo de data/hora, [nome, texto]). Observe como o timestamp não é primário; nome e texto podem ser replicados, ou você pode usar uma junção comarticles_versioned
(que será rápido já que id e timestamp são osarticles_versioned
chave primária) articles_versioned
tem um gatilho na inserção que pega a linha recém inserida e a replica emarticles
- Para restaurar uma versão específica de um artigo, modifique os
articles
tabela.
As vantagens desta abordagem são:
- Você obtém gratuitamente outra informação (a data e hora do artigo) em sua tabela, que você pode precisar de qualquer maneira
- Você não precisa consultar o banco de dados para obter a data atual. Se você usa a versão, precisa.
- Seu código não precisa inserir o artigo em duas tabelas. Você simplesmente insere em
articles_versioned
e leia dearticles
, o banco de dados cuida da migração dos dados conforme você os insere por meio do gatilho, evitando problemas de consistência.
Contras
- Em um ambiente altamente concorrente, duas versões podem ser inseridas ao mesmo tempo, então uma delas pode falhar. Isso não deve ser um problema ao inserir artigos escritos por usuários (é altamente improvável, dada a precisão dos carimbos de data e hora nos dias de hoje). Se você não especificar o carimbo de data/hora em seu
INSERT
, mas, em vez de definir o campo datetime para ter a hora atual como valor padrão, você pode evitar totalmente esse problema.
Para responder ao resto da sua pergunta. A abordagem 1 não levará a consultas mais longas, desde que você adicione um índice no status. Isso só faz sentido se você tende a ter muitas versões diferentes de cada artigo; contanto que você tenha 2 versões por artigo em média ou menos, o índice só irá atrasá-lo, e a abordagem 2 não seria sensatamente mais rápida de qualquer maneira (embora eu ainda recomende minha abordagem porque ela simplifica o código, já que restaurar uma versão não não requer status de comutação para duas linhas).
Recursos relacionados, como imagens, devem seguir um versionamento semelhante. Presumo que você os esteja salvando no sistema de arquivos; em vez de salvá-los com seu nome real, use uma tabela (id , image_name) para dar a cada imagem um id e salve a imagem como
-id-.jpg
. O campo image_name permitirá que você saiba qual era o nome do arquivo original (se você se importa com isso). Dessa forma, você pode fazer a versão das imagens da mesma forma que faz a versão dos artigos, e nos artigos você usaria algo como <img src="-id-.jpg">
, que você sabe que permanecerá disponível para sempre.